3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 oroborus - (c) 2001 Ken Lynch
18 xfwm4 - (c) 2002-2007 Olivier Fourdan
28 #include <X11/Xutil.h>
29 #include <X11/Xatom.h>
30 #include <X11/extensions/shape.h>
36 #include <libxfce4util/libxfce4util.h>
39 #include "compositor.h"
48 #include "placement.h"
54 #include "startup_notification.h"
56 #include "transients.h"
57 #include "wireframe.h"
58 #include "workspaces.h"
59 #include "event_filter.h"
61 /* Event mask definition */
63 #define POINTER_EVENT_MASK \
67 #define FRAME_EVENT_MASK \
68 SubstructureNotifyMask|\
69 SubstructureRedirectMask|\
74 #define CLIENT_EVENT_MASK \
79 #define BUTTON_EVENT_MASK \
84 #define START_ICONIC(c) \
86 (c->wmhints->initial_state == IconicState) && \
87 !clientIsValidTransientOrModal (c))
89 #define OPACITY_SET_STEP (guint) 0x16000000
90 #define OPACITY_SET_MIN (guint) 0x40000000
92 typedef struct _MoveResizeData MoveResizeData
;
93 struct _MoveResizeData
98 gboolean is_transient
;
99 gboolean move_resized
;
102 int cancel_x
, cancel_y
; /* for cancellation (either position or size) */
103 int cancel_workspace
;
111 typedef struct _ClientCycleData ClientCycleData
;
112 struct _ClientCycleData
120 typedef struct _ButtonPressData ButtonPressData
;
121 struct _ButtonPressData
129 clientUpdateIconPix (Client
* c
);
132 clientGetXDisplay (Client
* c
)
134 g_return_val_if_fail (c
, NULL
);
136 return myScreenGetXDisplay (c
->screen_info
);
140 clientInstallColormaps (Client
* c
)
142 XWindowAttributes attr
;
146 g_return_if_fail (c
!= NULL
);
147 TRACE ("entering clientInstallColormaps");
152 for (i
= c
->ncmap
- 1; i
>= 0; i
--)
154 XGetWindowAttributes (clientGetXDisplay (c
), c
->cmap_windows
[i
], &attr
);
155 XInstallColormap (clientGetXDisplay (c
), attr
.colormap
);
156 if (c
->cmap_windows
[i
] == c
->window
)
162 if ((!installed
) && (c
->cmap
))
164 XInstallColormap (clientGetXDisplay (c
), c
->cmap
);
169 clientUpdateColormaps (Client
* c
)
171 g_return_if_fail (c
!= NULL
);
172 TRACE ("entering clientUpdateColormaps");
176 XFree (c
->cmap_windows
);
179 if (!XGetWMColormapWindows (clientGetXDisplay (c
), c
->window
, &c
->cmap_windows
, &c
->ncmap
))
181 c
->cmap_windows
= NULL
;
187 clientUpdateName (Client
* c
)
189 ScreenInfo
*screen_info
;
190 DisplayInfo
*display_info
;
193 g_return_if_fail (c
!= NULL
);
194 TRACE ("entering clientUpdateName");
196 screen_info
= c
->screen_info
;
197 display_info
= screen_info
->display_info
;
199 getWindowName (display_info
, c
->window
, &name
);
204 if (strcmp (name
, c
->name
))
208 FLAG_SET (c
->flags
, CLIENT_FLAG_NAME_CHANGED
);
216 clientUpdateAllFrames (ScreenInfo
*screen_info
, int mask
)
222 g_return_if_fail (screen_info
!= NULL
);
224 TRACE ("entering clientRedrawAllFrames");
225 myScreenGrabPointer (screen_info
, EnterWindowMask
, None
, myDisplayGetCurrentTime (screen_info
->display_info
));
227 for (c
= screen_info
->clients
, i
= 0; i
< screen_info
->client_count
; c
= c
->next
, i
++)
229 unsigned long configure_flags
= 0L;
231 if (mask
& UPDATE_BUTTON_GRABS
)
233 clientUngrabButtons (c
);
234 clientGrabButtons (c
);
235 clientGrabMouseButton (c
);
237 if (mask
& UPDATE_CACHE
)
239 clientUpdateIconPix (c
);
241 if (mask
& UPDATE_GRAVITY
)
243 clientGravitate (c
, REMOVE
);
244 clientGravitate (c
, APPLY
);
245 setNetFrameExtents (screen_info
->display_info
,
251 configure_flags
|= CFG_FORCE_REDRAW
;
252 mask
&= ~UPDATE_FRAME
;
254 if (mask
& UPDATE_MAXIMIZE
)
256 unsigned long maximization_flags
= 0L;
258 /* Recompute size and position of maximized windows */
259 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
| CLIENT_FLAG_MAXIMIZED_VERT
))
261 maximization_flags
|= FLAG_TEST (c
->flags
,
262 CLIENT_FLAG_MAXIMIZED_HORIZ
) ? WIN_STATE_MAXIMIZED_HORIZ
: 0;
263 maximization_flags
|= FLAG_TEST (c
->flags
,
264 CLIENT_FLAG_MAXIMIZED_VERT
) ? WIN_STATE_MAXIMIZED_VERT
: 0;
266 /* Force an update by clearing the internal flags */
267 FLAG_UNSET (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
| CLIENT_FLAG_MAXIMIZED_VERT
);
268 clientToggleMaximized (c
, maximization_flags
, FALSE
);
270 configure_flags
|= CFG_FORCE_REDRAW
;
271 mask
&= ~UPDATE_FRAME
;
274 if (configure_flags
!= 0L)
279 wc
.height
= c
->height
;
280 clientConfigure (c
, &wc
, CWX
| CWY
| CWWidth
| CWHeight
, configure_flags
);
282 if (mask
& UPDATE_FRAME
)
288 myScreenUngrabPointer (screen_info
);
292 clientGrabButtons (Client
* c
)
294 ScreenInfo
*screen_info
;
296 g_return_if_fail (c
!= NULL
);
297 TRACE ("entering clientGrabButtons");
298 TRACE ("grabbing buttons for client \"%s\" (0x%lx)", c
->name
, c
->window
);
300 screen_info
= c
->screen_info
;
301 if (screen_info
->params
->easy_click
)
303 grabButton(clientGetXDisplay (c
), AnyButton
, screen_info
->params
->easy_click
, c
->window
);
308 clientUngrabButtons (Client
* c
)
310 g_return_if_fail (c
!= NULL
);
311 TRACE ("entering clientUngrabButtons");
312 TRACE ("grabbing buttons for client \"%s\" (0x%lx)", c
->name
, c
->window
);
314 XUngrabButton (clientGetXDisplay (c
), AnyButton
, AnyModifier
, c
->window
);
318 urgent_cb (gpointer data
)
322 TRACE ("entering urgent_cb");
325 if (c
!= clientGetFocus ())
327 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_SEEN_ACTIVE
);
328 frameDraw (c
, FALSE
);
334 clientUpdateUrgency (Client
*c
)
336 g_return_if_fail (c
!= NULL
);
338 TRACE ("entering clientUpdateUrgency");
340 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_SEEN_ACTIVE
);
341 if (c
->blink_timeout_id
)
343 g_source_remove (c
->blink_timeout_id
);
344 frameDraw (c
, FALSE
);
346 FLAG_UNSET (c
->wm_flags
, WM_FLAG_URGENT
);
348 c
->blink_timeout_id
= 0;
349 if ((c
->wmhints
) && (c
->wmhints
->flags
& XUrgencyHint
))
351 FLAG_SET (c
->wm_flags
, WM_FLAG_URGENT
);
352 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
))
354 c
->blink_timeout_id
=
355 g_timeout_add_full (G_PRIORITY_DEFAULT
,
356 CLIENT_BLINK_TIMEOUT
,
357 (GtkFunction
) urgent_cb
,
361 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_SEEN_ACTIVE
)
362 && !FLAG_TEST (c
->wm_flags
, WM_FLAG_URGENT
)
363 && (c
!= clientGetFocus ()))
365 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_SEEN_ACTIVE
);
366 frameDraw (c
, FALSE
);
371 clientCoordGravitate (Client
* c
, int mode
, int *x
, int *y
)
375 g_return_if_fail (c
!= NULL
);
376 TRACE ("entering clientCoordGravitate");
378 c
->gravity
= c
->size
->flags
& PWinGravity
? c
->size
->win_gravity
: NorthWestGravity
;
382 dx
= (c
->border_width
* 2) - ((frameLeft (c
) +
383 frameRight (c
)) / 2);
384 dy
= (c
->border_width
* 2) - ((frameTop (c
) +
385 frameBottom (c
)) / 2);
388 dx
= (c
->border_width
* 2) - ((frameLeft (c
) +
389 frameRight (c
)) / 2);
393 dx
= (c
->border_width
* 2) - ((frameLeft (c
) +
394 frameRight (c
)) / 2);
395 dy
= (c
->border_width
* 2) - frameBottom (c
);
398 dx
= (c
->border_width
* 2) - frameRight (c
);
399 dy
= (c
->border_width
* 2) - ((frameTop (c
) +
400 frameBottom (c
)) / 2);
404 dy
= (c
->border_width
* 2) - ((frameTop (c
) +
405 frameBottom (c
)) / 2);
407 case NorthWestGravity
:
411 case NorthEastGravity
:
412 dx
= (c
->border_width
* 2) - frameRight (c
);
415 case SouthWestGravity
:
417 dy
= (c
->border_width
* 2) - frameBottom (c
);
419 case SouthEastGravity
:
420 dx
= (c
->border_width
* 2) - frameRight (c
);
421 dy
= (c
->border_width
* 2) - frameBottom (c
);
428 *x
= *x
+ (dx
* mode
);
429 *y
= *y
+ (dy
* mode
);
433 clientGravitate (Client
* c
, int mode
)
437 g_return_if_fail (c
!= NULL
);
438 TRACE ("entering clientGravitate");
442 clientCoordGravitate (c
, mode
, &x
, &y
);
448 clientComputeWidth (Client
* c
, int *w
)
452 g_return_if_fail (c
!= NULL
);
453 g_return_if_fail (w
!= NULL
);
454 TRACE ("entering clientComputeWidth");
456 /* Bypass resize increment and max sizes for fullscreen */
457 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
458 && !(FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
459 && (c
->screen_info
->params
->borderless_maximize
)))
461 if ((c
->size
->flags
& PResizeInc
) && (c
->size
->width_inc
))
463 w2
= (*w
- c
->size
->min_width
) / c
->size
->width_inc
;
464 *w
= c
->size
->min_width
+ (w2
* c
->size
->width_inc
);
466 if (c
->size
->flags
& PMaxSize
)
468 if (*w
> c
->size
->max_width
)
470 *w
= c
->size
->max_width
;
475 if (c
->size
->flags
& PMinSize
)
477 if (*w
< c
->size
->min_width
)
479 *w
= c
->size
->min_width
;
489 clientSetWidth (Client
* c
, int w
)
493 g_return_if_fail (c
!= NULL
);
494 TRACE ("entering clientSetWidth");
495 TRACE ("setting width %i for client \"%s\" (0x%lx)", w
, c
->name
, c
->window
);
498 clientComputeWidth (c
, &temp
);
503 clientComputeHeight (Client
* c
, int *h
)
507 g_return_if_fail (c
!= NULL
);
508 TRACE ("entering clientComputeHeight");
510 /* Bypass resize increment and max sizes for fullscreen */
511 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
)
512 && !(FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
513 && (c
->screen_info
->params
->borderless_maximize
)))
515 if ((c
->size
->flags
& PResizeInc
) && (c
->size
->height_inc
))
517 h2
= (*h
- c
->size
->min_height
) / c
->size
->height_inc
;
518 *h
= c
->size
->min_height
+ (h2
* c
->size
->height_inc
);
520 if (c
->size
->flags
& PMaxSize
)
522 if (*h
> c
->size
->max_height
)
524 *h
= c
->size
->max_height
;
529 if (c
->size
->flags
& PMinSize
)
531 if (*h
< c
->size
->min_height
)
533 *h
= c
->size
->min_height
;
543 clientSetHeight (Client
* c
, int h
)
547 g_return_if_fail (c
!= NULL
);
548 TRACE ("entering clientSetHeight");
549 TRACE ("setting height %i for client \"%s\" (0x%lx)", h
, c
->name
, c
->window
);
552 clientComputeHeight (c
, &temp
);
556 /* clientConstrainRatio - adjust the given width and height to account for
557 the constraints imposed by size hints
559 The aspect ratio stuff, is borrowed from uwm's CheckConsistency routine.
562 #define MAKE_MULT(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
564 clientConstrainRatio (Client
* c
, int *w
, int *h
, int corner
)
567 g_return_if_fail (c
!= NULL
);
568 TRACE ("entering clientConstrainRatio");
569 TRACE ("client \"%s\" (0x%lx)", c
->name
, c
->window
);
571 if (c
->size
->flags
& PAspect
)
573 int xinc
, yinc
, minx
, miny
, maxx
, maxy
, delta
;
575 xinc
= c
->size
->width_inc
;
576 yinc
= c
->size
->height_inc
;
577 minx
= c
->size
->min_aspect
.x
;
578 miny
= c
->size
->min_aspect
.y
;
579 maxx
= c
->size
->max_aspect
.x
;
580 maxy
= c
->size
->max_aspect
.y
;
582 if ((minx
* *h
> miny
* *w
) && (miny
) &&
583 ((corner
== CORNER_COUNT
+ SIDE_TOP
) || (corner
== CORNER_COUNT
+ SIDE_BOTTOM
)))
585 /* Change width to match */
586 delta
= MAKE_MULT (minx
* *h
/ miny
- *w
, xinc
);
587 if (!(c
->size
->flags
& PMaxSize
) ||
588 (*w
+ delta
<= c
->size
->max_width
))
593 if ((minx
* *h
> miny
* *w
) && (minx
))
595 delta
= MAKE_MULT (*h
- *w
* miny
/ minx
, yinc
);
596 if (!(c
->size
->flags
& PMinSize
) ||
597 (*h
- delta
>= c
->size
->min_height
))
603 delta
= MAKE_MULT (minx
* *h
/ miny
- *w
, xinc
);
604 if (!(c
->size
->flags
& PMaxSize
) ||
605 (*w
+ delta
<= c
->size
->max_width
))
610 if ((maxx
* *h
< maxy
* *w
) && (maxx
) &&
611 ((corner
== CORNER_COUNT
+ SIDE_LEFT
) || (corner
== CORNER_COUNT
+ SIDE_RIGHT
)))
613 delta
= MAKE_MULT (*w
* maxy
/ maxx
- *h
, yinc
);
614 if (!(c
->size
->flags
& PMaxSize
) ||
615 (*h
+ delta
<= c
->size
->max_height
))
620 if ((maxx
* *h
< maxy
* *w
) && (maxy
))
622 delta
= MAKE_MULT (*w
- maxx
* *h
/ maxy
, xinc
);
623 if (!(c
->size
->flags
& PMinSize
) ||
624 (*w
- delta
>= c
->size
->min_width
))
630 delta
= MAKE_MULT (*w
* maxy
/ maxx
- *h
, yinc
);
631 if (!(c
->size
->flags
& PMaxSize
) ||
632 (*h
+ delta
<= c
->size
->max_height
))
641 #define WIN_MOVED (mask & (CWX | CWY))
642 #define WIN_RESIZED (mask & (CWWidth | CWHeight))
645 clientConfigureWindows (Client
* c
, XWindowChanges
* wc
, unsigned long mask
, unsigned short flags
)
647 unsigned long change_mask
;
648 XWindowChanges change_values
;
650 change_mask
= (mask
& (CWX
| CWY
| CWWidth
| CWHeight
));
651 if (flags
& CFG_FORCE_REDRAW
)
653 change_mask
|= (CWX
| CWY
);
656 if (change_mask
& (CWX
| CWY
| CWWidth
| CWHeight
))
658 change_values
.x
= frameX (c
);
659 change_values
.y
= frameY (c
);
660 change_values
.width
= frameWidth (c
);
661 change_values
.height
= frameHeight (c
);
662 XConfigureWindow (clientGetXDisplay (c
), c
->frame
, change_mask
, &change_values
);
664 if (WIN_RESIZED
|| (flags
& CFG_FORCE_REDRAW
))
666 frameDraw (c
, (flags
& CFG_FORCE_REDRAW
));
669 change_values
.x
= frameLeft (c
);
670 change_values
.y
= frameTop (c
);
671 change_values
.width
= c
->width
;
672 change_values
.height
= c
->height
;
673 XConfigureWindow (clientGetXDisplay (c
), c
->window
, change_mask
, &change_values
);
678 clientConfigure (Client
* c
, XWindowChanges
* wc
, unsigned long mask
, unsigned short flags
)
681 int px
, py
, pwidth
, pheight
;
683 g_return_if_fail (c
!= NULL
);
684 g_return_if_fail (c
->window
!= None
);
686 TRACE ("entering clientConfigure");
687 TRACE ("configuring client \"%s\" (0x%lx) %s, type %u", c
->name
,
688 c
->window
, flags
& CFG_CONSTRAINED
? "constrained" : "not contrained", c
->type
);
692 if (!FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
))
699 if (!FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
))
706 clientSetWidth (c
, wc
->width
);
710 clientSetHeight (c
, wc
->height
);
712 if (mask
& CWBorderWidth
)
714 c
->border_width
= wc
->border_width
;
716 if (mask
& CWStackMode
)
718 switch (wc
->stack_mode
)
721 * Limitation: we don't support neither
722 * TopIf, BottomIf nor Opposite ...
726 if (mask
& CWSibling
)
728 clientRaise (c
, wc
->sibling
);
732 clientRaise (c
, None
);
737 if (mask
& CWSibling
)
739 clientLower (c
, wc
->sibling
);
743 clientLower (c
, None
);
754 mask
&= ~(CWStackMode
| CWSibling
);
756 /* Keep control over what the application does. However, some broken apps try
757 to achieve fullscreen by using static gravity and a (0,0) position, the
758 second part of the test is for this case.
760 if (((flags
& (CFG_CONSTRAINED
| CFG_REQUEST
)) == (CFG_CONSTRAINED
| CFG_REQUEST
))
761 && CONSTRAINED_WINDOW (c
)
762 && !((c
->gravity
== StaticGravity
) && (c
->x
== 0) && (c
->y
== 0)))
769 /* Keep fully visible only on resize */
770 clientConstrainPos (c
, (mask
& (CWWidth
| CWHeight
)));
781 if (c
->width
!= pwidth
)
785 if (c
->height
!= pheight
)
791 clientConfigureWindows (c
, wc
, mask
, flags
);
794 We reparent to client window. According to the ICCCM spec, the
795 WM must send a senthetic event when the window is moved and not resized.
797 But, since we reparent the window, we must also send a synthetic
798 configure event when the window is moved and resized.
800 See this thread for the rational:
801 http://www.mail-archive.com/wm-spec-list@gnome.org/msg00379.html
803 And specifically this post from Carsten Haitzler:
804 http://www.mail-archive.com/wm-spec-list@gnome.org/msg00382.html
807 if ((WIN_MOVED
) || (flags
& CFG_NOTIFY
) ||
808 ((flags
& CFG_REQUEST
) && !(WIN_MOVED
|| WIN_RESIZED
)))
810 DBG ("Sending ConfigureNotify");
811 ce
.type
= ConfigureNotify
;
812 ce
.display
= clientGetXDisplay (c
);
813 ce
.event
= c
->window
;
814 ce
.window
= c
->window
;
818 ce
.height
= c
->height
;
821 ce
.override_redirect
= FALSE
;
822 XSendEvent (clientGetXDisplay (c
), c
->window
, FALSE
,
823 StructureNotifyMask
, (XEvent
*) & ce
);
830 clientGetMWMHints (Client
* c
, gboolean update
)
832 ScreenInfo
*screen_info
;
833 DisplayInfo
*display_info
;
834 PropMwmHints
*mwm_hints
;
837 g_return_if_fail (c
!= NULL
);
838 g_return_if_fail (c
->window
!= None
);
840 TRACE ("entering clientGetMWMHints client \"%s\" (0x%lx)", c
->name
,
843 screen_info
= c
->screen_info
;
844 display_info
= screen_info
->display_info
;
846 mwm_hints
= getMotifHints (display_info
, c
->window
);
849 if ((mwm_hints
->flags
& MWM_HINTS_DECORATIONS
))
851 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_HAS_SHAPE
))
853 if (mwm_hints
->decorations
& MWM_DECOR_ALL
)
855 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
| XFWM_FLAG_HAS_MENU
);
859 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
| XFWM_FLAG_HAS_MENU
);
860 FLAG_SET (c
->xfwm_flags
, (mwm_hints
-> decorations
& (MWM_DECOR_TITLE
| MWM_DECOR_BORDER
))
861 ? XFWM_FLAG_HAS_BORDER
: 0);
862 FLAG_SET (c
->xfwm_flags
, (mwm_hints
->decorations
& (MWM_DECOR_MENU
))
863 ? XFWM_FLAG_HAS_MENU
: 0);
865 FLAG_UNSET(c->xfwm_flags, XFWM_FLAG_HAS_HIDE);
866 FLAG_UNSET(c->xfwm_flags, XFWM_FLAG_HAS_MAXIMIZE);
867 FLAG_SET(c->xfwm_flags, (mwm_hints->decorations & (MWM_DECOR_MINIMIZE)) ? XFWM_FLAG_HAS_HIDE : 0);
868 FLAG_SET(c->xfwm_flags, (mwm_hints->decorations & (MWM_DECOR_MAXIMIZE)) ? XFWM_FLAG_HAS_MAXIMIZE : 0);
873 /* The following is from Metacity : */
874 if (mwm_hints
->flags
& MWM_HINTS_FUNCTIONS
)
876 if (!(mwm_hints
->functions
& MWM_FUNC_ALL
))
878 FLAG_UNSET (c
->xfwm_flags
,
879 XFWM_FLAG_HAS_CLOSE
| XFWM_FLAG_HAS_HIDE
|
880 XFWM_FLAG_HAS_MAXIMIZE
| XFWM_FLAG_HAS_MOVE
|
881 XFWM_FLAG_HAS_RESIZE
);
885 FLAG_SET (c
->xfwm_flags
,
886 XFWM_FLAG_HAS_CLOSE
| XFWM_FLAG_HAS_HIDE
|
887 XFWM_FLAG_HAS_MAXIMIZE
| XFWM_FLAG_HAS_MOVE
|
888 XFWM_FLAG_HAS_RESIZE
);
891 if (mwm_hints
->functions
& MWM_FUNC_CLOSE
)
893 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_HAS_CLOSE
);
895 if (mwm_hints
->functions
& MWM_FUNC_MINIMIZE
)
897 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_HAS_HIDE
);
899 if (mwm_hints
->functions
& MWM_FUNC_MAXIMIZE
)
901 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
);
903 if (mwm_hints
->functions
& MWM_FUNC_RESIZE
)
905 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_HAS_RESIZE
);
907 if (mwm_hints
->functions
& MWM_FUNC_MOVE
)
909 FLAG_TOGGLE (c
->xfwm_flags
, XFWM_FLAG_HAS_MOVE
);
917 if (FLAG_TEST_ALL(c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
| XFWM_FLAG_LEGACY_FULLSCREEN
)
918 && !FLAG_TEST(c
->flags
, CLIENT_FLAG_FULLSCREEN
))
920 /* legacy app changed its decoration, put it back on regular layer */
921 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_LEGACY_FULLSCREEN
);
922 clientSetLayer (c
, WIN_LAYER_NORMAL
);
927 wc
.height
= c
->height
;
928 clientConfigure (c
, &wc
, CWX
| CWY
| CWWidth
| CWHeight
, CFG_FORCE_REDRAW
);
930 /* MWM hints can add or remove decorations, update NET_FRAME_EXTENTS accordingly */
931 setNetFrameExtents (display_info
,
941 clientGetWMNormalHints (Client
* c
, gboolean update
)
944 unsigned long previous_value
;
947 g_return_if_fail (c
!= NULL
);
948 g_return_if_fail (c
->window
!= None
);
950 TRACE ("entering clientGetWMNormalHints client \"%s\" (0x%lx)", c
->name
,
955 c
->size
= XAllocSizeHints ();
960 if (!XGetWMNormalHints (clientGetXDisplay (c
), c
->window
, c
->size
, &dummy
))
965 previous_value
= FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_IS_RESIZABLE
);
966 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_IS_RESIZABLE
);
971 wc
.height
= c
->height
;
973 if (!(c
->size
->flags
& PMaxSize
))
975 c
->size
->max_width
= G_MAXINT
;
976 c
->size
->max_height
= G_MAXINT
;
977 c
->size
->flags
|= PMaxSize
;
980 if (!(c
->size
->flags
& PBaseSize
))
982 c
->size
->base_width
= 0;
983 c
->size
->base_height
= 0;
986 if (!(c
->size
->flags
& PMinSize
))
988 if ((c
->size
->flags
& PBaseSize
))
990 c
->size
->min_width
= c
->size
->base_width
;
991 c
->size
->min_height
= c
->size
->base_height
;
995 c
->size
->min_width
= 1;
996 c
->size
->min_height
= 1;
998 c
->size
->flags
|= PMinSize
;
1001 if (c
->size
->flags
& PResizeInc
)
1003 if (c
->size
->width_inc
< 1)
1005 c
->size
->width_inc
= 1;
1007 if (c
->size
->height_inc
< 1)
1009 c
->size
->height_inc
= 1;
1014 c
->size
->width_inc
= 1;
1015 c
->size
->height_inc
= 1;
1018 if (c
->size
->flags
& PAspect
)
1020 if (c
->size
->min_aspect
.x
< 1)
1022 c
->size
->min_aspect
.x
= 1;
1024 if (c
->size
->min_aspect
.y
< 1)
1026 c
->size
->min_aspect
.y
= 1;
1028 if (c
->size
->max_aspect
.x
< 1)
1030 c
->size
->max_aspect
.x
= 1;
1032 if (c
->size
->max_aspect
.y
< 1)
1034 c
->size
->max_aspect
.y
= 1;
1039 c
->size
->min_aspect
.x
= 1;
1040 c
->size
->min_aspect
.y
= 1;
1041 c
->size
->max_aspect
.x
= G_MAXINT
;
1042 c
->size
->max_aspect
.y
= G_MAXINT
;
1045 if (c
->size
->min_width
< 1)
1047 c
->size
->min_width
= 1;
1049 if (c
->size
->min_height
< 1)
1051 c
->size
->min_height
= 1;
1053 if (c
->size
->max_width
< 1)
1055 c
->size
->max_width
= 1;
1057 if (c
->size
->max_height
< 1)
1059 c
->size
->max_height
= 1;
1061 if (wc
.width
> c
->size
->max_width
)
1063 wc
.width
= c
->size
->max_width
;
1065 if (wc
.height
> c
->size
->max_height
)
1067 wc
.height
= c
->size
->max_height
;
1069 if (wc
.width
< c
->size
->min_width
)
1071 wc
.width
= c
->size
->min_width
;
1073 if (wc
.height
< c
->size
->min_height
)
1075 wc
.height
= c
->size
->min_height
;
1078 if ((c
->size
->min_width
< c
->size
->max_width
) ||
1079 (c
->size
->min_height
< c
->size
->max_height
))
1081 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_IS_RESIZABLE
);
1086 if ((c
->width
!= wc
.width
) || (c
->height
!= wc
.height
))
1088 clientConfigure (c
, &wc
, CWX
| CWY
| CWWidth
| CWHeight
, CFG_CONSTRAINED
);
1090 else if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_IS_RESIZABLE
) != previous_value
)
1097 c
->width
= wc
.width
;
1098 c
->height
= wc
.height
;
1103 clientGetWMProtocols (Client
* c
)
1105 ScreenInfo
*screen_info
;
1106 DisplayInfo
*display_info
;
1107 unsigned int wm_protocols_flags
;
1109 g_return_if_fail (c
!= NULL
);
1110 g_return_if_fail (c
->window
!= None
);
1112 TRACE ("entering clientGetWMProtocols client \"%s\" (0x%lx)", c
->name
,
1115 screen_info
= c
->screen_info
;
1116 display_info
= screen_info
->display_info
;
1118 wm_protocols_flags
= getWMProtocols (display_info
, c
->window
);
1119 FLAG_SET (c
->wm_flags
,
1120 (wm_protocols_flags
& WM_PROTOCOLS_DELETE_WINDOW
) ?
1121 WM_FLAG_DELETE
: 0);
1122 FLAG_SET (c
->wm_flags
,
1123 (wm_protocols_flags
& WM_PROTOCOLS_TAKE_FOCUS
) ?
1124 WM_FLAG_TAKEFOCUS
: 0);
1126 FLAG_SET (c
->wm_flags
,
1127 (wm_protocols_flags
& WM_PROTOCOLS_CONTEXT_HELP
) ?
1128 WM_FLAG_CONTEXT_HELP
: 0);
1133 clientIncrementXSyncValue (Client
*c
)
1138 g_return_if_fail (c
!= NULL
);
1139 g_return_if_fail (c
->xsync_counter
!= None
);
1141 TRACE ("entering clientIncrementXSyncValue");
1143 XSyncIntToValue (&add
, 1);
1144 XSyncValueAdd (&c
->xsync_value
, c
->xsync_value
, add
, &overflow
);
1148 clientCreateXSyncAlarm (Client
*c
)
1150 ScreenInfo
*screen_info
;
1151 DisplayInfo
*display_info
;
1152 XSyncAlarmAttributes values
;
1154 g_return_val_if_fail (c
!= NULL
, FALSE
);
1155 g_return_val_if_fail (c
->xsync_counter
!= None
, FALSE
);
1157 TRACE ("entering clientCreateXSyncAlarm");
1159 screen_info
= c
->screen_info
;
1160 display_info
= screen_info
->display_info
;
1162 XSyncIntToValue (&c
->xsync_value
, 0);
1163 XSyncSetCounter (display_info
->dpy
, c
->xsync_counter
, c
->xsync_value
);
1164 XSyncIntToValue (&values
.trigger
.wait_value
, 1);
1165 XSyncIntToValue (&values
.delta
, 1);
1167 values
.trigger
.counter
= c
->xsync_counter
;
1168 values
.trigger
.value_type
= XSyncAbsolute
;
1169 values
.trigger
.test_type
= XSyncPositiveComparison
;
1170 values
.events
= True
;
1172 c
->xsync_alarm
= XSyncCreateAlarm (display_info
->dpy
,
1180 return (c
->xsync_alarm
!= None
);
1184 clientDestroyXSyncAlarm (Client
*c
)
1186 ScreenInfo
*screen_info
;
1187 DisplayInfo
*display_info
;
1189 g_return_if_fail (c
!= NULL
);
1190 g_return_if_fail (c
->xsync_alarm
!= None
);
1192 TRACE ("entering clientClearXSyncAlarm");
1194 screen_info
= c
->screen_info
;
1195 display_info
= screen_info
->display_info
;
1197 XSyncDestroyAlarm (display_info
->dpy
, c
->xsync_alarm
);
1198 c
->xsync_alarm
= None
;
1202 clientXSyncClearTimeout (Client
* c
)
1204 g_return_if_fail (c
!= NULL
);
1206 TRACE ("entering clientXSyncClearTimeout");
1208 if (c
->xsync_timeout_id
)
1210 g_source_remove (c
->xsync_timeout_id
);
1211 c
->xsync_timeout_id
= 0;
1216 clientXSyncTimeout (gpointer data
)
1221 TRACE ("entering clientXSyncTimeout");
1223 c
= (Client
*) data
;
1226 TRACE ("XSync timeout for client \"%s\" (0x%lx)", c
->name
, c
->window
);
1227 clientXSyncClearTimeout (c
);
1228 c
->xsync_waiting
= FALSE
;
1229 c
->xsync_enabled
= FALSE
;
1233 wc
.width
= c
->width
;
1234 wc
.height
= c
->height
;
1235 clientConfigure (c
, &wc
, CWX
| CWY
| CWWidth
| CWHeight
, NO_CFG_FLAG
);
1241 clientXSyncResetTimeout (Client
* c
)
1243 g_return_if_fail (c
!= NULL
);
1245 TRACE ("entering clientXSyncResetTimeout");
1247 clientXSyncClearTimeout (c
);
1248 c
->xsync_timeout_id
= g_timeout_add_full (G_PRIORITY_DEFAULT
,
1249 CLIENT_XSYNC_TIMEOUT
,
1250 (GtkFunction
) clientXSyncTimeout
,
1251 (gpointer
) c
, NULL
);
1255 clientXSyncRequest (Client
* c
)
1257 ScreenInfo
*screen_info
;
1258 DisplayInfo
*display_info
;
1260 g_return_if_fail (c
!= NULL
);
1261 g_return_if_fail (c
->window
!= None
);
1263 TRACE ("entering clientXSyncRequest");
1265 screen_info
= c
->screen_info
;
1266 display_info
= screen_info
->display_info
;
1268 clientIncrementXSyncValue (c
);
1269 sendXSyncRequest (display_info
, c
->window
, c
->xsync_value
);
1270 clientXSyncResetTimeout (c
);
1271 c
->xsync_waiting
= TRUE
;
1275 clientXSyncEnable (Client
* c
)
1277 ScreenInfo
*screen_info
;
1278 DisplayInfo
*display_info
;
1280 g_return_val_if_fail (c
!= NULL
, FALSE
);
1282 TRACE ("entering clientXSyncEnable");
1284 screen_info
= c
->screen_info
;
1285 display_info
= screen_info
->display_info
;
1287 c
->xsync_enabled
= FALSE
;
1288 if (display_info
->have_xsync
)
1290 if ((c
->xsync_counter
) && (c
->xsync_alarm
))
1292 c
->xsync_enabled
= TRUE
;
1295 return (c
->xsync_enabled
);
1297 #endif /* HAVE_XSYNC */
1300 clientFree (Client
* c
)
1302 g_return_if_fail (c
!= NULL
);
1304 TRACE ("entering clientFree");
1305 TRACE ("freeing client \"%s\" (0x%lx)", c
->name
, c
->window
);
1307 clientClearFocus (c
);
1308 if (clientGetLastRaise (c
->screen_info
) == c
)
1310 clientClearLastRaise (c
->screen_info
);
1312 if (clientGetLastUngrab () == c
)
1314 clientClearLastUngrab ();
1316 if (clientGetDelayedFocus () == c
)
1318 clientClearDelayedFocus ();
1320 if (c
->blink_timeout_id
)
1322 g_source_remove (c
->blink_timeout_id
);
1324 if (c
->icon_timeout_id
)
1326 g_source_remove (c
->icon_timeout_id
);
1328 if (c
->frame_timeout_id
)
1330 g_source_remove (c
->frame_timeout_id
);
1337 if (c
->xsync_alarm
!= None
)
1339 clientDestroyXSyncAlarm (c
);
1341 if (c
->xsync_timeout_id
)
1343 g_source_remove (c
->xsync_timeout_id
);
1345 #endif /* HAVE_XSYNC */
1346 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
1349 g_free (c
->startup_id
);
1351 #endif /* HAVE_LIBSTARTUP_NOTIFICATION */
1360 if ((c
->ncmap
> 0) && (c
->cmap_windows
))
1362 XFree (c
->cmap_windows
);
1364 if (c
->class.res_name
)
1366 XFree (c
->class.res_name
);
1368 if (c
->class.res_class
)
1370 XFree (c
->class.res_class
);
1377 clientGetWinState (Client
* c
)
1379 g_return_if_fail (c
!= NULL
);
1381 TRACE ("entering clientGetWinState");
1383 if (c
->win_state
& WIN_STATE_STICKY
)
1385 if (!clientIsValidTransientOrModal (c
))
1387 FLAG_SET (c
->flags
, CLIENT_FLAG_STICKY
);
1390 if (c
->win_state
& WIN_STATE_SHADED
)
1392 FLAG_SET (c
->flags
, CLIENT_FLAG_SHADED
);
1394 if (c
->win_state
& WIN_STATE_MAXIMIZED_HORIZ
)
1396 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
))
1398 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
);
1401 if (c
->win_state
& WIN_STATE_MAXIMIZED_VERT
)
1403 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
))
1405 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED_VERT
);
1408 if (c
->win_state
& WIN_STATE_MAXIMIZED
)
1410 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
))
1412 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED
);
1418 clientApplyInitialState (Client
* c
)
1420 g_return_if_fail (c
!= NULL
);
1422 TRACE ("entering clientApplyInitialState");
1424 /* We check that afterwards to make sure all states are now known */
1425 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED
))
1427 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
))
1429 unsigned long mode
= 0;
1431 TRACE ("Applying client's initial state: maximized");
1432 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
))
1434 TRACE ("initial state: maximized horiz.");
1435 mode
|= WIN_STATE_MAXIMIZED_HORIZ
;
1437 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_VERT
))
1439 TRACE ("initial state: maximized vert.");
1440 mode
|= WIN_STATE_MAXIMIZED_VERT
;
1442 /* Unset fullscreen mode so that clientToggleMaximized() really change the state */
1443 FLAG_UNSET (c
->flags
, CLIENT_FLAG_MAXIMIZED
);
1444 clientToggleMaximized (c
, mode
, FALSE
);
1447 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
1449 if (!clientIsValidTransientOrModal (c
))
1451 TRACE ("Applying client's initial state: fullscreen");
1452 clientUpdateFullscreenState (c
);
1455 if (FLAG_TEST_AND_NOT (c
->flags
, CLIENT_FLAG_ABOVE
, CLIENT_FLAG_BELOW
))
1457 TRACE ("Applying client's initial state: above");
1458 clientUpdateAboveState (c
);
1460 if (FLAG_TEST_AND_NOT (c
->flags
, CLIENT_FLAG_BELOW
, CLIENT_FLAG_ABOVE
))
1462 TRACE ("Applying client's initial state: below");
1463 clientUpdateBelowState (c
);
1465 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_STICKY
) &&
1466 FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_STICK
))
1468 if (!clientIsValidTransientOrModal (c
))
1470 TRACE ("Applying client's initial state: sticky");
1471 clientStick (c
, TRUE
);
1474 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
1476 TRACE ("Applying client's initial state: shaded");
1482 clientUpdateWinState (Client
* c
, XClientMessageEvent
* ev
)
1484 unsigned long action
;
1487 g_return_if_fail (c
!= NULL
);
1488 TRACE ("entering clientUpdateWinState");
1489 TRACE ("client \"%s\" (0x%lx)", c
->name
, c
->window
);
1491 action
= ((XEvent
*) ev
)->xclient
.data
.l
[0];
1492 add_remove
= ((XEvent
*) ev
)->xclient
.data
.l
[1];
1494 if (action
& WIN_STATE_SHADED
)
1496 TRACE ("client \"%s\" (0x%lx) has received a win_state/shade event",
1497 c
->name
, c
->window
);
1498 if (add_remove
== WIN_STATE_SHADED
)
1507 else if ((action
& WIN_STATE_STICKY
)
1508 && FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_STICK
))
1510 TRACE ("client \"%s\" (0x%lx) has received a win_state/stick event",
1511 c
->name
, c
->window
);
1512 if (!clientIsValidTransientOrModal (c
))
1514 if (add_remove
== WIN_STATE_STICKY
)
1516 clientStick (c
, TRUE
);
1520 clientUnstick (c
, TRUE
);
1522 frameDraw (c
, FALSE
);
1525 else if ((action
& WIN_STATE_MAXIMIZED
)
1526 && FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_MAXIMIZE
))
1528 TRACE ("client \"%s\" (0x%lx) has received a win_state/maximize event",
1529 c
->name
, c
->window
);
1530 clientToggleMaximized (c
, add_remove
, TRUE
);
1535 clientCheckShape (Client
* c
)
1537 ScreenInfo
*screen_info
;
1538 DisplayInfo
*display_info
;
1539 int xws
, yws
, xbs
, ybs
;
1540 unsigned wws
, hws
, wbs
, hbs
;
1541 int boundingShaped
, clipShaped
;
1543 g_return_val_if_fail (c
!= NULL
, FALSE
);
1545 screen_info
= c
->screen_info
;
1546 display_info
= screen_info
->display_info
;
1548 if (display_info
->have_shape
)
1550 XShapeQueryExtents (display_info
->dpy
, c
->window
, &boundingShaped
, &xws
, &yws
, &wws
,
1551 &hws
, &clipShaped
, &xbs
, &ybs
, &wbs
, &hbs
);
1552 return (boundingShaped
!= 0);
1558 clientGetUserTime (Client
* c
)
1560 ScreenInfo
*screen_info
;
1561 DisplayInfo
*display_info
;
1563 g_return_if_fail (c
!= NULL
);
1564 g_return_if_fail (c
->window
!= None
);
1566 screen_info
= c
->screen_info
;
1567 display_info
= screen_info
->display_info
;
1569 if (getNetWMUserTime (display_info
, c
->window
, &c
->user_time
))
1571 FLAG_SET (c
->flags
, CLIENT_FLAG_HAS_USER_TIME
);
1572 myDisplaySetLastUserTime (display_info
, c
->user_time
);
1577 clientUpdateIconPix (Client
* c
)
1579 ScreenInfo
*screen_info
;
1580 DisplayInfo
*display_info
;
1585 g_return_if_fail (c
!= NULL
);
1586 g_return_if_fail (c
->window
!= None
);
1588 TRACE ("entering clientUpdateIconPix for \"%s\" (0x%lx)", c
->name
, c
->window
);
1590 screen_info
= c
->screen_info
;
1591 display_info
= screen_info
->display_info
;
1593 for (i
= 0; i
< STATE_TOGGLED
; i
++)
1595 xfwmPixmapFree (&c
->appmenu
[i
]);
1598 if (xfwmPixmapNone(&screen_info
->buttons
[MENU_BUTTON
][ACTIVE
]))
1600 /* The current theme has no menu button */
1604 for (i
= 0; i
< STATE_TOGGLED
; i
++)
1606 if (!xfwmPixmapNone(&screen_info
->buttons
[MENU_BUTTON
][i
]))
1608 xfwmPixmapDuplicate (&screen_info
->buttons
[MENU_BUTTON
][i
], &c
->appmenu
[i
]);
1611 size
= MIN (screen_info
->buttons
[MENU_BUTTON
][ACTIVE
].width
,
1612 screen_info
->buttons
[MENU_BUTTON
][ACTIVE
].height
);
1616 icon
= getAppIcon (display_info
, c
->window
, size
, size
);
1618 for (i
= 0; i
< STATE_TOGGLED
; i
++)
1620 if (!xfwmPixmapNone(&c
->appmenu
[i
]))
1622 xfwmPixmapRenderGdkPixbuf (&c
->appmenu
[i
], icon
);
1625 g_object_unref (icon
);
1630 update_icon_idle_cb (gpointer data
)
1634 TRACE ("entering update_icon_idle_cb");
1636 c
= (Client
*) data
;
1637 g_return_val_if_fail (c
, FALSE
);
1639 clientUpdateIconPix (c
);
1640 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
))
1642 frameDraw (c
, FALSE
);
1644 c
->icon_timeout_id
= 0;
1650 clientUpdateIcon (Client
* c
)
1652 g_return_if_fail (c
);
1654 TRACE ("entering clientUpdateIcon for \"%s\" (0x%lx)", c
->name
, c
->window
);
1656 if (c
->icon_timeout_id
== 0)
1658 c
->icon_timeout_id
= g_idle_add_full (G_PRIORITY_DEFAULT_IDLE
,
1659 update_icon_idle_cb
, c
, NULL
);
1664 clientFrame (DisplayInfo
*display_info
, Window w
, gboolean recapture
)
1666 ScreenInfo
*screen_info
;
1667 XWindowAttributes attr
;
1669 XSetWindowAttributes attributes
;
1673 unsigned long valuemask
;
1676 g_return_val_if_fail (w
!= None
, NULL
);
1677 g_return_val_if_fail (display_info
!= NULL
, NULL
);
1679 TRACE ("entering clientFrame");
1680 TRACE ("framing client (0x%lx)", w
);
1682 gdk_error_trap_push ();
1683 myDisplayGrabServer (display_info
);
1685 if (!XGetWindowAttributes (display_info
->dpy
, w
, &attr
))
1687 TRACE ("Cannot get window attributes");
1688 myDisplayUngrabServer (display_info
);
1689 gdk_error_trap_pop ();
1693 screen_info
= myDisplayGetScreenFromRoot (display_info
, attr
.root
);
1696 TRACE ("Cannot determine screen info from windows");
1697 myDisplayUngrabServer (display_info
);
1698 gdk_error_trap_pop ();
1702 if (w
== screen_info
->xfwm4_win
)
1704 TRACE ("Not managing our own event window");
1705 compositorAddWindow (display_info
, w
, NULL
);
1706 myDisplayUngrabServer (display_info
);
1707 gdk_error_trap_pop ();
1711 #ifdef ENABLE_KDE_SYSTRAY_PROXY
1712 if (checkKdeSystrayWindow (display_info
, w
))
1714 TRACE ("Detected KDE systray windows");
1715 if (screen_info
->systray
!= None
)
1717 sendSystrayReqDock (display_info
, w
, screen_info
->systray
);
1718 myDisplayUngrabServer (display_info
);
1719 gdk_error_trap_pop ();
1722 TRACE ("No systray found for this screen");
1724 #endif /* ENABLE_KDE_SYSTRAY_PROXY */
1726 if (attr
.override_redirect
)
1728 TRACE ("Override redirect window 0x%lx", w
);
1729 compositorAddWindow (display_info
, w
, NULL
);
1730 myDisplayUngrabServer (display_info
);
1731 gdk_error_trap_pop ();
1735 c
= g_new0 (Client
, 1);
1738 TRACE ("Cannot allocate memory for the window structure");
1739 myDisplayUngrabServer (display_info
);
1740 gdk_error_trap_pop ();
1745 c
->screen_info
= screen_info
;
1746 c
->serial
= screen_info
->client_serial
++;
1748 getWindowName (display_info
, c
->window
, &c
->name
);
1749 TRACE ("name \"%s\"", c
->name
);
1750 getTransientFor (display_info
, screen_info
->xroot
, c
->window
, &c
->transient_for
);
1752 /* Initialize structure */
1756 c
->xfwm_flags
= CLIENT_FLAG_INITIAL_VALUES
;
1759 c
->width
= attr
.width
;
1760 c
->height
= attr
.height
;
1762 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
1763 c
->startup_id
= NULL
;
1764 #endif /* HAVE_LIBSTARTUP_NOTIFICATION */
1767 c
->xsync_waiting
= FALSE
;
1768 c
->xsync_enabled
= FALSE
;
1769 c
->xsync_counter
= None
;
1770 c
->xsync_alarm
= None
;
1771 c
->xsync_timeout_id
= 0;
1772 if (display_info
->have_xsync
)
1774 getXSyncCounter (display_info
, c
->window
, &c
->xsync_counter
);
1775 if ((c
->xsync_counter
) && clientCreateXSyncAlarm (c
))
1777 c
->xsync_enabled
= TRUE
;
1780 #endif /* HAVE_XSYNC */
1782 clientGetWMNormalHints (c
, FALSE
);
1786 c
->size
->width
= c
->width
;
1787 c
->size
->height
= c
->height
;
1788 c
->previous_width
= -1;
1789 c
->previous_height
= -1;
1790 c
->border_width
= attr
.border_width
;
1791 c
->cmap
= attr
.colormap
;
1793 shaped
= clientCheckShape(c
);
1796 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
);
1797 FLAG_SET (c
->flags
, CLIENT_FLAG_HAS_SHAPE
);
1800 if (((c
->size
->flags
& (PMinSize
| PMaxSize
)) != (PMinSize
| PMaxSize
))
1801 || (((c
->size
->flags
& (PMinSize
| PMaxSize
)) ==
1802 (PMinSize
| PMaxSize
))
1803 && ((c
->size
->min_width
< c
->size
->max_width
)
1804 || (c
->size
->min_height
< c
->size
->max_height
))))
1806 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_IS_RESIZABLE
);
1809 for (i
= 0; i
< BUTTON_COUNT
; i
++)
1811 c
->button_status
[i
] = BUTTON_STATE_NORMAL
;
1814 if (!XGetWMColormapWindows (display_info
->dpy
, c
->window
, &c
->cmap_windows
, &c
->ncmap
))
1819 /* Opacity for compositing manager */
1820 c
->opacity
= NET_WM_OPAQUE
;
1821 getOpacity (display_info
, c
->window
, &c
->opacity
);
1822 c
->opacity_applied
= c
->opacity
;
1823 c
->opacity_flags
= 0;
1825 c
->opacity_locked
= getOpacityLock (display_info
, c
->window
);
1827 /* Timout for asynchronous icon update */
1828 c
->icon_timeout_id
= 0;
1829 /* Timout for asynchronous frame update */
1830 c
->frame_timeout_id
= 0;
1831 /* Timeout for blinking on urgency */
1832 c
->blink_timeout_id
= 0;
1834 c
->class.res_name
= NULL
;
1835 c
->class.res_class
= NULL
;
1836 XGetClassHint (display_info
->dpy
, w
, &c
->class);
1837 c
->wmhints
= XGetWMHints (display_info
->dpy
, c
->window
);
1838 c
->group_leader
= None
;
1841 if (c
->wmhints
->flags
& WindowGroupHint
)
1843 c
->group_leader
= c
->wmhints
->window_group
;
1846 c
->client_leader
= getClientLeader (display_info
, c
->window
);
1848 TRACE ("\"%s\" (0x%lx) initial map_state = %s",
1850 (attr
.map_state
== IsUnmapped
) ?
1852 (attr
.map_state
== IsViewable
) ?
1854 (attr
.map_state
== IsUnviewable
) ?
1857 if (attr
.map_state
!= IsUnmapped
)
1859 /* Reparent will send us unmap/map events */
1860 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_MAP_PENDING
);
1862 c
->ignore_unmap
= 0;
1864 c
->type_atom
= None
;
1866 FLAG_SET (c
->flags
, START_ICONIC (c
) ? CLIENT_FLAG_ICONIFIED
: 0);
1867 FLAG_SET (c
->wm_flags
, HINTS_ACCEPT_INPUT (c
->wmhints
) ? WM_FLAG_INPUT
: 0);
1869 clientGetWMProtocols (c
);
1870 clientGetMWMHints (c
, FALSE
);
1871 getHint (display_info
, w
, WIN_HINTS
, (long *) &c
->win_hints
);
1872 getHint (display_info
, w
, WIN_STATE
, (long *) &c
->win_state
);
1873 if (!getHint (display_info
, w
, WIN_LAYER
, (long *) &c
->win_layer
))
1875 c
->win_layer
= WIN_LAYER_NORMAL
;
1877 c
->fullscreen_old_layer
= c
->win_layer
;
1879 /* net_wm_user_time standard */
1880 clientGetUserTime (c
);
1882 /* Apply startup notification properties if available */
1883 sn_client_startup_properties (c
);
1885 /* Reload from session */
1886 if (sessionMatchWinToSM (c
))
1888 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_SESSION_MANAGED
);
1891 /* Beware, order of calls is important here ! */
1892 clientGetWinState (c
);
1893 clientGetNetState (c
);
1894 clientGetNetWmType (c
);
1895 clientGetInitialNetWmDesktop (c
);
1896 /* workarea will be updated when shown, no need to worry here */
1897 clientGetNetStruts (c
);
1899 /* Fullscreen for older legacy apps */
1900 if ((c
->x
<= 0) && (c
->y
<= 0) &&
1901 (c
->width
>= screen_info
->width
) &&
1902 (c
->height
>= screen_info
->height
) &&
1903 !FLAG_TEST(c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
) &&
1904 !FLAG_TEST (c
->flags
, CLIENT_FLAG_BELOW
| CLIENT_FLAG_ABOVE
| CLIENT_FLAG_FULLSCREEN
) &&
1905 (c
->win_layer
== WIN_LAYER_NORMAL
) &&
1906 (c
->type
== WINDOW_NORMAL
))
1908 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_LEGACY_FULLSCREEN
);
1911 /* Once we know the type of window, we can initialize window position */
1912 if (!FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_SESSION_MANAGED
))
1914 if ((attr
.map_state
!= IsUnmapped
))
1916 clientGravitate (c
, APPLY
);
1920 clientInitPosition (c
);
1925 Initialize "old" fields once the position is ensured, to avoid
1926 initially maximized or fullscreen windows being placed offscreen
1931 c
->old_width
= c
->width
;
1932 c
->old_height
= c
->height
;
1933 c
->fullscreen_old_x
= c
->x
;
1934 c
->fullscreen_old_y
= c
->y
;
1935 c
->fullscreen_old_width
= c
->width
;
1936 c
->fullscreen_old_height
= c
->height
;
1939 We must call clientApplyInitialState() after having placed the
1940 window so that the inital position values are correctly set if the
1941 inital state is maximize or fullscreen
1943 clientApplyInitialState (c
);
1945 valuemask
= CWEventMask
|CWBitGravity
|CWWinGravity
;
1946 attributes
.event_mask
= (FRAME_EVENT_MASK
| POINTER_EVENT_MASK
);
1947 attributes
.win_gravity
= StaticGravity
;
1948 attributes
.bit_gravity
= StaticGravity
;
1951 if (display_info
->have_render
)
1953 c
->visual
= attr
.visual
;
1954 c
->depth
= attr
.depth
;
1955 attributes
.colormap
= attr
.colormap
;
1956 valuemask
|= CWColormap
;
1960 c
->visual
= screen_info
->visual
;
1961 c
->depth
= screen_info
->depth
;
1966 attributes
.background_pixmap
= None
;
1967 attributes
.border_pixel
= 0;
1968 attributes
.background_pixel
= 0;
1969 valuemask
|= CWBackPixmap
|CWBackPixel
|CWBorderPixel
;
1971 #else /* HAVE_RENDER */
1972 /* We don't support multiple depth/visual w/out render */
1973 c
->visual
= screen_info
->visual
;
1974 c
->depth
= screen_info
->depth
;
1975 #endif /* HAVE_RENDER */
1978 XCreateWindow (display_info
->dpy
, screen_info
->xroot
, 0, 0, 1, 1, 0,
1979 c
->depth
, InputOutput
, c
->visual
, valuemask
, &attributes
);
1981 XSelectInput (display_info
->dpy
, c
->window
, 0);
1982 XSetWindowBorderWidth (display_info
->dpy
, c
->window
, 0);
1983 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
1985 XUnmapWindow (display_info
->dpy
, c
->window
);
1987 XReparentWindow (display_info
->dpy
, c
->window
, c
->frame
, frameLeft (c
), frameTop (c
));
1988 valuemask
= CWEventMask
;
1989 attributes
.event_mask
= (CLIENT_EVENT_MASK
);
1990 XChangeWindowAttributes (display_info
->dpy
, c
->window
, valuemask
, &attributes
);
1991 XSelectInput (display_info
->dpy
, c
->window
, CLIENT_EVENT_MASK
);
1992 if (display_info
->have_shape
)
1994 XShapeSelectInput (display_info
->dpy
, c
->window
, ShapeNotifyMask
);
1997 clientAddToList (c
);
1998 clientSetNetActions (c
);
1999 clientGrabButtons(c
);
2001 /* Initialize per client menu button pixmap */
2003 for (i
= 0; i
< STATE_TOGGLED
; i
++)
2005 xfwmPixmapInit (screen_info
, &c
->appmenu
[i
]);
2008 for (i
= 0; i
< SIDE_TOP
; i
++) /* Keep SIDE_TOP for later */
2010 xfwmWindowCreate (screen_info
, c
->visual
, c
->depth
, c
->frame
,
2011 &c
->sides
[i
], NoEventMask
,
2012 myDisplayGetCursorResize(screen_info
->display_info
, CORNER_COUNT
+ i
));
2015 for (i
= 0; i
< CORNER_COUNT
; i
++)
2017 xfwmWindowCreate (screen_info
, c
->visual
, c
->depth
, c
->frame
,
2018 &c
->corners
[i
], NoEventMask
,
2019 myDisplayGetCursorResize(screen_info
->display_info
, i
));
2022 xfwmWindowCreate (screen_info
, c
->visual
, c
->depth
, c
->frame
,
2023 &c
->title
, NoEventMask
, None
);
2025 /* create the top side window AFTER the title window since they overlap
2026 and the top side window should be on top */
2028 xfwmWindowCreate (screen_info
, c
->visual
, c
->depth
, c
->frame
,
2029 &c
->sides
[SIDE_TOP
], NoEventMask
,
2030 myDisplayGetCursorResize(screen_info
->display_info
,
2031 CORNER_COUNT
+ SIDE_TOP
));
2033 for (i
= 0; i
< BUTTON_COUNT
; i
++)
2035 xfwmWindowCreate (screen_info
, c
->visual
, c
->depth
, c
->frame
,
2036 &c
->buttons
[i
], BUTTON_EVENT_MASK
, None
);
2038 clientUpdateIconPix (c
);
2040 /* Put the window on top to avoid XShape, that speeds up hw accelerated
2041 GL apps dramatically */
2042 XRaiseWindow (display_info
->dpy
, c
->window
);
2044 TRACE ("now calling configure for the new window \"%s\" (0x%lx)", c
->name
, c
->window
);
2047 wc
.width
= c
->width
;
2048 wc
.height
= c
->height
;
2049 clientConfigure (c
, &wc
, CWX
| CWY
| CWHeight
| CWWidth
, CFG_NOTIFY
| CFG_FORCE_REDRAW
);
2051 /* Notify the compositor about this new window */
2052 compositorAddWindow (display_info
, c
->frame
, c
);
2055 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_ICONIFIED
))
2057 if ((c
->win_workspace
== screen_info
->current_ws
) ||
2058 FLAG_TEST(c
->flags
, CLIENT_FLAG_STICKY
))
2062 clientRaise (c
, None
);
2063 clientShow (c
, TRUE
);
2074 clientRaise (c
, None
);
2075 clientInitFocusFlag (c
);
2080 clientRaise (c
, None
);
2081 setWMState (display_info
, c
->window
, IconicState
);
2082 clientSetNetState (c
);
2087 clientGrabMouseButton (c
);
2089 setNetFrameExtents (display_info
, c
->window
, frameTop (c
), frameLeft (c
),
2090 frameRight (c
), frameBottom (c
));
2092 /* Window is reparented now, so we can safely release the grab
2095 myDisplayUngrabServer (display_info
);
2096 gdk_error_trap_pop ();
2098 DBG ("client \"%s\" (0x%lx) is now managed", c
->name
, c
->window
);
2099 DBG ("client_count=%d", screen_info
->client_count
);
2105 clientUnframe (Client
* c
, gboolean remap
)
2107 ScreenInfo
*screen_info
;
2108 DisplayInfo
*display_info
;
2111 gboolean reparented
;
2113 TRACE ("entering clientUnframe");
2114 TRACE ("unframing client \"%s\" (0x%lx) [%s]",
2115 c
->name
, c
->window
, remap
? "remap" : "no remap");
2117 g_return_if_fail (c
!= NULL
);
2119 screen_info
= c
->screen_info
;
2120 display_info
= screen_info
->display_info
;
2122 clientRemoveFromList (c
);
2123 compositorSetClient (display_info
, c
->frame
, NULL
);
2125 myDisplayGrabServer (display_info
);
2126 gdk_error_trap_push ();
2127 clientUngrabButtons (c
);
2128 XUnmapWindow (display_info
->dpy
, c
->frame
);
2129 clientGravitate (c
, REMOVE
);
2130 XSelectInput (display_info
->dpy
, c
->window
, NoEventMask
);
2131 reparented
= XCheckTypedWindowEvent (display_info
->dpy
, c
->window
, ReparentNotify
, &ev
);
2133 if (remap
|| !reparented
)
2135 XReparentWindow (display_info
->dpy
, c
->window
, c
->screen_info
->xroot
, c
->x
, c
->y
);
2136 XSetWindowBorderWidth (display_info
->dpy
, c
->window
, c
->border_width
);
2139 compositorAddWindow (display_info
, c
->window
, NULL
);
2140 XMapWindow (display_info
->dpy
, c
->window
);
2144 XUnmapWindow (display_info
->dpy
, c
->window
);
2145 setWMState (display_info
, c
->window
, WithdrawnState
);
2151 XDeleteProperty (display_info
->dpy
, c
->window
,
2152 display_info
->atoms
[NET_WM_STATE
]);
2153 XDeleteProperty (display_info
->dpy
, c
->window
,
2154 display_info
->atoms
[WIN_STATE
]);
2155 XDeleteProperty (display_info
->dpy
, c
->window
,
2156 display_info
->atoms
[NET_WM_DESKTOP
]);
2157 XDeleteProperty (display_info
->dpy
, c
->window
,
2158 display_info
->atoms
[WIN_WORKSPACE
]);
2159 XDeleteProperty (display_info
->dpy
, c
->window
,
2160 display_info
->atoms
[WIN_LAYER
]);
2161 XDeleteProperty (display_info
->dpy
, c
->window
,
2162 display_info
->atoms
[NET_WM_ALLOWED_ACTIONS
]);
2165 xfwmWindowDelete (&c
->title
);
2167 for (i
= 0; i
< SIDE_COUNT
; i
++)
2169 xfwmWindowDelete (&c
->sides
[i
]);
2171 for (i
= 0; i
< CORNER_COUNT
; i
++)
2173 xfwmWindowDelete (&c
->corners
[i
]);
2175 for (i
= 0; i
< STATE_TOGGLED
; i
++)
2177 xfwmPixmapFree (&c
->appmenu
[i
]);
2179 for (i
= 0; i
< BUTTON_COUNT
; i
++)
2181 xfwmWindowDelete (&c
->buttons
[i
]);
2183 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_HAS_STRUT
))
2185 workspaceUpdateArea (c
->screen_info
);
2187 XDestroyWindow (display_info
->dpy
, c
->frame
);
2189 myDisplayUngrabServer (display_info
);
2190 gdk_error_trap_pop ();
2195 clientFrameAll (ScreenInfo
*screen_info
)
2197 DisplayInfo
*display_info
;
2198 XWindowAttributes attr
;
2200 Window w1
, w2
, *wins
;
2201 unsigned int count
, i
;
2203 TRACE ("entering clientFrameAll");
2205 display_info
= screen_info
->display_info
;
2206 clientSetFocus (screen_info
, NULL
, myDisplayGetCurrentTime (display_info
), NO_FOCUS_FLAG
);
2207 xfwmWindowTemp (screen_info
,
2213 screen_info
->height
,
2217 XSync (display_info
->dpy
, FALSE
);
2218 myDisplayGrabServer (display_info
);
2219 XQueryTree (display_info
->dpy
, screen_info
->xroot
, &w1
, &w2
, &wins
, &count
);
2220 for (i
= 0; i
< count
; i
++)
2222 XGetWindowAttributes (display_info
->dpy
, wins
[i
], &attr
);
2223 if ((attr
.map_state
== IsViewable
) && (attr
.root
== screen_info
->xroot
))
2225 Client
*c
= clientFrame (display_info
, wins
[i
], TRUE
);
2226 if ((c
) && ((screen_info
->params
->raise_on_click
) || (screen_info
->params
->click_to_focus
)))
2228 clientGrabMouseButton (c
);
2233 compositorAddWindow (display_info
, wins
[i
], NULL
);
2240 clientFocusTop (screen_info
, WIN_LAYER_NORMAL
, myDisplayGetCurrentTime (display_info
));
2241 xfwmWindowDelete (&shield
);
2242 myDisplayUngrabServer (display_info
);
2243 XSync (display_info
->dpy
, FALSE
);
2247 clientUnframeAll (ScreenInfo
*screen_info
)
2249 DisplayInfo
*display_info
;
2251 Window w1
, w2
, *wins
;
2252 unsigned int count
, i
;
2254 TRACE ("entering clientUnframeAll");
2256 display_info
= screen_info
->display_info
;
2257 clientSetFocus (screen_info
, NULL
, myDisplayGetCurrentTime (display_info
), FOCUS_IGNORE_MODAL
);
2258 XSync (display_info
->dpy
, FALSE
);
2259 myDisplayGrabServer (display_info
);
2260 XQueryTree (display_info
->dpy
, screen_info
->xroot
, &w1
, &w2
, &wins
, &count
);
2261 for (i
= 0; i
< count
; i
++)
2263 c
= myScreenGetClientFromWindow (screen_info
, wins
[i
], SEARCH_FRAME
);
2266 clientUnframe (c
, TRUE
);
2269 myDisplayUngrabServer (display_info
);
2270 XSync(display_info
->dpy
, FALSE
);
2278 clientGetFromWindow (Client
*c
, Window w
, unsigned short mode
)
2282 g_return_val_if_fail (w
!= None
, NULL
);
2283 g_return_val_if_fail (c
!= NULL
, NULL
);
2284 TRACE ("entering clientGetFromWindow");
2286 if (mode
& SEARCH_WINDOW
)
2290 TRACE ("found \"%s\" (mode WINDOW)", c
->name
);
2295 if (mode
& SEARCH_FRAME
)
2299 TRACE ("found \"%s\" (mode FRAME)", c
->name
);
2304 if (mode
& SEARCH_BUTTON
)
2306 for (b
= 0; b
< BUTTON_COUNT
; b
++)
2308 if (MYWINDOW_XWINDOW(c
->buttons
[b
]) == w
)
2310 TRACE ("found \"%s\" (mode BUTTON)", c
->name
);
2316 TRACE ("no client found");
2322 clientSetWorkspaceSingle (Client
* c
, int ws
)
2324 ScreenInfo
*screen_info
;
2325 DisplayInfo
*display_info
;
2327 g_return_if_fail (c
!= NULL
);
2329 TRACE ("entering clientSetWorkspaceSingle");
2331 screen_info
= c
->screen_info
;
2332 display_info
= screen_info
->display_info
;
2334 if (ws
> screen_info
->workspace_count
- 1)
2336 ws
= screen_info
->workspace_count
- 1;
2337 TRACE ("value off limits, using %i instead", ws
);
2340 if (c
->win_workspace
!= ws
)
2342 TRACE ("setting client \"%s\" (0x%lx) to current_ws %d", c
->name
, c
->window
, ws
);
2343 c
->win_workspace
= ws
;
2344 setHint (display_info
, c
->window
, WIN_WORKSPACE
, ws
);
2345 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_STICKY
))
2347 setHint (display_info
, c
->window
, NET_WM_DESKTOP
, (unsigned long) ALL_WORKSPACES
);
2351 setHint (display_info
, c
->window
, NET_WM_DESKTOP
, (unsigned long) ws
);
2354 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_WORKSPACE_SET
);
2358 clientSetWorkspace (Client
* c
, int ws
, gboolean manage_mapping
)
2361 GList
*list_of_windows
;
2365 g_return_if_fail (c
!= NULL
);
2367 TRACE ("entering clientSetWorkspace");
2369 list_of_windows
= clientListTransientOrModal (c
);
2370 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
2372 c2
= (Client
*) index
->data
;
2374 if (c2
->win_workspace
!= ws
)
2376 TRACE ("setting client \"%s\" (0x%lx) to current_ws %d", c
->name
, c
->window
, ws
);
2378 previous_ws
= c2
->win_workspace
;
2379 clientSetWorkspaceSingle (c2
, ws
);
2381 if (manage_mapping
&& !clientIsValidTransientOrModal (c2
) && !FLAG_TEST (c2
->flags
, CLIENT_FLAG_ICONIFIED
))
2383 if (previous_ws
== c2
->screen_info
->current_ws
)
2385 clientHide (c2
, c2
->screen_info
->current_ws
, FALSE
);
2387 if (FLAG_TEST (c2
->flags
, CLIENT_FLAG_STICKY
) || (ws
== c2
->screen_info
->current_ws
))
2389 clientShow (c2
, FALSE
);
2394 g_list_free (list_of_windows
);
2398 clientShowSingle (Client
* c
, gboolean deiconify
)
2400 ScreenInfo
*screen_info
;
2401 DisplayInfo
*display_info
;
2403 g_return_if_fail (c
!= NULL
);
2405 screen_info
= c
->screen_info
;
2406 display_info
= screen_info
->display_info
;
2408 if ((c
->win_workspace
== screen_info
->current_ws
) || FLAG_TEST (c
->flags
, CLIENT_FLAG_STICKY
))
2410 TRACE ("showing client \"%s\" (0x%lx)", c
->name
, c
->window
);
2411 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
);
2412 XMapWindow (display_info
->dpy
, c
->frame
);
2413 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
2415 XMapWindow (display_info
->dpy
, c
->window
);
2417 /* Adjust to urgency state as the window is visible */
2418 clientUpdateUrgency (c
);
2422 FLAG_UNSET (c
->flags
, CLIENT_FLAG_ICONIFIED
);
2423 setWMState (display_info
, c
->window
, NormalState
);
2425 clientSetNetState (c
);
2429 clientShow (Client
* c
, gboolean deiconify
)
2432 GList
*list_of_windows
;
2435 g_return_if_fail (c
!= NULL
);
2436 TRACE ("entering clientShow \"%s\" (0x%lx)", c
->name
, c
->window
);
2438 list_of_windows
= clientListTransientOrModal (c
);
2439 for (index
= g_list_last (list_of_windows
); index
; index
= g_list_previous (index
))
2441 c2
= (Client
*) index
->data
;
2442 clientSetWorkspaceSingle (c2
, c
->win_workspace
);
2443 /* Ignore request before if the window is not yet managed */
2444 if (!FLAG_TEST (c2
->xfwm_flags
, XFWM_FLAG_MANAGED
))
2448 clientShowSingle (c2
, deiconify
);
2450 g_list_free (list_of_windows
);
2452 /* Update working area as windows have been shown */
2453 workspaceUpdateArea (c
->screen_info
);
2457 clientHideSingle (Client
* c
, gboolean iconify
)
2459 ScreenInfo
*screen_info
;
2460 DisplayInfo
*display_info
;
2462 g_return_if_fail (c
!= NULL
);
2464 screen_info
= c
->screen_info
;
2465 display_info
= screen_info
->display_info
;
2467 TRACE ("hiding client \"%s\" (0x%lx)", c
->name
, c
->window
);
2468 clientPassFocus(c
->screen_info
, c
, c
);
2469 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
))
2471 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
);
2473 /* Adjust to urgency state as the window is not visible */
2474 clientUpdateUrgency (c
);
2476 XUnmapWindow (display_info
->dpy
, c
->window
);
2477 XUnmapWindow (display_info
->dpy
, c
->frame
);
2480 FLAG_SET (c
->flags
, CLIENT_FLAG_ICONIFIED
);
2481 setWMState (display_info
, c
->window
, IconicState
);
2483 clientSetNetState (c
);
2487 clientHide (Client
* c
, int ws
, gboolean iconify
)
2490 GList
*list_of_windows
;
2493 g_return_if_fail (c
!= NULL
);
2494 TRACE ("entering clientHide \"%s\" (0x%lx)", c
->name
, c
->window
);
2496 list_of_windows
= clientListTransientOrModal (c
);
2497 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
2499 c2
= (Client
*) index
->data
;
2501 /* Ignore request before if the window is not yet managed */
2502 if (!FLAG_TEST (c2
->xfwm_flags
, XFWM_FLAG_MANAGED
))
2507 /* ws is used when transitioning between desktops, to avoid
2508 hiding a transient for group that will be shown again on the new
2509 workspace (transient for groups can be transients for multiple
2510 ancesors splitted across workspaces...)
2512 if (clientIsTransientOrModal (c2
) &&
2513 clientTransientOrModalHasAncestor (c2
, ws
))
2515 /* Other ancestors for that transient are still on screen, so don't
2521 if (FLAG_TEST (c2
->flags
, CLIENT_FLAG_STICKY
) && !iconify
)
2525 clientHideSingle (c2
, iconify
);
2527 g_list_free (list_of_windows
);
2529 /* Update working area as windows have been hidden */
2530 workspaceUpdateArea (c
->screen_info
);
2534 clientHideAll (Client
* c
, int ws
)
2536 ScreenInfo
*screen_info
;
2540 g_return_if_fail (c
!= NULL
);
2542 TRACE ("entering clientHideAll");
2544 screen_info
= c
->screen_info
;
2545 for (c2
= c
->next
, i
= 0; (c2
) && (i
< screen_info
->client_count
); c2
= c2
->next
, i
++)
2547 if (CLIENT_CAN_HIDE_WINDOW (c2
)
2548 && !clientIsValidTransientOrModal (c2
) && (c2
!= c
))
2550 if (((!c
) && (c2
->win_workspace
== ws
))
2551 || ((c
) && !clientIsTransientOrModalFor (c
, c2
)
2552 && (c2
->win_workspace
== c
->win_workspace
)))
2554 clientHide (c2
, ws
, TRUE
);
2561 clientClearAllShowDesktop (ScreenInfo
*screen_info
)
2563 TRACE ("entering clientClearShowDesktop");
2565 if (screen_info
->show_desktop
)
2567 GList
*index
= NULL
;
2569 for (index
= screen_info
->windows_stack
; index
; index
= g_list_next (index
))
2571 Client
*c
= (Client
*) index
->data
;
2572 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_WAS_SHOWN
);
2574 screen_info
->show_desktop
= FALSE
;
2575 sendRootMessage (screen_info
, NET_SHOWING_DESKTOP
, screen_info
->show_desktop
,
2576 myDisplayGetCurrentTime (screen_info
->display_info
));
2581 clientToggleShowDesktop (ScreenInfo
*screen_info
)
2585 TRACE ("entering clientToggleShowDesktop");
2587 clientSetFocus (screen_info
, NULL
,
2588 myDisplayGetCurrentTime (screen_info
->display_info
),
2589 FOCUS_IGNORE_MODAL
);
2590 if (screen_info
->show_desktop
)
2592 for (index
= screen_info
->windows_stack
; index
; index
= g_list_next (index
))
2594 Client
*c
= (Client
*) index
->data
;
2595 if ((c
->type
& WINDOW_REGULAR_FOCUSABLE
)
2596 && !FLAG_TEST (c
->flags
, CLIENT_FLAG_ICONIFIED
| CLIENT_FLAG_SKIP_TASKBAR
))
2598 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_WAS_SHOWN
);
2599 clientHide (c
, c
->win_workspace
, TRUE
);
2602 clientFocusTop (screen_info
, WIN_LAYER_DESKTOP
, myDisplayGetCurrentTime (screen_info
->display_info
));
2606 for (index
= g_list_last(screen_info
->windows_stack
); index
; index
= g_list_previous (index
))
2608 Client
*c
= (Client
*) index
->data
;
2609 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_WAS_SHOWN
))
2611 clientShow (c
, TRUE
);
2613 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_WAS_SHOWN
);
2615 clientFocusTop (screen_info
, WIN_LAYER_NORMAL
, myDisplayGetCurrentTime (screen_info
->display_info
));
2620 clientActivate (Client
* c
, Time timestamp
)
2622 ScreenInfo
*screen_info
;
2624 g_return_if_fail (c
!= NULL
);
2625 TRACE ("entering clientActivate \"%s\" (0x%lx)", c
->name
, c
->window
);
2627 screen_info
= c
->screen_info
;
2628 if ((screen_info
->current_ws
== c
->win_workspace
) || (screen_info
->params
->activate_action
!= ACTIVATE_ACTION_NONE
))
2630 if (screen_info
->current_ws
!= c
->win_workspace
)
2632 if (screen_info
->params
->activate_action
== ACTIVATE_ACTION_BRING
)
2634 clientSetWorkspace (c
, screen_info
->current_ws
, TRUE
);
2638 workspaceSwitch (screen_info
, c
->win_workspace
, NULL
, FALSE
, timestamp
);
2641 clientShow (c
, TRUE
);
2642 clientClearAllShowDesktop (screen_info
);
2643 clientSetFocus (screen_info
, c
, timestamp
, NO_FOCUS_FLAG
);
2644 clientRaise (c
, None
);
2648 TRACE ("Setting WM_STATE_DEMANDS_ATTENTION flag on \"%s\" (0x%lx)", c
->name
, c
->window
);
2649 FLAG_SET (c
->flags
, CLIENT_FLAG_DEMANDS_ATTENTION
);
2650 clientSetNetState (c
);
2655 clientClose (Client
* c
)
2657 ScreenInfo
*screen_info
;
2658 DisplayInfo
*display_info
;
2660 g_return_if_fail (c
!= NULL
);
2662 TRACE ("entering clientClose");
2663 TRACE ("closing client \"%s\" (0x%lx)", c
->name
, c
->window
);
2665 screen_info
= c
->screen_info
;
2666 display_info
= screen_info
->display_info
;
2668 if (FLAG_TEST (c
->wm_flags
, WM_FLAG_DELETE
))
2670 sendClientMessage (screen_info
, c
->window
, WM_DELETE_WINDOW
,
2671 myDisplayGetCurrentTime (display_info
));
2680 clientKill (Client
* c
)
2682 g_return_if_fail (c
!= NULL
);
2683 TRACE ("entering clientKill");
2684 TRACE ("killing client \"%s\" (0x%lx)", c
->name
, c
->window
);
2686 XKillClient (clientGetXDisplay (c
), c
->window
);
2690 clientEnterContextMenuState (Client
* c
)
2692 ScreenInfo
*screen_info
;
2693 DisplayInfo
*display_info
;
2695 g_return_if_fail (c
!= NULL
);
2697 TRACE ("entering clientEnterContextMenuState");
2698 TRACE ("Showing the what's this help for client \"%s\" (0x%lx)", c
->name
, c
->window
);
2700 screen_info
= c
->screen_info
;
2701 display_info
= screen_info
->display_info
;
2703 if (FLAG_TEST (c
->wm_flags
, WM_FLAG_CONTEXT_HELP
))
2705 sendClientMessage (c
->screen_info
, c
->window
, NET_WM_CONTEXT_HELP
,
2706 myDisplayGetCurrentTime (display_info
));
2711 clientSetLayer (Client
* c
, int l
)
2713 ScreenInfo
*screen_info
;
2714 DisplayInfo
*display_info
;
2715 GList
*list_of_windows
= NULL
;
2716 GList
*index
= NULL
;
2719 g_return_if_fail (c
!= NULL
);
2720 TRACE ("entering clientSetLayer");
2722 screen_info
= c
->screen_info
;
2723 display_info
= screen_info
->display_info
;
2725 list_of_windows
= clientListTransientOrModal (c
);
2726 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
2728 c2
= (Client
*) index
->data
;
2729 if (c2
->win_layer
!= l
)
2731 TRACE ("setting client \"%s\" (0x%lx) layer to %d", c2
->name
,
2734 setHint (display_info
, c2
->window
, WIN_LAYER
, l
);
2737 g_list_free (list_of_windows
);
2738 if (clientGetLastRaise (c
->screen_info
) == c
)
2740 clientClearLastRaise (c
->screen_info
);
2742 clientRaise (c
, None
);
2746 clientShade (Client
* c
)
2749 ScreenInfo
*screen_info
;
2750 DisplayInfo
*display_info
;
2753 g_return_if_fail (c
!= NULL
);
2754 TRACE ("entering clientToggleShaded");
2755 TRACE ("shading client \"%s\" (0x%lx)", c
->name
, c
->window
);
2757 if (!FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
2758 || FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
))
2760 TRACE ("cowardly refusing to shade \"%s\" (0x%lx) because it has no border", c
->name
, c
->window
);
2763 else if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
2765 TRACE ("\"%s\" (0x%lx) is already shaded", c
->name
, c
->window
);
2769 screen_info
= c
->screen_info
;
2770 display_info
= screen_info
->display_info
;
2772 c
->win_state
|= WIN_STATE_SHADED
;
2773 FLAG_SET (c
->flags
, CLIENT_FLAG_SHADED
);
2774 clientSetNetState (c
);
2775 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MANAGED
))
2777 mask
= (CWWidth
| CWHeight
);
2778 if (clientConstrainPos (c
, FALSE
))
2782 mask
|= (CWX
| CWY
);
2785 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
))
2790 * Shading unmaps the client window. We therefore have to transfer focus to its frame
2791 * so that focus doesn't return to root. clientSetFocus() will take care of focusing
2792 * the window frame since the SHADED flag is now set.
2794 if (c
== clientGetFocus ())
2796 clientSetFocus (screen_info
, c
, myDisplayGetCurrentTime (display_info
), FOCUS_FORCE
);
2798 XUnmapWindow (display_info
->dpy
, c
->window
);
2800 wc
.width
= c
->width
;
2801 wc
.height
= c
->height
;
2802 clientConfigure (c
, &wc
, mask
, CFG_FORCE_REDRAW
);
2807 clientUnshade (Client
* c
)
2810 ScreenInfo
*screen_info
;
2811 DisplayInfo
*display_info
;
2813 g_return_if_fail (c
!= NULL
);
2814 TRACE ("entering clientToggleShaded");
2815 TRACE ("shading/unshading client \"%s\" (0x%lx)", c
->name
, c
->window
);
2817 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
2819 TRACE ("\"%s\" (0x%lx) is not shaded", c
->name
, c
->window
);
2823 screen_info
= c
->screen_info
;
2824 display_info
= screen_info
->display_info
;
2826 c
->win_state
&= ~WIN_STATE_SHADED
;
2827 FLAG_UNSET (c
->flags
, CLIENT_FLAG_SHADED
);
2828 clientSetNetState (c
);
2829 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MANAGED
))
2831 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_VISIBLE
))
2833 XMapWindow (display_info
->dpy
, c
->window
);
2836 * Unshading will show the client window, so we need to focus it when unshading.
2838 if (c
== clientGetFocus ())
2840 clientSetFocus (screen_info
, c
, myDisplayGetCurrentTime (display_info
), FOCUS_FORCE
);
2843 wc
.width
= c
->width
;
2844 wc
.height
= c
->height
;
2845 clientConfigure (c
, &wc
, CWWidth
| CWHeight
, CFG_FORCE_REDRAW
);
2850 clientToggleShaded (Client
* c
)
2852 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
2863 clientStick (Client
* c
, gboolean include_transients
)
2865 ScreenInfo
*screen_info
;
2866 DisplayInfo
*display_info
;
2868 GList
*list_of_windows
;
2871 g_return_if_fail (c
!= NULL
);
2872 TRACE ("entering clientStick");
2874 screen_info
= c
->screen_info
;
2875 display_info
= screen_info
->display_info
;
2877 if (include_transients
)
2879 list_of_windows
= clientListTransientOrModal (c
);
2880 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
2882 c2
= (Client
*) index
->data
;
2883 TRACE ("sticking client \"%s\" (0x%lx)", c2
->name
, c2
->window
);
2884 c2
->win_state
|= WIN_STATE_STICKY
;
2885 FLAG_SET (c2
->flags
, CLIENT_FLAG_STICKY
);
2886 setHint (display_info
, c2
->window
, NET_WM_DESKTOP
, (unsigned long) ALL_WORKSPACES
);
2887 clientSetNetState (c2
);
2889 clientSetWorkspace (c
, screen_info
->current_ws
, TRUE
);
2890 g_list_free (list_of_windows
);
2894 TRACE ("sticking client \"%s\" (0x%lx)", c
->name
, c
->window
);
2895 c
->win_state
|= WIN_STATE_STICKY
;
2896 FLAG_SET (c
->flags
, CLIENT_FLAG_STICKY
);
2897 setHint (display_info
, c
->window
, NET_WM_DESKTOP
, (unsigned long) ALL_WORKSPACES
);
2898 clientSetNetState (c
);
2899 clientSetWorkspace (c
, screen_info
->current_ws
, TRUE
);
2904 clientUnstick (Client
* c
, gboolean include_transients
)
2906 ScreenInfo
*screen_info
;
2907 DisplayInfo
*display_info
;
2909 GList
*list_of_windows
;
2912 g_return_if_fail (c
!= NULL
);
2913 TRACE ("entering clientUnstick");
2914 TRACE ("unsticking client \"%s\" (0x%lx)", c
->name
, c
->window
);
2916 screen_info
= c
->screen_info
;
2917 display_info
= screen_info
->display_info
;
2919 if (include_transients
)
2921 list_of_windows
= clientListTransientOrModal (c
);
2922 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
2924 c2
= (Client
*) index
->data
;
2925 c2
->win_state
&= ~WIN_STATE_STICKY
;
2926 FLAG_UNSET (c2
->flags
, CLIENT_FLAG_STICKY
);
2927 setHint (display_info
, c2
->window
, NET_WM_DESKTOP
, (unsigned long) screen_info
->current_ws
);
2928 clientSetNetState (c2
);
2930 clientSetWorkspace (c
, screen_info
->current_ws
, TRUE
);
2931 g_list_free (list_of_windows
);
2935 c
->win_state
&= ~WIN_STATE_STICKY
;
2936 FLAG_UNSET (c
->flags
, CLIENT_FLAG_STICKY
);
2937 setHint (display_info
, c
->window
, NET_WM_DESKTOP
, (unsigned long) screen_info
->current_ws
);
2938 clientSetNetState (c
);
2939 clientSetWorkspace (c
, screen_info
->current_ws
, TRUE
);
2944 clientToggleSticky (Client
* c
, gboolean include_transients
)
2946 g_return_if_fail (c
!= NULL
);
2947 TRACE ("entering clientToggleSticky");
2948 TRACE ("sticking/unsticking client \"%s\" (0x%lx)", c
->name
, c
->window
);
2950 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_STICKY
))
2952 clientUnstick (c
, include_transients
);
2956 clientStick (c
, include_transients
);
2960 void clientToggleFullscreen (Client
* c
)
2962 g_return_if_fail (c
!= NULL
);
2963 TRACE ("entering clientToggleFullscreen");
2964 TRACE ("toggle fullscreen client \"%s\" (0x%lx)", c
->name
, c
->window
);
2966 /* Can we switch to full screen, does it make any sense? */
2967 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
) && (c
->size
->flags
& PMaxSize
))
2973 cx
= frameX (c
) + (frameWidth (c
) / 2);
2974 cy
= frameY (c
) + (frameHeight (c
) / 2);
2976 monitor_nbr
= find_monitor_at_point (c
->screen_info
->gscr
, cx
, cy
);
2977 gdk_screen_get_monitor_geometry (c
->screen_info
->gscr
, monitor_nbr
, &rect
);
2979 if ((c
->size
->max_width
< rect
.width
) || (c
->size
->max_height
< rect
.height
))
2985 if (!clientIsValidTransientOrModal (c
) && (c
->type
== WINDOW_NORMAL
))
2987 FLAG_TOGGLE (c
->flags
, CLIENT_FLAG_FULLSCREEN
);
2988 clientUpdateFullscreenState (c
);
2992 void clientToggleAbove (Client
* c
)
2994 g_return_if_fail (c
!= NULL
);
2995 TRACE ("entering clientToggleAbove");
2996 TRACE ("toggle above client \"%s\" (0x%lx)", c
->name
, c
->window
);
2998 if (!clientIsValidTransientOrModal (c
) &&
2999 !FLAG_TEST (c
->flags
, CLIENT_FLAG_BELOW
| CLIENT_FLAG_FULLSCREEN
))
3001 FLAG_TOGGLE (c
->flags
, CLIENT_FLAG_ABOVE
);
3002 clientUpdateAboveState (c
);
3006 void clientToggleBelow (Client
* c
)
3008 g_return_if_fail (c
!= NULL
);
3009 TRACE ("entering clientToggleBelow");
3010 TRACE ("toggle below client \"%s\" (0x%lx)", c
->name
, c
->window
);
3012 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_ABOVE
))
3014 FLAG_TOGGLE (c
->flags
, CLIENT_FLAG_BELOW
);
3015 clientUpdateAboveState (c
);
3020 clientRemoveMaximizeFlag (Client
* c
)
3022 g_return_if_fail (c
!= NULL
);
3023 TRACE ("entering clientRemoveMaximizeFlag");
3024 TRACE ("Removing maximize flag on client \"%s\" (0x%lx)", c
->name
,
3027 c
->win_state
&= ~WIN_STATE_MAXIMIZED
;
3028 FLAG_UNSET (c
->flags
, CLIENT_FLAG_MAXIMIZED
);
3029 frameDraw (c
, FALSE
);
3030 clientSetNetState (c
);
3034 clientNewMaxState (Client
* c
, XWindowChanges
*wc
, int mode
)
3037 * We treat differently full maximization from vertical or horizontal maximization.
3038 * This is for usability concerns, otherwise maximization acts like a toggle,
3039 * switching from horizontal to vertical instead of switching to full maximization.
3041 * The full size is not computed yet, as full maximization removes borders
3042 * while either horizontal or vertical maximization still shows decorations...
3045 if ((mode
& WIN_STATE_MAXIMIZED
) == WIN_STATE_MAXIMIZED
)
3047 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED
))
3049 c
->win_state
|= WIN_STATE_MAXIMIZED
;
3050 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED
);
3055 if (mode
& WIN_STATE_MAXIMIZED_HORIZ
)
3057 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
))
3059 c
->win_state
|= WIN_STATE_MAXIMIZED_HORIZ
;
3060 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
);
3065 if (mode
& WIN_STATE_MAXIMIZED_VERT
)
3067 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_VERT
))
3069 c
->win_state
|= WIN_STATE_MAXIMIZED_VERT
;
3070 FLAG_SET (c
->flags
, CLIENT_FLAG_MAXIMIZED_VERT
);
3075 c
->win_state
&= ~WIN_STATE_MAXIMIZED
;
3076 FLAG_UNSET (c
->flags
, CLIENT_FLAG_MAXIMIZED
);
3079 wc
->width
= c
->old_width
;
3080 wc
->height
= c
->old_height
;
3084 clientNewMaxSize (Client
* c
, XWindowChanges
*wc
)
3086 ScreenInfo
*screen_info
;
3088 int cx
, cy
, full_x
, full_y
, full_w
, full_h
;
3089 int tmp_x
, tmp_y
, tmp_w
, tmp_h
;
3094 tmp_h
= frameHeight (c
);
3095 tmp_w
= frameWidth (c
);
3097 cx
= tmp_x
+ (tmp_w
/ 2);
3098 cy
= tmp_y
+ (tmp_h
/ 2);
3100 screen_info
= c
->screen_info
;
3102 monitor_nbr
= find_monitor_at_point (screen_info
->gscr
, cx
, cy
);
3103 gdk_screen_get_monitor_geometry (screen_info
->gscr
, monitor_nbr
, &rect
);
3105 full_x
= MAX (screen_info
->params
->xfwm_margins
[STRUTS_LEFT
], rect
.x
);
3106 full_y
= MAX (screen_info
->params
->xfwm_margins
[STRUTS_TOP
], rect
.y
);
3107 full_w
= MIN (screen_info
->width
- screen_info
->params
->xfwm_margins
[STRUTS_RIGHT
],
3108 rect
.x
+ rect
.width
) - full_x
;
3109 full_h
= MIN (screen_info
->height
- screen_info
->params
->xfwm_margins
[STRUTS_BOTTOM
],
3110 rect
.y
+ rect
.height
) - full_y
;
3112 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
))
3114 /* Adjust size to the largest size available, not covering struts */
3115 clientMaxSpace (screen_info
, &full_x
, &full_y
, &full_w
, &full_h
);
3116 wc
->x
= full_x
+ frameLeft (c
);
3117 wc
->y
= full_y
+ frameTop (c
);
3118 wc
->width
= full_w
- frameLeft (c
) - frameRight (c
);
3119 wc
->height
= full_h
- frameTop (c
) - frameBottom (c
);
3124 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
))
3126 /* Adjust size to the widest size available, for the current vertical position/height */
3127 clientMaxSpace (screen_info
, &full_x
, &tmp_y
, &full_w
, &tmp_h
);
3128 wc
->x
= full_x
+ frameLeft (c
);
3129 wc
->width
= full_w
- frameLeft (c
) - frameRight (c
);
3134 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_VERT
))
3136 /* Adjust size to the tallest size available, for the current horizontal position/width */
3137 clientMaxSpace (screen_info
, &tmp_x
, &full_y
, &tmp_w
, &full_h
);
3138 wc
->y
= full_y
+ frameTop (c
);
3139 wc
->height
= full_h
- frameTop (c
) - frameBottom (c
);
3146 clientToggleMaximized (Client
* c
, int mode
, gboolean restore_position
)
3148 DisplayInfo
*display_info
;
3149 ScreenInfo
*screen_info
;
3153 g_return_if_fail (c
!= NULL
);
3154 TRACE ("entering clientToggleMaximized");
3155 TRACE ("maximzing/unmaximizing client \"%s\" (0x%lx)", c
->name
, c
->window
);
3157 if (!CLIENT_CAN_MAXIMIZE_WINDOW (c
))
3162 screen_info
= c
->screen_info
;
3163 display_info
= screen_info
->display_info
;
3167 wc
.width
= c
->width
;
3168 wc
.height
= c
->height
;
3170 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED
) && (restore_position
))
3174 c
->old_width
= c
->width
;
3175 c
->old_height
= c
->height
;
3178 /* 1) Compute the new state */
3179 clientNewMaxState (c
, &wc
, mode
);
3181 /* 2) Compute the new size, based on the state */
3182 clientNewMaxSize (c
, &wc
);
3184 /* 3) Update window state fields */
3185 clientSetNetState (c
);
3187 /* 4) Update size and position fields */
3190 c
->height
= wc
.height
;
3191 c
->width
= wc
.width
;
3193 /* Maximizing may remove decoration on the side, update NET_FRAME_EXTENTS accordingly */
3194 setNetFrameExtents (display_info
,
3201 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MANAGED
) && (restore_position
))
3204 For some reason, the configure can generate EnterNotify events
3205 on lower windows, causing a nasty race cond with apps trying to
3206 grab focus in focus follow mouse mode. Grab the pointer to
3209 myScreenGrabPointer (c
->screen_info
, EnterWindowMask
, None
, myDisplayGetCurrentTime (display_info
));
3210 clientConfigure (c
, &wc
, CWWidth
| CWHeight
| CWX
| CWY
, CFG_FORCE_REDRAW
);
3211 myScreenUngrabPointer (c
->screen_info
);
3216 clientFill (Client
* c
, int fill_type
)
3218 ScreenInfo
*screen_info
;
3219 DisplayInfo
*display_info
;
3220 Client
*east_neighbour
;
3221 Client
*west_neighbour
;
3222 Client
*north_neighbour
;
3223 Client
*south_neighbour
;
3227 unsigned short mask
;
3228 int i
, cx
, cy
, full_x
, full_y
, full_w
, full_h
;
3229 int tmp_x
, tmp_y
, tmp_w
, tmp_h
;
3232 g_return_if_fail (c
!= NULL
);
3234 if (!CLIENT_CAN_FILL_WINDOW (c
))
3239 screen_info
= c
->screen_info
;
3240 display_info
= screen_info
->display_info
;
3242 east_neighbour
= NULL
;
3243 west_neighbour
= NULL
;
3244 north_neighbour
= NULL
;
3245 south_neighbour
= NULL
;
3247 for (c2
= screen_info
->clients
, i
= 0; i
< screen_info
->client_count
; c2
= c2
->next
, i
++)
3250 /* Filter out all windows which are not visible, or not on the same layer
3251 * as well as the client window itself
3253 if ((c
!= c2
) && FLAG_TEST (c2
->xfwm_flags
, XFWM_FLAG_VISIBLE
) && (c2
->win_layer
== c
->win_layer
))
3255 /* Fill horizontally */
3256 if (fill_type
& CLIENT_FILL_HORIZ
)
3259 * check if the neigbour client (c2) is located
3260 * east or west of our client.
3262 if (!(((frameY(c
) + frameHeight(c
)) < (frameY(c2
) - frameTop(c2
))) || ((frameY(c2
) + frameHeight(c2
)) < (frameY(c
) - frameTop(c
)))))
3264 if ((frameX(c2
) + frameWidth(c2
)) < frameX(c
))
3268 /* Check if c2 is closer to the client
3269 * then the east neighbour already found
3271 if ((frameX(east_neighbour
) + frameWidth(east_neighbour
)) < (frameX(c2
) + frameWidth(c2
)))
3273 east_neighbour
= c2
;
3278 east_neighbour
= c2
;
3281 if ((frameX(c
) + frameWidth(c
)) < frameX(c2
))
3283 /* Check if c2 is closer to the client
3284 * then the west neighbour already found
3288 if (frameX(c2
) < frameX(west_neighbour
))
3290 west_neighbour
= c2
;
3295 west_neighbour
= c2
;
3301 /* Fill vertically */
3302 if (fill_type
& CLIENT_FILL_VERT
)
3304 /* check if the neigbour client (c2) is located
3305 * north or south of our client.
3307 if (!(((frameX(c
) + frameWidth(c
)) < frameX(c2
)) || ((frameX(c2
) + frameWidth(c2
)) < frameX(c
))))
3309 if ((frameY(c2
) + frameHeight(c2
)) < frameY(c
))
3311 if (north_neighbour
)
3313 /* Check if c2 is closer to the client
3314 * then the north neighbour already found
3316 if ((frameY(north_neighbour
) + frameHeight(north_neighbour
)) < (frameY(c2
) + frameHeight(c2
)))
3318 north_neighbour
= c2
;
3323 north_neighbour
= c2
;
3326 if ((frameY(c
) + frameHeight(c
)) < frameY(c2
))
3328 if (south_neighbour
)
3330 /* Check if c2 is closer to the client
3331 * then the south neighbour already found
3333 if (frameY(c2
) < frameY(south_neighbour
))
3335 south_neighbour
= c2
;
3340 south_neighbour
= c2
;
3348 /* Compute the largest size available, based on struts, margins and Xinerama layout */
3351 tmp_h
= frameHeight (c
);
3352 tmp_w
= frameWidth (c
);
3354 cx
= tmp_x
+ (tmp_w
/ 2);
3355 cy
= tmp_y
+ (tmp_h
/ 2);
3357 monitor_nbr
= find_monitor_at_point (screen_info
->gscr
, cx
, cy
);
3358 gdk_screen_get_monitor_geometry (screen_info
->gscr
, monitor_nbr
, &rect
);
3360 full_x
= MAX (screen_info
->params
->xfwm_margins
[STRUTS_LEFT
], rect
.x
);
3361 full_y
= MAX (screen_info
->params
->xfwm_margins
[STRUTS_TOP
], rect
.y
);
3362 full_w
= MIN (screen_info
->width
- screen_info
->params
->xfwm_margins
[STRUTS_RIGHT
],
3363 rect
.x
+ rect
.width
) - full_x
;
3364 full_h
= MIN (screen_info
->height
- screen_info
->params
->xfwm_margins
[STRUTS_BOTTOM
],
3365 rect
.y
+ rect
.height
) - full_y
;
3367 if ((fill_type
& CLIENT_FILL
) == CLIENT_FILL
)
3369 mask
= CWX
| CWY
| CWHeight
| CWWidth
;
3370 /* Adjust size to the largest size available, not covering struts */
3371 clientMaxSpace (screen_info
, &full_x
, &full_y
, &full_w
, &full_h
);
3373 else if (fill_type
& CLIENT_FILL_VERT
)
3375 mask
= CWY
| CWHeight
;
3376 /* Adjust size to the tallest size available, for the current horizontal position/width */
3377 clientMaxSpace (screen_info
, &tmp_x
, &full_y
, &tmp_w
, &full_h
);
3379 else if (fill_type
& CLIENT_FILL_HORIZ
)
3381 mask
= CWX
| CWWidth
;
3382 /* Adjust size to the widest size available, for the current vertical position/height */
3383 clientMaxSpace (screen_info
, &full_x
, &tmp_y
, &full_w
, &tmp_h
);
3386 /* If there are neighbours, resize to their borders.
3387 * If not, resize to the largest size available taht you just have computed.
3392 wc
.x
= frameX(east_neighbour
) + frameWidth(east_neighbour
) + frameLeft(c
);
3396 wc
.x
= full_x
+ frameLeft(c
);
3401 wc
.width
= full_x
+ frameX(west_neighbour
) - frameRight(c
) - wc
.x
;
3405 wc
.width
= full_x
+ full_w
- frameRight(c
) - wc
.x
;
3408 if (north_neighbour
)
3410 wc
.y
= frameY(north_neighbour
) + frameHeight(north_neighbour
) + frameTop(c
);
3414 wc
.y
= full_y
+ frameTop(c
);
3417 if (south_neighbour
)
3419 wc
.height
= full_y
+ frameY(south_neighbour
) - frameBottom(c
) - wc
.y
;
3423 wc
.height
= full_y
+ full_h
- frameBottom(c
) - wc
.y
;
3426 TRACE ("Fill size request: (%d,%d) %dx%d", wc
.x
, wc
.y
, wc
.width
, wc
.height
);
3427 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_MANAGED
))
3430 For some reason, the configure can generate EnterNotify events
3431 on lower windows, causing a nasty race cond with apps trying to
3432 grab focus in focus follow mouse mode. Grab the pointer to
3435 myScreenGrabPointer (c
->screen_info
, EnterWindowMask
, None
, myDisplayGetCurrentTime (display_info
));
3436 clientConfigure(c
, &wc
, mask
, NO_CFG_FLAG
);
3437 myScreenUngrabPointer (c
->screen_info
);
3442 clientUpdateOpacity (ScreenInfo
*screen_info
, Client
*focus
)
3444 DisplayInfo
*display_info
;
3448 display_info
= screen_info
->display_info
;
3449 if (!compositorIsUsable (display_info
))
3454 for (c
= screen_info
->clients
, i
= 0; i
< screen_info
->client_count
; c
= c
->next
, ++i
)
3456 gboolean o
= FLAG_TEST(c
->type
, WINDOW_TYPE_DONT_PLACE
| WINDOW_TYPE_DONT_FOCUS
)
3458 || (focus
&& ((focus
->transient_for
== c
->window
) || (focus
->window
== c
->transient_for
)))
3459 || (focus
&& (clientIsModalFor (c
, focus
) || clientIsModalFor (focus
, c
)));
3461 clientSetOpacity (c
, c
->opacity
, OPACITY_INACTIVE
, o
? 0 : OPACITY_INACTIVE
);
3466 clientSetOpacity (Client
*c
, guint opacity
, guint clear
, guint
xor)
3468 ScreenInfo
*screen_info
;
3469 DisplayInfo
*display_info
;
3472 screen_info
= c
->screen_info
;
3473 display_info
= screen_info
->display_info
;
3475 if (!compositorIsUsable (display_info
))
3480 c
->opacity_flags
= (c
->opacity_flags
& ~clear
) ^ xor;
3482 if (c
->opacity_locked
)
3484 applied
= c
->opacity
;
3488 long long multiplier
= 1, divisor
= 1;
3490 c
->opacity
= applied
= opacity
;
3492 if (FLAG_TEST (c
->opacity_flags
, OPACITY_MOVE
))
3494 multiplier
*= c
->screen_info
->params
->move_opacity
;
3497 if (FLAG_TEST (c
->opacity_flags
, OPACITY_RESIZE
))
3499 multiplier
*= c
->screen_info
->params
->resize_opacity
;
3502 if (FLAG_TEST (c
->opacity_flags
, OPACITY_INACTIVE
))
3504 multiplier
*= c
->screen_info
->params
->inactive_opacity
;
3508 applied
= (guint
) ((long long) applied
* multiplier
/ divisor
);
3511 if (applied
!= c
->opacity_applied
)
3513 c
->opacity_applied
= applied
;
3514 compositorWindowSetOpacity (display_info
, c
->frame
, applied
);
3519 clientDecOpacity (Client
* c
)
3521 ScreenInfo
*screen_info
;
3522 DisplayInfo
*display_info
;
3524 screen_info
= c
->screen_info
;
3525 display_info
= screen_info
->display_info
;
3527 if (!compositorIsUsable (display_info
))
3532 if ((c
->opacity
> OPACITY_SET_MIN
) && !(c
->opacity_locked
))
3534 clientSetOpacity (c
, c
->opacity
- OPACITY_SET_STEP
, 0, 0);
3539 clientIncOpacity (Client
* c
)
3541 ScreenInfo
*screen_info
;
3542 DisplayInfo
*display_info
;
3544 screen_info
= c
->screen_info
;
3545 display_info
= screen_info
->display_info
;
3547 if (!compositorIsUsable (display_info
))
3552 if ((c
->opacity
< NET_WM_OPAQUE
) && !(c
->opacity_locked
))
3554 guint opacity
= c
->opacity
+ OPACITY_SET_STEP
;
3556 if (opacity
< OPACITY_SET_MIN
)
3558 opacity
= NET_WM_OPAQUE
;
3560 clientSetOpacity (c
, opacity
, 0, 0);
3564 /* Xrandr stuff: on screen size change, make sure all clients are still visible */
3566 clientScreenResize(ScreenInfo
*screen_info
)
3569 GList
*index
, *list_of_windows
;
3572 list_of_windows
= clientGetStackList (screen_info
);
3574 if (!list_of_windows
)
3579 /* Revalidate client struts */
3580 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
3582 c
= (Client
*) index
->data
;
3583 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_HAS_STRUT
))
3585 clientValidateNetStrut (c
);
3589 myScreenGrabPointer (screen_info
, EnterWindowMask
, None
, myDisplayGetCurrentTime (screen_info
->display_info
));
3590 for (index
= list_of_windows
; index
; index
= g_list_next (index
))
3592 unsigned long maximization_flags
= 0L;
3594 c
= (Client
*) index
->data
;
3595 if (!CONSTRAINED_WINDOW (c
))
3600 /* Recompute size and position of maximized windows */
3601 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
| CLIENT_FLAG_MAXIMIZED_VERT
))
3603 /* Too bad, the flags used internally are different from the WIN_STATE_* bits */
3604 maximization_flags
|= FLAG_TEST (c
->flags
,
3605 CLIENT_FLAG_MAXIMIZED_HORIZ
) ? WIN_STATE_MAXIMIZED_HORIZ
: 0;
3606 maximization_flags
|= FLAG_TEST (c
->flags
,
3607 CLIENT_FLAG_MAXIMIZED_VERT
) ? WIN_STATE_MAXIMIZED_VERT
: 0;
3609 /* Force an update by clearing the internal flags */
3610 FLAG_UNSET (c
->flags
, CLIENT_FLAG_MAXIMIZED_HORIZ
| CLIENT_FLAG_MAXIMIZED_VERT
);
3611 clientToggleMaximized (c
, maximization_flags
, FALSE
);
3615 wc
.width
= c
->width
;
3616 wc
.height
= c
->height
;
3617 clientConfigure (c
, &wc
, CWX
| CWY
| CWWidth
| CWHeight
, CFG_NOTIFY
);
3623 clientConfigure (c
, &wc
, CWX
| CWY
, CFG_CONSTRAINED
| CFG_REQUEST
);
3626 myScreenUngrabPointer (screen_info
);
3628 g_list_free (list_of_windows
);
3632 clientDrawOutline (Client
* c
)
3634 TRACE ("entering clientDrawOutline");
3636 XDrawRectangle (clientGetXDisplay (c
), c
->screen_info
->xroot
, c
->screen_info
->box_gc
, frameX (c
), frameY (c
),
3637 frameWidth (c
) - 1, frameHeight (c
) - 1);
3638 if (FLAG_TEST (c
->xfwm_flags
, XFWM_FLAG_HAS_BORDER
)
3639 &&!FLAG_TEST (c
->flags
, CLIENT_FLAG_FULLSCREEN
| CLIENT_FLAG_SHADED
))
3641 XDrawRectangle (clientGetXDisplay (c
), c
->screen_info
->xroot
, c
->screen_info
->box_gc
, c
->x
, c
->y
, c
->width
- 1,
3647 clientSnapPosition (Client
* c
, int prev_x
, int prev_y
)
3649 ScreenInfo
*screen_info
;
3651 int cx
, cy
, i
, delta
;
3652 int disp_x
, disp_y
, disp_max_x
, disp_max_y
;
3653 int frame_x
, frame_y
, frame_height
, frame_width
;
3654 int frame_top
, frame_left
, frame_right
, frame_bottom
;
3655 int frame_x2
, frame_y2
;
3656 int best_frame_x
, best_frame_y
;
3657 int best_delta_x
, best_delta_y
;
3658 int c_frame_x1
, c_frame_x2
, c_frame_y1
, c_frame_y2
;
3662 g_return_if_fail (c
!= NULL
);
3663 TRACE ("entering clientSnapPosition");
3664 TRACE ("Snapping client \"%s\" (0x%lx)", c
->name
, c
->window
);
3666 screen_info
= c
->screen_info
;
3667 best_delta_x
= screen_info
->params
->snap_width
+ 1;
3668 best_delta_y
= screen_info
->params
->snap_width
+ 1;
3670 frame_x
= frameX (c
);
3671 frame_y
= frameY (c
);
3672 frame_height
= frameHeight (c
);
3673 frame_width
= frameWidth (c
);
3674 frame_top
= frameTop (c
);
3675 frame_left
= frameLeft (c
);
3676 frame_right
= frameRight (c
);
3677 frame_bottom
= frameBottom (c
);
3679 cx
= frame_x
+ (frame_width
/ 2);
3680 cy
= frame_y
+ (frame_height
/ 2);
3682 frame_x2
= frame_x
+ frame_width
;
3683 frame_y2
= frame_y
+ frame_height
;
3684 best_frame_x
= frame_x
;
3685 best_frame_y
= frame_y
;
3687 monitor_nbr
= find_monitor_at_point (screen_info
->gscr
, cx
, cy
);
3688 gdk_screen_get_monitor_geometry (screen_info
->gscr
, monitor_nbr
, &rect
);
3692 disp_max_x
= rect
.x
+ rect
.width
;
3693 disp_max_y
= rect
.y
+ rect
.height
;
3695 if (screen_info
->params
->snap_to_border
)
3697 if (abs (disp_x
- frame_x
) < abs (disp_max_x
- frame_x2
))
3699 if (!screen_info
->params
->snap_resist
|| ((frame_x
<= disp_x
) && (c
->x
< prev_x
)))
3701 best_delta_x
= abs (disp_x
- frame_x
);
3702 best_frame_x
= disp_x
;
3707 if (!screen_info
->params
->snap_resist
|| ((frame_x2
>= disp_max_x
) && (c
->x
> prev_x
)))
3709 best_delta_x
= abs (disp_max_x
- frame_x2
);
3710 best_frame_x
= disp_max_x
- frame_width
;
3714 if (abs (disp_y
- frame_y
) < abs (disp_max_y
- frame_y2
))
3716 if (!screen_info
->params
->snap_resist
|| ((frame_y
<= disp_y
) && (c
->y
< prev_y
)))
3718 best_delta_y
= abs (disp_y
- frame_y
);
3719 best_frame_y
= disp_y
;
3724 if (!screen_info
->params
->snap_resist
|| ((frame_y2
>= disp_max_y
) && (c
->y
> prev_y
)))
3726 best_delta_y
= abs (disp_max_y
- frame_y2
);
3727 best_frame_y
= disp_max_y
- frame_height
;
3732 for (c2
= screen_info
->clients
, i
= 0; i
< screen_info
->client_count
; c2
= c2
->next
, i
++)
3734 if (FLAG_TEST (c2
->xfwm_flags
, XFWM_FLAG_VISIBLE
) && (c2
!= c
) &&
3735 (((screen_info
->params
->snap_to_windows
) && (c2
->win_layer
== c
->win_layer
))
3736 || ((screen_info
->params
->snap_to_border
)
3737 && FLAG_TEST (c2
->flags
, CLIENT_FLAG_HAS_STRUT
)
3738 && FLAG_TEST (c2
->xfwm_flags
, XFWM_FLAG_VISIBLE
))))
3740 c_frame_x1
= frameX (c2
);
3741 c_frame_x2
= c_frame_x1
+ frameWidth (c2
);
3742 c_frame_y1
= frameY (c2
);
3743 c_frame_y2
= c_frame_y1
+ frameHeight (c2
);
3745 if ((c_frame_y1
<= frame_y2
) && (c_frame_y2
>= frame_y
))
3747 delta
= abs (c_frame_x2
- frame_x
);
3748 if (delta
< best_delta_x
)
3750 if (!screen_info
->params
->snap_resist
|| ((frame_x
<= c_frame_x2
) && (c
->x
< prev_x
)))
3752 best_delta_x
= delta
;
3753 best_frame_x
= c_frame_x2
;
3757 delta
= abs (c_frame_x1
- frame_x2
);
3758 if (delta
< best_delta_x
)
3760 if (!screen_info
->params
->snap_resist
|| ((frame_x2
>= c_frame_x1
) && (c
->x
> prev_x
)))
3762 best_delta_x
= delta
;
3763 best_frame_x
= c_frame_x1
- frame_width
;
3768 if ((c_frame_x1
<= frame_x2
) && (c_frame_x2
>= frame_x
))
3770 delta
= abs (c_frame_y2
- frame_y
);
3771 if (delta
< best_delta_y
)
3773 if (!screen_info
->params
->snap_resist
|| ((frame_y
<= c_frame_y2
) && (c
->y
< prev_y
)))
3775 best_delta_y
= delta
;
3776 best_frame_y
= c_frame_y2
;
3780 delta
= abs (c_frame_y1
- frame_y2
);
3781 if (delta
< best_delta_y
)
3783 if (!screen_info
->params
->snap_resist
|| ((frame_y2
>= c_frame_y1
) && (c
->y
> prev_y
)))
3785 best_delta_y
= delta
;
3786 best_frame_y
= c_frame_y1
- frame_height
;
3793 if (best_delta_x
<= screen_info
->params
->snap_width
)
3795 c
->x
= best_frame_x
+ frame_left
;
3797 if (best_delta_y
<= screen_info
->params
->snap_width
)
3799 c
->y
= best_frame_y
+ frame_top
;
3803 static eventFilterStatus
3804 clientButtonReleaseFilter (XEvent
* xevent
, gpointer data
)
3806 MoveResizeData
*passdata
= (MoveResizeData
*) data
;
3808 TRACE ("entering clientButtonReleaseFilter");
3810 if ((xevent
->type
== ButtonRelease
) &&
3811 (xevent
->xbutton
.button
== passdata
->button
))
3814 return EVENT_FILTER_STOP
;
3817 return EVENT_FILTER_CONTINUE
;
3820 static eventFilterStatus
3821 clientMoveEventFilter (XEvent
* xevent
, gpointer data
)
3823 static int edge_scroll_x
= 0;
3824 static int edge_scroll_y
= 0;
3825 static gboolean toggled_maximize
= FALSE
;
3826 static Time lastresist
= (Time
) 0;
3827 unsigned long configure_flags
;
3828 ScreenInfo
*screen_info
;
3829 DisplayInfo
*display_info
;
3830 eventFilterStatus status
= EVENT_FILTER_STOP
;
3831 MoveResizeData
*passdata
= (MoveResizeData
*) data
;
3833 gboolean moving
= TRUE
;
3834 gboolean warp_pointer
= FALSE
;
3838 TRACE ("entering clientMoveEventFilter");
3843 screen_info
= c
->screen_info
;
3844 display_info
= screen_info
->display_info
;
3845 configure_flags
= NO_CFG_FLAG
;
3847 /* Update the display time */
3848 myDisplayUpdateCurrentTime (display_info
, xevent
);
3850 if (xevent
->type
== KeyPress
)
3852 while (XCheckMaskEvent (display_info
->dpy
, KeyPressMask
, xevent
))
3854 /* Update the display time */
3855 myDisplayUpdateCurrentTime (display_info
, xevent
);
3858 if ((passdata
->use_keys
) && !FLAG_TEST_ALL(c
->flags
, CLIENT_FLAG_MAXIMIZED
))
3863 if ((screen_info
->params
->snap_to_border
) || (screen_info
->params
->snap_to_windows
))
3865 key_move
= MAX (16, screen_info
->params
->snap_width
+ 1);
3868 if (!passdata
->grab
&& screen_info
->params
->box_move
)
3870 myDisplayGrabServer (display_info
);
3871 passdata
->grab
= TRUE
;
3872 clientDrawOutline (c
);
3874 if (screen_info
->params
->box_move
)
3876 clientDrawOutline (c
);
3878 if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_LEFT
].keycode
)
3880 c
->x
= c
->x
- key_move
;
3882 else if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_RIGHT
].keycode
)
3884 c
->x
= c
->x
+ key_move
;
3886 else if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_UP
].keycode
)
3888 c
->y
= c
->y
- key_move
;
3890 else if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_DOWN
].keycode
)
3892 c
->y
= c
->y
+ key_move
;
3895 clientSnapPosition (c
, prev_x
, prev_y
);
3896 edge
= clientConstrainPos (c
, FALSE
);
3897 if ((edge
) && (screen_info
->params
->wrap_windows
))
3899 int maxx
, maxy
, maxw
, maxh
;
3903 maxw
= screen_info
->width
;
3904 maxh
= screen_info
->height
;
3905 clientMaxSpace (screen_info
, &maxx
, &maxy
, &maxw
, &maxh
);
3907 if (edge
& CLIENT_CONSTRAINED_TOP
)
3909 if (workspaceMove (screen_info
, -1, 0, c
, xevent
->xkey
.time
))
3914 else if (edge
& CLIENT_CONSTRAINED_BOTTOM
)
3916 if (workspaceMove (screen_info
, 1, 0, c
, xevent
->xkey
.time
))
3918 c
->y
= maxy
+ frameTop (c
);
3922 if (edge
& CLIENT_CONSTRAINED_LEFT
)
3924 if (workspaceMove (screen_info
, 0, -1, c
, xevent
->xkey
.time
))
3926 c
->x
= maxx
+ maxw
- frameWidth (c
) + frameRight (c
);
3929 else if (edge
& CLIENT_CONSTRAINED_RIGHT
)
3931 if (workspaceMove (screen_info
, 0, 1, c
, xevent
->xkey
.time
))
3933 c
->x
= maxx
+ frameLeft (c
);
3937 #ifdef SHOW_POSITION
3938 if (passdata
->poswin
)
3940 poswinSetPosition (passdata
->poswin
, c
);
3942 #endif /* SHOW_POSITION */
3943 if (screen_info
->params
->box_move
)
3945 clientDrawOutline (c
);
3951 clientConfigure (c
, &wc
, CWX
| CWY
, configure_flags
);
3955 else if (xevent
->type
== KeyRelease
)
3957 if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_CANCEL
].keycode
)
3960 passdata
->released
= passdata
->use_keys
;
3962 if (screen_info
->params
->box_move
)
3964 clientDrawOutline (c
);
3967 c
->x
= passdata
->cancel_x
;
3968 c
->y
= passdata
->cancel_y
;
3970 if (screen_info
->params
->box_move
)
3972 clientDrawOutline (c
);
3978 clientConfigure (c
, &wc
, CWX
| CWY
, configure_flags
);
3980 if (screen_info
->current_ws
!= passdata
->cancel_workspace
)
3982 workspaceSwitch (screen_info
, passdata
->cancel_workspace
, c
, FALSE
, xevent
->xkey
.time
);
3984 if (toggled_maximize
)
3986 toggled_maximize
= FALSE
;
3987 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED
, FALSE
);
3988 configure_flags
= CFG_FORCE_REDRAW
;
3989 passdata
->move_resized
= TRUE
;
3992 else if (passdata
->use_keys
)
3994 if (IsModifierKey (XLookupKeysym (&xevent
->xkey
, 0)))
4000 else if (xevent
->type
== ButtonRelease
)
4002 if (!passdata
->use_keys
)
4005 passdata
->released
= (xevent
->xbutton
.button
== passdata
->button
);
4008 else if (xevent
->type
== MotionNotify
)
4010 while (XCheckMaskEvent (display_info
->dpy
, ButtonMotionMask
, xevent
))
4012 /* Update the display time */
4013 myDisplayUpdateCurrentTime (display_info
, xevent
);
4015 if (!passdata
->grab
&& screen_info
->params
->box_move
)
4017 myDisplayGrabServer (display_info
);
4018 passdata
->grab
= TRUE
;
4019 clientDrawOutline (c
);
4021 if (screen_info
->params
->box_move
)
4023 clientDrawOutline (c
);
4025 if ((screen_info
->workspace_count
> 1) && !(passdata
->is_transient
))
4027 if ((screen_info
->params
->wrap_windows
) && (screen_info
->params
->wrap_resistance
))
4029 int msx
, msy
, maxx
, maxy
;
4032 msx
= xevent
->xmotion
.x_root
;
4033 msy
= xevent
->xmotion
.y_root
;
4034 maxx
= screen_info
->width
- 1;
4035 maxy
= screen_info
->height
- 1;
4038 warp_pointer
= FALSE
;
4040 if ((msx
== 0) || (msx
== maxx
))
4042 if ((xevent
->xmotion
.time
- lastresist
) > 250) /* ms */
4058 warp_pointer
= TRUE
;
4059 lastresist
= xevent
->xmotion
.time
;
4061 if ((msy
== 0) || (msy
== maxy
))
4063 if ((xevent
->xmotion
.time
- lastresist
) > 250) /* ms */
4079 warp_pointer
= TRUE
;
4080 lastresist
= xevent
->xmotion
.time
;
4083 if (edge_scroll_x
> screen_info
->params
->wrap_resistance
)
4086 if ((msx
== 0) || (msx
== maxx
))
4090 if (workspaceMove (screen_info
, 0, -1, c
, xevent
->xmotion
.time
))
4097 if (workspaceMove (screen_info
, 0, 1, c
, xevent
->xmotion
.time
))
4102 warp_pointer
= TRUE
;
4104 lastresist
= (Time
) 0;
4106 if (edge_scroll_y
> screen_info
->params
->wrap_resistance
)
4109 if ((msy
== 0) || (msy
== maxy
))
4113 if (workspaceMove (screen_info
, -1, 0, c
, xevent
->xmotion
.time
))
4120 if (workspaceMove (screen_info
, 1, 0, c
, xevent
->xmotion
.time
))
4125 warp_pointer
= TRUE
;
4127 lastresist
= (Time
) 0;
4132 XWarpPointer (display_info
->dpy
, None
, None
, 0, 0, 0, 0, rx
, ry
);
4133 XFlush (display_info
->dpy
);
4138 xevent
->xmotion
.x_root
= msx
;
4139 xevent
->xmotion
.y_root
= msy
;
4143 if (FLAG_TEST_ALL(c
->flags
, CLIENT_FLAG_MAXIMIZED
)
4144 && (screen_info
->params
->restore_on_move
))
4146 if (xevent
->xmotion
.y_root
- passdata
->my
> 15)
4148 /* to keep the distance from the edges of the window proportional. */
4149 double xratio
, yratio
;
4151 xratio
= (xevent
->xmotion
.x_root
- c
->x
)/(double)c
->width
;
4152 yratio
= (xevent
->xmotion
.y_root
- c
->y
)/(double)c
->width
;
4154 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED
, FALSE
);
4155 passdata
->move_resized
= TRUE
;
4156 passdata
->ox
= c
->x
;
4157 passdata
->mx
= CLAMP(c
->x
+ c
->width
* xratio
, c
->x
, c
->x
+ c
->width
);
4158 passdata
->oy
= c
->y
;
4159 passdata
->my
= c
->y
- frameTop(c
) / 2;
4160 configure_flags
= CFG_FORCE_REDRAW
;
4161 toggled_maximize
= TRUE
;
4165 xevent
->xmotion
.x_root
= c
->x
- passdata
->ox
+ passdata
->mx
;
4166 xevent
->xmotion
.y_root
= c
->y
- passdata
->oy
+ passdata
->my
;
4170 c
->x
= passdata
->ox
+ (xevent
->xmotion
.x_root
- passdata
->mx
);
4171 c
->y
= passdata
->oy
+ (xevent
->xmotion
.y_root
- passdata
->my
);
4173 clientSnapPosition (c
, prev_x
, prev_y
);
4174 if (screen_info
->params
->restore_on_move
)
4176 if ((clientConstrainPos (c
, FALSE
) & CLIENT_CONSTRAINED_TOP
) && toggled_maximize
)
4178 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED
, FALSE
);
4179 configure_flags
= CFG_FORCE_REDRAW
;
4180 toggled_maximize
= FALSE
;
4181 passdata
->move_resized
= TRUE
;
4183 Update "passdata->my" to the current value to
4184 allow "restore on move" to keep working next time
4186 passdata
->my
= c
->y
- frameTop(c
) / 2;
4191 clientConstrainPos(c
, FALSE
);
4194 #ifdef SHOW_POSITION
4195 if (passdata
->poswin
)
4197 poswinSetPosition (passdata
->poswin
, c
);
4199 #endif /* SHOW_POSITION */
4200 if (screen_info
->params
->box_move
)
4202 clientDrawOutline (c
);
4206 int changes
= CWX
| CWY
;
4208 if (passdata
->move_resized
)
4210 wc
.width
= c
->width
;
4211 wc
.height
= c
->height
;
4212 changes
|= CWWidth
| CWHeight
;
4213 passdata
->move_resized
= FALSE
;
4218 clientConfigure (c
, &wc
, changes
, configure_flags
);
4221 else if ((xevent
->type
== UnmapNotify
) && (xevent
->xunmap
.window
== c
->window
))
4225 else if ((xevent
->type
== EnterNotify
) || (xevent
->type
== LeaveNotify
))
4227 /* Ignore enter/leave events */
4231 status
= EVENT_FILTER_CONTINUE
;
4234 TRACE ("leaving clientMoveEventFilter");
4238 TRACE ("event loop now finished");
4241 toggled_maximize
= FALSE
;
4249 clientMove (Client
* c
, XEvent
* ev
)
4251 ScreenInfo
*screen_info
;
4252 DisplayInfo
*display_info
;
4254 MoveResizeData passdata
;
4258 g_return_if_fail (c
!= NULL
);
4259 TRACE ("entering clientDoMove");
4260 TRACE ("moving client \"%s\" (0x%lx)", c
->name
, c
->window
);
4262 screen_info
= c
->screen_info
;
4263 display_info
= screen_info
->display_info
;
4265 changes
= CWX
| CWY
;
4268 passdata
.cancel_x
= passdata
.ox
= c
->x
;
4269 passdata
.cancel_y
= passdata
.oy
= c
->y
;
4270 passdata
.cancel_workspace
= c
->win_workspace
;
4271 passdata
.use_keys
= FALSE
;
4272 passdata
.grab
= FALSE
;
4273 passdata
.released
= FALSE
;
4274 passdata
.button
= ev
->xbutton
.button
;
4275 passdata
.is_transient
= clientIsValidTransientOrModal (c
);
4276 passdata
.move_resized
= FALSE
;
4278 if (ev
->type
== KeyPress
)
4280 passdata
.released
= passdata
.use_keys
= TRUE
;
4281 passdata
.mx
= ev
->xkey
.x_root
;
4282 passdata
.my
= ev
->xkey
.y_root
;
4284 else if (ev
->type
== ButtonPress
)
4286 passdata
.mx
= ev
->xbutton
.x_root
;
4287 passdata
.my
= ev
->xbutton
.y_root
;
4291 getMouseXY (screen_info
, screen_info
->xroot
, &passdata
.mx
, &passdata
.my
);
4294 g1
= myScreenGrabKeyboard (screen_info
, myDisplayGetCurrentTime (display_info
));
4295 g2
= myScreenGrabPointer (screen_info
, ButtonMotionMask
| ButtonReleaseMask
,
4296 myDisplayGetCursorMove (display_info
),
4297 myDisplayGetCurrentTime (display_info
));
4300 TRACE ("grab failed in clientMove");
4303 myScreenUngrabKeyboard (screen_info
);
4304 myScreenUngrabPointer (screen_info
);
4309 passdata
.poswin
= NULL
;
4310 #ifdef SHOW_POSITION
4311 passdata
.poswin
= poswinCreate(screen_info
->gscr
);
4312 poswinSetPosition (passdata
.poswin
, c
);
4313 poswinShow (passdata
.poswin
);
4314 #endif /* SHOW_POSITION */
4316 /* Set window translucent while moving, looks nice */
4317 if ((screen_info
->params
->move_opacity
< 100) && !(screen_info
->params
->box_move
) && !(c
->opacity_locked
))
4319 clientSetOpacity (c
, c
->opacity
, OPACITY_MOVE
, OPACITY_MOVE
);
4323 * Need to remove the sidewalk windows while moving otherwise
4324 * the motion events aren't reported on screen edges
4326 placeSidewalks(screen_info
, FALSE
);
4328 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
);
4329 TRACE ("entering move loop");
4330 eventFilterPush (display_info
->xfilter
, clientMoveEventFilter
, &passdata
);
4331 if (passdata
.use_keys
)
4333 XPutBackEvent (display_info
->dpy
, ev
);
4336 eventFilterPop (display_info
->xfilter
);
4337 TRACE ("leaving move loop");
4338 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
);
4340 /* Put back the sidewalks as they ought to be */
4341 placeSidewalks(screen_info
, screen_info
->params
->wrap_workspaces
);
4343 #ifdef SHOW_POSITION
4344 if (passdata
.poswin
)
4346 poswinDestroy (passdata
.poswin
);
4348 #endif /* SHOW_POSITION */
4349 if (passdata
.grab
&& screen_info
->params
->box_move
)
4351 clientDrawOutline (c
);
4353 /* Set window opacity to its original value */
4354 clientSetOpacity (c
, c
->opacity
, OPACITY_MOVE
, 0);
4358 if (passdata
.move_resized
)
4360 wc
.width
= c
->width
;
4361 wc
.height
= c
->height
;
4362 changes
|= CWWidth
| CWHeight
;
4364 clientConfigure (c
, &wc
, changes
, NO_CFG_FLAG
);
4366 myScreenUngrabKeyboard (screen_info
);
4367 if (!passdata
.released
)
4369 /* If this is a drag-move, wait for the button to be released.
4370 * If we don't, we might get release events in the wrong place.
4372 eventFilterPush (display_info
->xfilter
, clientButtonReleaseFilter
, &passdata
);
4374 eventFilterPop (display_info
->xfilter
);
4376 myScreenUngrabPointer (screen_info
);
4378 if (passdata
.grab
&& screen_info
->params
->box_move
)
4380 myDisplayUngrabServer (display_info
);
4385 clientResizeConfigure (Client
*c
, int px
, int py
, int pw
, int ph
)
4387 ScreenInfo
*screen_info
;
4388 DisplayInfo
*display_info
;
4390 unsigned long value_mask
;
4392 screen_info
= c
->screen_info
;
4393 display_info
= screen_info
->display_info
;
4406 value_mask
|= CWWidth
;
4408 if (c
->height
!= ph
)
4410 value_mask
|= CWHeight
;
4418 if (!c
->xsync_waiting
)
4420 if ((display_info
->have_xsync
) && (c
->xsync_enabled
) && (c
->xsync_counter
)
4421 && (value_mask
& (CWWidth
| CWHeight
)))
4423 clientXSyncRequest (c
);
4425 #endif /* HAVE_XSYNC */
4428 wc
.width
= c
->width
;
4429 wc
.height
= c
->height
;
4430 clientConfigure (c
, &wc
, value_mask
, NO_CFG_FLAG
);
4433 #endif /* HAVE_XSYNC */
4436 static eventFilterStatus
4437 clientResizeEventFilter (XEvent
* xevent
, gpointer data
)
4439 ScreenInfo
*screen_info
;
4440 DisplayInfo
*display_info
;
4443 MoveResizeData
*passdata
;
4444 eventFilterStatus status
;
4445 int prev_x
, prev_y
, prev_width
, prev_height
;
4446 int cx
, cy
, disp_x
, disp_y
, disp_max_x
, disp_max_y
;
4447 int frame_x
, frame_y
, frame_height
, frame_width
;
4448 int frame_top
, frame_left
, frame_right
, frame_bottom
;
4449 int move_top
, move_bottom
, move_left
, move_right
;
4455 TRACE ("entering clientResizeEventFilter");
4457 passdata
= (MoveResizeData
*) data
;
4459 screen_info
= c
->screen_info
;
4460 display_info
= screen_info
->display_info
;
4461 status
= EVENT_FILTER_STOP
;
4464 frame_x
= frameX (c
);
4465 frame_y
= frameY (c
);
4466 frame_height
= frameHeight (c
);
4467 frame_width
= frameWidth (c
);
4468 frame_top
= frameTop (c
);
4469 frame_left
= frameLeft (c
);
4470 frame_right
= frameRight (c
);
4471 frame_bottom
= frameBottom (c
);
4472 min_visible
= MAX (frame_top
, CLIENT_MIN_VISIBLE
);
4474 cx
= frame_x
+ (frame_width
/ 2);
4475 cy
= frame_y
+ (frame_height
/ 2);
4477 move_top
= ((passdata
->corner
== CORNER_TOP_RIGHT
)
4478 || (passdata
->corner
== CORNER_TOP_LEFT
)
4479 || (passdata
->corner
== CORNER_COUNT
+ SIDE_TOP
)) ?
4481 move_bottom
= ((passdata
->corner
== CORNER_BOTTOM_RIGHT
)
4482 || (passdata
->corner
== CORNER_BOTTOM_LEFT
)
4483 || (passdata
->corner
== CORNER_COUNT
+ SIDE_BOTTOM
)) ?
4485 move_right
= ((passdata
->corner
== CORNER_TOP_RIGHT
)
4486 || (passdata
->corner
== CORNER_BOTTOM_RIGHT
)
4487 || (passdata
->corner
== CORNER_COUNT
+ SIDE_RIGHT
)) ?
4489 move_left
= ((passdata
->corner
== CORNER_TOP_LEFT
)
4490 || (passdata
->corner
== CORNER_BOTTOM_LEFT
)
4491 || (passdata
->corner
== CORNER_COUNT
+ SIDE_LEFT
)) ?
4494 monitor_nbr
= find_monitor_at_point (screen_info
->gscr
, cx
, cy
);
4495 gdk_screen_get_monitor_geometry (screen_info
->gscr
, monitor_nbr
, &rect
);
4499 disp_max_x
= rect
.x
+ rect
.width
;
4500 disp_max_y
= rect
.y
+ rect
.height
;
4502 /* Store previous values in case the resize puts the window title off bounds */
4505 prev_width
= c
->width
;
4506 prev_height
= c
->height
;
4508 /* Update the display time */
4509 myDisplayUpdateCurrentTime (display_info
, xevent
);
4511 if (xevent
->type
== KeyPress
)
4513 while (XCheckMaskEvent (display_info
->dpy
, KeyPressMask
, xevent
))
4515 /* Update the display time */
4516 myDisplayUpdateCurrentTime (display_info
, xevent
);
4519 if (passdata
->use_keys
)
4521 int key_width_inc
, key_height_inc
;
4524 key_width_inc
= c
->size
->width_inc
;
4525 key_height_inc
= c
->size
->height_inc
;
4527 if (key_width_inc
< 10)
4529 key_width_inc
= ((int) (10 / key_width_inc
)) * key_width_inc
;
4531 if (key_height_inc
< 10)
4533 key_height_inc
= ((int) (10 / key_height_inc
)) * key_height_inc
;
4535 if (!passdata
->grab
&& screen_info
->params
->box_resize
)
4537 myDisplayGrabServer (display_info
);
4538 passdata
->grab
= TRUE
;
4539 clientDrawOutline (c
);
4541 if (screen_info
->params
->box_resize
)
4543 clientDrawOutline (c
);
4546 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
)
4547 && (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_UP
].keycode
))
4549 c
->height
= c
->height
- key_height_inc
;
4550 corner
= CORNER_COUNT
+ SIDE_BOTTOM
;
4552 else if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
)
4553 && (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_DOWN
].keycode
))
4555 c
->height
= c
->height
+ key_height_inc
;
4556 corner
= CORNER_COUNT
+ SIDE_BOTTOM
;
4558 else if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_LEFT
].keycode
)
4560 c
->width
= c
->width
- key_width_inc
;
4561 corner
= CORNER_COUNT
+ SIDE_RIGHT
;
4563 else if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_MOVE_RIGHT
].keycode
)
4565 c
->width
= c
->width
+ key_width_inc
;
4566 corner
= CORNER_COUNT
+ SIDE_RIGHT
;
4570 clientConstrainRatio (c
, &c
->width
, &c
->height
, corner
);
4572 if ((c
->x
+ c
->width
< disp_x
+ min_visible
)
4573 || (c
->x
+ c
->width
< screen_info
->margins
[STRUTS_LEFT
] + min_visible
))
4575 c
->width
= prev_width
;
4577 if ((c
->y
+ c
->height
< disp_y
+ min_visible
)
4578 || (c
->y
+ c
->height
< screen_info
->margins
[STRUTS_TOP
] + min_visible
))
4580 c
->height
= prev_height
;
4582 if (passdata
->poswin
)
4584 poswinSetPosition (passdata
->poswin
, c
);
4586 if (screen_info
->params
->box_resize
)
4588 clientDrawOutline (c
);
4592 clientResizeConfigure (c
, prev_x
, prev_y
, prev_width
, prev_height
);
4596 else if (xevent
->type
== KeyRelease
)
4598 if (xevent
->xkey
.keycode
== screen_info
->params
->keys
[KEY_CANCEL
].keycode
)
4601 passdata
->released
= passdata
->use_keys
;
4603 if (screen_info
->params
->box_resize
)
4605 clientDrawOutline (c
);
4608 /* restore the pre-resize position & size */
4611 c
->x
+= c
->width
- passdata
->cancel_x
;
4615 c
->y
+= c
->height
- passdata
->cancel_y
;
4617 c
->width
= passdata
->cancel_x
;
4618 c
->height
= passdata
->cancel_y
;
4619 if (screen_info
->params
->box_resize
)
4621 clientDrawOutline (c
);
4625 clientResizeConfigure (c
, prev_x
, prev_y
, prev_width
, prev_height
);
4628 else if (passdata
->use_keys
)
4630 if (IsModifierKey (XLookupKeysym (&xevent
->xkey
, 0)))
4636 else if (xevent
->type
== MotionNotify
)
4638 while (XCheckMaskEvent (display_info
->dpy
, ButtonMotionMask
| PointerMotionMask
, xevent
))
4640 /* Update the display time */
4641 myDisplayUpdateCurrentTime (display_info
, xevent
);
4644 if (xevent
->type
== ButtonRelease
)
4648 if (!passdata
->grab
&& screen_info
->params
->box_resize
)
4650 myDisplayGrabServer (display_info
);
4651 passdata
->grab
= TRUE
;
4652 clientDrawOutline (c
);
4654 if (screen_info
->params
->box_resize
)
4656 clientDrawOutline (c
);
4658 passdata
->oldw
= c
->width
;
4659 passdata
->oldh
= c
->height
;
4663 c
->width
= passdata
->ox
- (xevent
->xmotion
.x_root
- passdata
->mx
);
4665 else if (move_right
)
4667 c
->width
= passdata
->ox
+ (xevent
->xmotion
.x_root
- passdata
->mx
);
4669 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
))
4673 c
->height
= passdata
->oy
- (xevent
->xmotion
.y_root
- passdata
->my
);
4675 else if (move_bottom
)
4677 c
->height
= passdata
->oy
+ (xevent
->xmotion
.y_root
- passdata
->my
);
4680 clientConstrainRatio (c
, &c
->width
, &c
->height
, passdata
->corner
);
4682 clientSetWidth (c
, c
->width
);
4685 c
->x
= c
->x
- (c
->width
- passdata
->oldw
);
4686 frame_x
= frameX (c
);
4689 clientSetHeight (c
, c
->height
);
4690 if (!FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
) && move_top
)
4692 c
->y
= c
->y
- (c
->height
- passdata
->oldh
);
4693 frame_y
= frameY (c
);
4698 if ((c
->y
> MAX (disp_max_y
- min_visible
, screen_info
->height
- screen_info
->margins
[STRUTS_BOTTOM
] - min_visible
))
4699 || (!clientCkeckTitle (c
) && (frame_y
< screen_info
->margins
[STRUTS_TOP
])))
4701 temp
= c
->y
+ c
->height
;
4702 c
->y
= CLAMP (c
->y
, screen_info
->margins
[STRUTS_TOP
] + frame_top
,
4703 MAX (disp_max_y
- min_visible
, screen_info
->height
- screen_info
->margins
[STRUTS_BOTTOM
] - min_visible
));
4704 clientSetHeight (c
, temp
- c
->y
);
4705 c
->y
= temp
- c
->height
;
4707 else if (frame_y
< 0)
4709 temp
= c
->y
+ c
->height
;
4711 clientSetHeight (c
, temp
- c
->y
);
4712 c
->y
= temp
- c
->height
;
4715 else if (move_bottom
)
4717 if (c
->y
+ c
->height
< MAX (disp_y
+ min_visible
, screen_info
->margins
[STRUTS_TOP
] + min_visible
))
4719 temp
= MAX (disp_y
+ min_visible
, screen_info
->margins
[STRUTS_TOP
] + min_visible
);
4720 clientSetHeight (c
, temp
- c
->y
);
4725 if (c
->x
> MIN (disp_max_x
- min_visible
, screen_info
->width
- screen_info
->margins
[STRUTS_RIGHT
] - min_visible
))
4727 temp
= c
->x
+ c
->width
;
4728 c
->x
= MIN (disp_max_x
- min_visible
, screen_info
->width
- screen_info
->margins
[STRUTS_RIGHT
] - min_visible
);
4729 clientSetWidth (c
, temp
- c
->x
);
4730 c
->x
= temp
- c
->width
;
4733 else if (move_right
)
4735 if (c
->x
+ c
->width
< MAX (disp_x
+ min_visible
, screen_info
->margins
[STRUTS_LEFT
] + min_visible
))
4737 temp
= MAX (disp_x
+ min_visible
, screen_info
->margins
[STRUTS_LEFT
] + min_visible
);
4738 clientSetWidth (c
, temp
- c
->x
);
4742 if (passdata
->poswin
)
4744 poswinSetPosition (passdata
->poswin
, c
);
4746 if (screen_info
->params
->box_resize
)
4748 clientDrawOutline (c
);
4752 clientResizeConfigure (c
, prev_x
, prev_y
, prev_width
, prev_height
);
4756 else if (xevent
->type
== ButtonRelease
)
4758 if (!passdata
->use_keys
)
4761 passdata
->released
= (xevent
->xbutton
.button
== passdata
->button
);
4764 else if ((xevent
->type
== UnmapNotify
) && (xevent
->xunmap
.window
== c
->window
))
4768 else if ((xevent
->type
== EnterNotify
) || (xevent
->type
== LeaveNotify
))
4770 /* Ignore enter/leave events */
4774 status
= EVENT_FILTER_CONTINUE
;
4777 TRACE ("leaving clientResizeEventFilter");
4781 TRACE ("event loop now finished");
4789 clientResize (Client
* c
, int corner
, XEvent
* ev
)
4791 ScreenInfo
*screen_info
;
4792 DisplayInfo
*display_info
;
4794 MoveResizeData passdata
;
4798 g_return_if_fail (c
!= NULL
);
4799 TRACE ("entering clientResize");
4800 TRACE ("resizing client \"%s\" (0x%lx)", c
->name
, c
->window
);
4802 screen_info
= c
->screen_info
;
4803 display_info
= screen_info
->display_info
;
4805 if (FLAG_TEST_ALL (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
4806 && (screen_info
->params
->borderless_maximize
))
4812 passdata
.cancel_x
= passdata
.ox
= c
->width
;
4813 passdata
.cancel_y
= passdata
.oy
= c
->height
;
4814 passdata
.use_keys
= FALSE
;
4815 passdata
.grab
= FALSE
;
4816 passdata
.released
= FALSE
;
4817 passdata
.button
= ev
->xbutton
.button
;
4818 passdata
.corner
= corner
;
4822 if (ev
->type
== KeyPress
)
4824 passdata
.released
= passdata
.use_keys
= TRUE
;
4825 passdata
.mx
= ev
->xkey
.x_root
;
4826 passdata
.my
= ev
->xkey
.y_root
;
4828 else if (ev
->type
== ButtonPress
)
4830 passdata
.mx
= ev
->xbutton
.x_root
;
4831 passdata
.my
= ev
->xbutton
.y_root
;
4835 getMouseXY (screen_info
, screen_info
->xroot
, &passdata
.mx
, &passdata
.my
);
4838 g1
= myScreenGrabKeyboard (screen_info
, myDisplayGetCurrentTime (display_info
));
4839 g2
= myScreenGrabPointer (screen_info
, ButtonMotionMask
| ButtonReleaseMask
,
4840 myDisplayGetCursorResize(display_info
, passdata
.corner
),
4841 myDisplayGetCurrentTime (display_info
));
4845 TRACE ("grab failed in clientResize");
4848 myScreenUngrabKeyboard (screen_info
);
4849 myScreenUngrabPointer (screen_info
);
4854 passdata
.poswin
= NULL
;
4855 #ifndef SHOW_POSITION
4856 if ((c
->size
->width_inc
> 1) || (c
->size
->height_inc
> 1))
4857 #endif /* SHOW_POSITION */
4859 passdata
.poswin
= poswinCreate(screen_info
->gscr
);
4860 poswinSetPosition (passdata
.poswin
, c
);
4861 poswinShow (passdata
.poswin
);
4865 clientXSyncEnable (c
);
4866 #endif /* HAVE_XSYNC */
4868 /* Set window translucent while resizing, doesn't looks too nice :( */
4869 if ((screen_info
->params
->resize_opacity
< 100) && !(screen_info
->params
->box_resize
) && !(c
->opacity_locked
))
4871 clientSetOpacity (c
, c
->opacity
, OPACITY_RESIZE
, OPACITY_RESIZE
);
4874 FLAG_SET (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
);
4875 TRACE ("entering resize loop");
4876 eventFilterPush (display_info
->xfilter
, clientResizeEventFilter
, &passdata
);
4877 if (passdata
.use_keys
)
4879 XPutBackEvent (display_info
->dpy
, ev
);
4882 eventFilterPop (display_info
->xfilter
);
4883 TRACE ("leaving resize loop");
4884 FLAG_UNSET (c
->xfwm_flags
, XFWM_FLAG_MOVING_RESIZING
);
4886 if (passdata
.poswin
)
4888 poswinDestroy (passdata
.poswin
);
4890 if (passdata
.grab
&& screen_info
->params
->box_resize
)
4892 clientDrawOutline (c
);
4894 /* Set window opacity to its original value */
4895 clientSetOpacity (c
, c
->opacity
, OPACITY_RESIZE
, 0);
4897 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED
) &&
4898 ((w_orig
!= c
->width
) || (h_orig
!= c
->height
)))
4900 clientRemoveMaximizeFlag (c
);
4905 wc
.width
= c
->width
;
4906 wc
.height
= c
->height
;
4907 clientConfigure (c
, &wc
, CWX
| CWY
| CWHeight
| CWWidth
, NO_CFG_FLAG
);
4909 clientXSyncClearTimeout (c
);
4910 c
->xsync_waiting
= FALSE
;
4911 #endif /* HAVE_XSYNC */
4913 myScreenUngrabKeyboard (screen_info
);
4914 if (!passdata
.released
)
4916 /* If this is a drag-resize, wait for the button to be released.
4917 * If we don't, we might get release events in the wrong place.
4919 eventFilterPush (display_info
->xfilter
, clientButtonReleaseFilter
, &passdata
);
4921 eventFilterPop (display_info
->xfilter
);
4923 myScreenUngrabPointer (screen_info
);
4925 if (passdata
.grab
&& screen_info
->params
->box_resize
)
4927 myDisplayUngrabServer (display_info
);
4931 static eventFilterStatus
4932 clientCycleEventFilter (XEvent
* xevent
, gpointer data
)
4934 ScreenInfo
*screen_info
;
4935 DisplayInfo
*display_info
;
4936 ClientCycleData
*passdata
;
4937 Client
*c
, *removed
;
4938 eventFilterStatus status
;
4942 gboolean key_pressed
, cycling
, gone
;
4944 TRACE ("entering clientCycleEventFilter");
4946 passdata
= (ClientCycleData
*) data
;
4947 if (passdata
->c
== NULL
)
4949 return EVENT_FILTER_CONTINUE
;
4950 /* will never be executed */
4951 /* gtk_main_quit (); */
4955 screen_info
= c
->screen_info
;
4956 display_info
= screen_info
->display_info
;
4957 cycle
= screen_info
->params
->keys
[KEY_CYCLE_WINDOWS
].keycode
;
4958 cancel
= screen_info
->params
->keys
[KEY_CANCEL
].keycode
;
4959 modifier
= screen_info
->params
->keys
[KEY_CYCLE_WINDOWS
].modifier
;
4960 key_pressed
= ((xevent
->type
== KeyPress
) && ((xevent
->xkey
.keycode
== cycle
) ||
4961 (xevent
->xkey
.keycode
== cancel
)));
4962 status
= EVENT_FILTER_STOP
;
4966 /* Update the display time */
4967 myDisplayUpdateCurrentTime (display_info
, xevent
);
4969 switch (xevent
->type
)
4972 removed
= myScreenGetClientFromWindow (screen_info
, ((XDestroyWindowEvent
*) xevent
)->window
, SEARCH_WINDOW
);
4973 gone
|= (c
== removed
);
4974 c
= tabwinRemoveClient(passdata
->tabwin
, removed
);
4976 status
= EVENT_FILTER_CONTINUE
;
4979 removed
= myScreenGetClientFromWindow (screen_info
, ((XUnmapEvent
*) xevent
)->window
, SEARCH_WINDOW
);
4980 gone
|= (c
== removed
);
4981 c
= tabwinRemoveClient(passdata
->tabwin
, removed
);
4983 status
= EVENT_FILTER_CONTINUE
;
4986 if (gone
|| key_pressed
)
4992 if (xevent
->xkey
.keycode
== cancel
)
4994 c2
= tabwinGetHead (passdata
->tabwin
);
4997 /* If KEY_CYCLE_WINDOWS has Shift, then do not reverse */
4998 else if (!(modifier
& ShiftMask
) && (xevent
->xkey
.state
& ShiftMask
))
5000 TRACE ("Cycle: previous");
5001 c2
= tabwinSelectPrev(passdata
->tabwin
);
5005 TRACE ("Cycle: next");
5006 c2
= tabwinSelectNext(passdata
->tabwin
);
5014 /* If last key press event had not our modifier pressed, finish cycling */
5015 if (!(xevent
->xkey
.state
& modifier
))
5025 wireframeUpdate (c
, passdata
->wireframe
);
5036 int keysym
= XLookupKeysym (&xevent
->xkey
, 0);
5038 if (!(xevent
->xkey
.state
& modifier
) ||
5039 (IsModifierKey(keysym
) && (keysym
!= XK_Shift_L
) && (keysym
!= XK_Shift_R
)))
5052 status
= EVENT_FILTER_CONTINUE
;
5058 TRACE ("event loop now finished");
5066 clientCycle (Client
* c
, XEvent
* ev
)
5068 ScreenInfo
*screen_info
;
5069 DisplayInfo
*display_info
;
5070 ClientCycleData passdata
;
5073 g_return_if_fail (c
!= NULL
);
5074 TRACE ("entering clientCycle");
5076 screen_info
= c
->screen_info
;
5077 display_info
= screen_info
->display_info
;
5079 g1
= myScreenGrabKeyboard (screen_info
, myDisplayGetCurrentTime (display_info
));
5080 g2
= myScreenGrabPointer (screen_info
, NoEventMask
, None
, myDisplayGetCurrentTime (display_info
));
5084 TRACE ("grab failed in clientCycle");
5087 myScreenUngrabKeyboard (screen_info
);
5088 myScreenUngrabPointer (screen_info
);
5093 if (screen_info
->params
->cycle_hidden
)
5095 passdata
.cycle_range
= INCLUDE_HIDDEN
;
5099 passdata
.cycle_range
= 0;
5101 if (!screen_info
->params
->cycle_minimum
)
5103 passdata
.cycle_range
|= INCLUDE_SKIP_TASKBAR
| INCLUDE_SKIP_PAGER
;
5105 if (screen_info
->params
->cycle_workspaces
)
5107 passdata
.cycle_range
|= INCLUDE_ALL_WORKSPACES
;
5109 passdata
.c
= clientGetNext (c
, passdata
.cycle_range
);
5111 /* If there is one single client, and if it's eligible for focus, use it */
5112 if ((passdata
.c
== NULL
) && (c
!= clientGetFocus()) &&
5113 clientSelectMask (c
, passdata
.cycle_range
, WINDOW_REGULAR_FOCUSABLE
))
5120 TRACE ("entering cycle loop");
5121 passdata
.wireframe
= wireframeCreate (passdata
.c
);
5122 passdata
.tabwin
= tabwinCreate (passdata
.c
->screen_info
->gscr
, c
,
5123 passdata
.c
, passdata
.cycle_range
,
5124 screen_info
->params
->cycle_workspaces
);
5125 eventFilterPush (display_info
->xfilter
, clientCycleEventFilter
, &passdata
);
5127 eventFilterPop (display_info
->xfilter
);
5128 TRACE ("leaving cycle loop");
5129 tabwinDestroy (passdata
.tabwin
);
5130 g_free (passdata
.tabwin
);
5131 wireframeDelete (screen_info
, passdata
.wireframe
);
5132 updateXserverTime (display_info
);
5141 workspace
= c
->win_workspace
;
5142 focused
= clientGetFocus ();
5144 if (workspace
!= screen_info
->current_ws
)
5146 workspaceSwitch (screen_info
, workspace
, c
, FALSE
, myDisplayGetCurrentTime (display_info
));
5149 if ((focused
) && (passdata
.c
!= focused
))
5151 clientClearAllShowDesktop (screen_info
);
5152 clientAdjustFullscreenLayer (focused
, FALSE
);
5155 clientShow (c
, TRUE
);
5156 clientSetFocus (screen_info
, c
, myDisplayGetCurrentTime (display_info
), NO_FOCUS_FLAG
);
5157 clientRaise (c
, None
);
5160 myScreenUngrabKeyboard (screen_info
);
5161 myScreenUngrabPointer (screen_info
);
5164 static eventFilterStatus
5165 clientButtonPressEventFilter (XEvent
* xevent
, gpointer data
)
5167 ScreenInfo
*screen_info
;
5168 DisplayInfo
*display_info
;
5170 ButtonPressData
*passdata
;
5171 eventFilterStatus status
;
5175 passdata
= (ButtonPressData
*) data
;
5179 screen_info
= c
->screen_info
;
5180 display_info
= screen_info
->display_info
;
5182 /* Update the display time */
5183 myDisplayUpdateCurrentTime (display_info
, xevent
);
5185 status
= EVENT_FILTER_STOP
;
5188 if (xevent
->type
== EnterNotify
)
5190 c
->button_status
[b
] = BUTTON_STATE_PRESSED
;
5191 frameDraw (c
, FALSE
);
5193 else if (xevent
->type
== LeaveNotify
)
5195 c
->button_status
[b
] = BUTTON_STATE_NORMAL
;
5196 frameDraw (c
, FALSE
);
5198 else if (xevent
->type
== ButtonRelease
)
5202 else if ((xevent
->type
== UnmapNotify
) && (xevent
->xunmap
.window
== c
->window
))
5205 c
->button_status
[b
] = BUTTON_STATE_NORMAL
;
5207 else if ((xevent
->type
== KeyPress
) || (xevent
->type
== KeyRelease
))
5212 status
= EVENT_FILTER_CONTINUE
;
5217 TRACE ("event loop now finished");
5225 clientButtonPress (Client
* c
, Window w
, XButtonEvent
* bev
)
5227 ScreenInfo
*screen_info
;
5228 DisplayInfo
*display_info
;
5229 ButtonPressData passdata
;
5232 g_return_if_fail (c
!= NULL
);
5233 TRACE ("entering clientButtonPress");
5235 for (b
= 0; b
< BUTTON_COUNT
; b
++)
5237 if (MYWINDOW_XWINDOW (c
->buttons
[b
]) == w
)
5243 screen_info
= c
->screen_info
;
5244 display_info
= screen_info
->display_info
;
5246 g1
= XGrabPointer (display_info
->dpy
, w
, FALSE
,
5247 ButtonReleaseMask
| EnterWindowMask
| LeaveWindowMask
,
5248 GrabModeAsync
, GrabModeAsync
,
5249 screen_info
->xroot
, None
,
5250 myDisplayGetCurrentTime (display_info
));
5252 if (g1
!= GrabSuccess
)
5254 TRACE ("grab failed in clientButtonPress");
5256 if (g1
== GrabSuccess
)
5258 XUngrabKeyboard (display_info
->dpy
, myDisplayGetCurrentTime (display_info
));
5266 c
->button_status
[b
] = BUTTON_STATE_PRESSED
;
5267 frameDraw (c
, FALSE
);
5269 TRACE ("entering button press loop");
5270 eventFilterPush (display_info
->xfilter
, clientButtonPressEventFilter
, &passdata
);
5272 eventFilterPop (display_info
->xfilter
);
5273 TRACE ("leaving button press loop");
5275 XUngrabPointer (display_info
->dpy
, myDisplayGetCurrentTime (display_info
));
5277 if (c
->button_status
[b
] == BUTTON_STATE_PRESSED
)
5280 * Button was pressed at the time, means the pointer was still within
5281 * the button, so return to prelight if available, normal otherwise.
5283 if (!xfwmPixmapNone(clientGetButtonPixmap(c
, b
, PRELIGHT
)))
5285 c
->button_status
[b
] = BUTTON_STATE_PRELIGHT
;
5289 c
->button_status
[b
] = BUTTON_STATE_NORMAL
;
5295 if (CLIENT_CAN_HIDE_WINDOW (c
))
5297 clientHide (c
, c
->win_workspace
, TRUE
);
5303 case MAXIMIZE_BUTTON
:
5304 if (CLIENT_CAN_MAXIMIZE_WINDOW (c
))
5306 if (bev
->button
== Button1
)
5308 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED
, TRUE
);
5310 else if (bev
->button
== Button2
)
5312 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED_VERT
, TRUE
);
5314 else if (bev
->button
== Button3
)
5316 clientToggleMaximized (c
, WIN_STATE_MAXIMIZED_HORIZ
, TRUE
);
5321 clientToggleShaded (c
);
5324 clientToggleSticky (c
, TRUE
);
5329 frameDraw (c
, FALSE
);
5334 clientGetButtonPixmap (Client
* c
, int button
, int state
)
5336 ScreenInfo
*screen_info
;
5338 screen_info
= c
->screen_info
;
5342 if ((screen_info
->params
->show_app_icon
)
5343 && (!xfwmPixmapNone(&c
->appmenu
[state
])))
5345 return &c
->appmenu
[state
];
5349 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_SHADED
)
5350 && (!xfwmPixmapNone(&screen_info
->buttons
[SHADE_BUTTON
][state
+ STATE_TOGGLED
])))
5352 return &screen_info
->buttons
[SHADE_BUTTON
][state
+ STATE_TOGGLED
];
5354 return &screen_info
->buttons
[SHADE_BUTTON
][state
];
5357 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_STICKY
)
5358 && (!xfwmPixmapNone(&screen_info
->buttons
[STICK_BUTTON
][state
+ STATE_TOGGLED
])))
5360 return &screen_info
->buttons
[STICK_BUTTON
][state
+ STATE_TOGGLED
];
5362 return &screen_info
->buttons
[STICK_BUTTON
][state
];
5364 case MAXIMIZE_BUTTON
:
5365 if (FLAG_TEST (c
->flags
, CLIENT_FLAG_MAXIMIZED
)
5366 && (!xfwmPixmapNone(&screen_info
->buttons
[MAXIMIZE_BUTTON
][state
+ STATE_TOGGLED
])))
5368 return &screen_info
->buttons
[MAXIMIZE_BUTTON
][state
+ STATE_TOGGLED
];
5370 return &screen_info
->buttons
[MAXIMIZE_BUTTON
][state
];
5375 return &screen_info
->buttons
[button
][state
];
5379 clientGetButtonState (Client
*c
, int button
, int state
)
5381 ScreenInfo
*screen_info
;
5383 screen_info
= c
->screen_info
;
5385 if (state
== INACTIVE
)
5390 if ((c
->button_status
[button
] == BUTTON_STATE_PRESSED
) &&
5391 clientGetButtonPixmap (c
, button
, PRESSED
))
5396 if ((c
->button_status
[button
] == BUTTON_STATE_PRELIGHT
) &&
5397 clientGetButtonPixmap (c
, button
, PRELIGHT
))
5407 clientGetLeader (Client
* c
)
5409 TRACE ("entering clientGetLeader");
5410 g_return_val_if_fail (c
!= NULL
, NULL
);
5412 if (c
->group_leader
!= None
)
5414 return myScreenGetClientFromWindow (c
->screen_info
, c
->group_leader
, SEARCH_WINDOW
);
5416 else if (c
->client_leader
!= None
)
5418 return myScreenGetClientFromWindow (c
->screen_info
, c
->client_leader
, SEARCH_WINDOW
);
5423 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
5425 clientGetStartupId (Client
* c
)
5427 ScreenInfo
*screen_info
;
5428 DisplayInfo
*display_info
;
5429 gboolean got_startup_id
;
5431 g_return_val_if_fail (c
!= NULL
, NULL
);
5432 g_return_val_if_fail (c
->window
!= None
, NULL
);
5434 screen_info
= c
->screen_info
;
5435 display_info
= screen_info
->display_info
;
5436 got_startup_id
= FALSE
;
5440 return (c
->startup_id
);
5443 got_startup_id
= getWindowStartupId (display_info
, c
->window
, &c
->startup_id
);
5445 if (!got_startup_id
&& (c
->client_leader
))
5447 got_startup_id
= getWindowStartupId (display_info
, c
->client_leader
, &c
->startup_id
);
5450 if (!got_startup_id
&& (c
->group_leader
))
5452 got_startup_id
= getWindowStartupId (display_info
, c
->group_leader
, &c
->startup_id
);
5455 return (c
->startup_id
);
5457 #endif /* HAVE_LIBSTARTUP_NOTIFICATION */