1 /*      $Id$
2 
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)
6         any later version.
7 
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.
12 
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., Inc., 51 Franklin Street, Fifth Floor, Boston,
16         MA 02110-1301, USA.
17 
18 
19         oroborus - (c) 2001 Ken Lynch
20         xfwm4    - (c) 2002-2011 Olivier Fourdan
21 
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <signal.h>
32 #include <unistd.h>
33 
34 #include <X11/X.h>
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #include <X11/Xmd.h>
38 #include <X11/cursorfont.h>
39 #include <X11/extensions/shape.h>
40 
41 #include <glib.h>
42 #include <gtk/gtk.h>
43 #include <sys/time.h>
44 #include <time.h>
45 
46 #include "screen.h"
47 #include "misc.h"
48 #include "hints.h"
49 #include "keyboard.h"
50 #include "mypixmap.h"
51 #include "mywindow.h"
52 #include "settings.h"
53 
54 #ifndef INC_CLIENT_H
55 #define INC_CLIENT_H
56 
57 #define APPLY                           +1
58 #define REMOVE                          -1
59 
60 #define PLACEMENT_MOUSE                 0
61 #define PLACEMENT_ROOT                  1
62 
63 #define NO_CFG_FLAG                     0
64 #define CFG_CONSTRAINED                 (1<<0)
65 #define CFG_REQUEST                     (1<<1)
66 #define CFG_NOTIFY                      (1<<2)
67 #define CFG_KEEP_VISIBLE                (1<<3)
68 #define CFG_FORCE_REDRAW                (1<<4)
69 
70 #define SEARCH_INCLUDE_HIDDEN           (1<<0)
71 #define SEARCH_INCLUDE_SHADED           (1<<1)
72 #define SEARCH_INCLUDE_ALL_WORKSPACES   (1<<2)
73 #define SEARCH_INCLUDE_SKIP_FOCUS       (1<<3)
74 #define SEARCH_INCLUDE_SKIP_PAGER       (1<<4)
75 #define SEARCH_INCLUDE_SKIP_TASKBAR     (1<<5)
76 #define SEARCH_SAME_APPLICATION         (1<<6)
77 #define SEARCH_DIFFERENT_APPLICATION    (1<<7)
78 
79 #define NO_UPDATE_FLAG                  0
80 #define UPDATE_BUTTON_GRABS             (1<<0)
81 #define UPDATE_FRAME                    (1<<1)
82 #define UPDATE_GRAVITY                  (1<<2)
83 #define UPDATE_MAXIMIZE                 (1<<3)
84 #define UPDATE_CACHE                    (1<<4)
85 #define UPDATE_ALL                      (UPDATE_BUTTON_GRABS | \
86                                          UPDATE_FRAME | \
87                                          UPDATE_GRAVITY | \
88                                          UPDATE_MAXIMIZE | \
89                                          UPDATE_CACHE)
90 
91 #define CLIENT_FILL_VERT                (1L<<0)
92 #define CLIENT_FILL_HORIZ               (1L<<1)
93 #define CLIENT_FILL                     (CLIENT_FILL_VERT | \
94                                          CLIENT_FILL_HORIZ)
95 
96 
97 #define STRUTS_SIZE                     12
98 
99 #ifndef CLIENT_MIN_VISIBLE
100 #define CLIENT_MIN_VISIBLE              15
101 #endif
102 
103 #ifndef CLIENT_XSYNC_TIMEOUT
104 #define CLIENT_XSYNC_TIMEOUT            500  /* ms */
105 #endif
106 
107 #ifndef CLIENT_BLINK_TIMEOUT
108 #define CLIENT_BLINK_TIMEOUT            500  /* ms */
109 #endif
110 
111 #ifndef CLIENT_PING_TIMEOUT
112 #define CLIENT_PING_TIMEOUT             3000 /* ms */
113 #endif
114 
115 #ifndef MAX_BLINK_ITERATIONS
116 #define MAX_BLINK_ITERATIONS            5
117 #endif
118 
119 #ifndef MAX_SNAP_DRIFT
120 #define MAX_SNAP_DRIFT                  15
121 #endif
122 
123 #define XFWM_FLAG_HAS_BORDER            (1L<<0)
124 #define XFWM_FLAG_HAS_MENU              (1L<<1)
125 #define XFWM_FLAG_HAS_MAXIMIZE          (1L<<2)
126 #define XFWM_FLAG_HAS_CLOSE             (1L<<3)
127 #define XFWM_FLAG_HAS_HIDE              (1L<<4)
128 #define XFWM_FLAG_HAS_MOVE              (1L<<5)
129 #define XFWM_FLAG_HAS_RESIZE            (1L<<6)
130 #define XFWM_FLAG_HAS_STICK             (1L<<7)
131 #define XFWM_FLAG_FOCUS                 (1L<<8)
132 #define XFWM_FLAG_IS_RESIZABLE          (1L<<9)
133 #define XFWM_FLAG_MAP_PENDING           (1L<<10)
134 #define XFWM_FLAG_VISIBLE               (1L<<11)
135 #define XFWM_FLAG_MANAGED               (1L<<13)
136 #define XFWM_FLAG_SESSION_MANAGED       (1L<<14)
137 #define XFWM_FLAG_WORKSPACE_SET         (1L<<15)
138 #define XFWM_FLAG_WAS_SHOWN             (1L<<16)
139 #define XFWM_FLAG_DRAW_ACTIVE           (1L<<17)
140 #define XFWM_FLAG_SEEN_ACTIVE           (1L<<18)
141 #define XFWM_FLAG_FIRST_MAP             (1L<<19)
142 #define XFWM_FLAG_SAVED_POS             (1L<<20)
143 #define XFWM_FLAG_MOVING_RESIZING       (1L<<21)
144 #define XFWM_FLAG_NEEDS_REDRAW          (1L<<22)
145 #define XFWM_FLAG_OPACITY_LOCKED        (1L<<23)
146 
147 #define CLIENT_FLAG_HAS_STRUT           (1L<<0)
148 #define CLIENT_FLAG_HAS_STRUT_PARTIAL   (1L<<1)
149 #define CLIENT_FLAG_HAS_USER_TIME       (1L<<2)
150 #define CLIENT_FLAG_HAS_STARTUP_TIME    (1L<<3)
151 #define CLIENT_FLAG_ABOVE               (1L<<4)
152 #define CLIENT_FLAG_BELOW               (1L<<5)
153 #define CLIENT_FLAG_FULLSCREEN          (1L<<6)
154 #define CLIENT_FLAG_ICONIFIED           (1L<<7)
155 #define CLIENT_FLAG_MAXIMIZED_VERT      (1L<<8)
156 #define CLIENT_FLAG_MAXIMIZED_HORIZ     (1L<<9)
157 #define CLIENT_FLAG_MAXIMIZED           (CLIENT_FLAG_MAXIMIZED_VERT | \
158                                          CLIENT_FLAG_MAXIMIZED_HORIZ)
159 #define CLIENT_FLAG_SHADED              (1L<<10)
160 #define CLIENT_FLAG_SKIP_PAGER          (1L<<11)
161 #define CLIENT_FLAG_SKIP_TASKBAR        (1L<<12)
162 #define CLIENT_FLAG_STATE_MODAL         (1L<<13)
163 #define CLIENT_FLAG_STICKY              (1L<<15)
164 #define CLIENT_FLAG_NAME_CHANGED        (1L<<16)
165 #define CLIENT_FLAG_DEMANDS_ATTENTION   (1L<<17)
166 #define CLIENT_FLAG_HAS_SHAPE           (1L<<18)
167 #define CLIENT_FLAG_FULLSCREEN_MONITORS (1L<<19)
168 #define CLIENT_FLAG_HAS_FRAME_EXTENTS   (1L<<20)
169 #define CLIENT_FLAG_HIDE_TITLEBAR       (1L<<21)
170 #define CLIENT_FLAG_XSYNC_WAITING       (1L<<22)
171 #define CLIENT_FLAG_XSYNC_ENABLED       (1L<<23)
172 #define CLIENT_FLAG_XSYNC_EXT_COUNTER   (1L<<24)
173 #define CLIENT_FLAG_RESTORE_SIZE_POS    (1L<<25)
174 
175 #define WM_FLAG_DELETE                  (1L<<0)
176 #define WM_FLAG_INPUT                   (1L<<1)
177 #define WM_FLAG_TAKEFOCUS               (1L<<2)
178 #define WM_FLAG_CONTEXT_HELP            (1L<<3)
179 #define WM_FLAG_URGENT                  (1L<<4)
180 #define WM_FLAG_PING                    (1L<<5)
181 
182 #define XFWM_FLAG_INITIAL_VALUES        XFWM_FLAG_HAS_BORDER | \
183                                         XFWM_FLAG_HAS_MENU | \
184                                         XFWM_FLAG_HAS_MAXIMIZE | \
185                                         XFWM_FLAG_HAS_STICK | \
186                                         XFWM_FLAG_HAS_HIDE | \
187                                         XFWM_FLAG_HAS_CLOSE | \
188                                         XFWM_FLAG_HAS_MOVE | \
189                                         XFWM_FLAG_HAS_RESIZE | \
190                                         XFWM_FLAG_FIRST_MAP | \
191                                         XFWM_FLAG_NEEDS_REDRAW
192 
193 #define ALL_WORKSPACES                  (guint) 0xFFFFFFFF
194 
195 #define CONSTRAINED_WINDOW(c)           ((c->win_layer > WIN_LAYER_DESKTOP) && \
196                                         !(c->type & (WINDOW_DESKTOP | WINDOW_DOCK)))
197 
198 #define WINDOW_TYPE_DIALOG              (WINDOW_DIALOG | \
199                                          WINDOW_MODAL_DIALOG)
200 #define WINDOW_TYPE_DONT_PLACE          (WINDOW_DESKTOP | \
201                                          WINDOW_DOCK | \
202                                          WINDOW_UTILITY | \
203                                          WINDOW_SPLASHSCREEN)
204 #define WINDOW_REGULAR_FOCUSABLE        (WINDOW_NORMAL | \
205                                          WINDOW_TYPE_DIALOG | \
206                                          WINDOW_UTILITY)
207 #define WINDOW_TYPE_DONT_FOCUS          (WINDOW_SPLASHSCREEN | \
208                                          WINDOW_DOCK)
209 #define WINDOW_TYPE_STATE_FOCUSED       (WINDOW_SPLASHSCREEN | \
210                                          WINDOW_DOCK )
211 
212 /* Which bits of opacity are applied */
213 #define OPACITY_MOVE                    (1<<0)
214 #define OPACITY_RESIZE                  (1<<1)
215 #define OPACITY_INACTIVE                (1<<2)
216 
217 /* Convenient macros */
218 #define FLAG_TEST(flag,bits)                   ((flag) & (bits))
219 #define FLAG_TEST_ALL(flag,bits)               (((flag) & (bits)) == (bits))
220 #define FLAG_TEST_AND_NOT(flag,bits1,bits2)    (((flag) & ((bits1) | (bits2))) == (bits1))
221 #define FLAG_SET(flag,bits)                    (flag |= (bits))
222 #define FLAG_UNSET(flag,bits)                  (flag &= ~(bits))
223 #define FLAG_TOGGLE(flag,bits)                 (flag ^= (bits))
224 
225 #define CLIENT_CAN_HIDE_WINDOW(c)       (FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_HIDE) && \
226                                          !FLAG_TEST(c->flags, CLIENT_FLAG_SKIP_TASKBAR))
227 #define CLIENT_CAN_MAXIMIZE_WINDOW(c)   (FLAG_TEST_ALL(c->xfwm_flags, XFWM_FLAG_HAS_MAXIMIZE | \
228                                                                       XFWM_FLAG_IS_RESIZABLE) && \
229                                          !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN))
230 #define CLIENT_CAN_FILL_WINDOW(c)       (FLAG_TEST(c->xfwm_flags, XFWM_FLAG_HAS_RESIZE | \
231                                                                   XFWM_FLAG_IS_RESIZABLE) && \
232                                          !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN | \
233                                                                CLIENT_FLAG_MAXIMIZED | \
234                                                                CLIENT_FLAG_SHADED))
235 #define CLIENT_CAN_TILE_WINDOW(c)       (CLIENT_CAN_MAXIMIZE_WINDOW(c) && \
236                                          !FLAG_TEST (c->flags, CLIENT_FLAG_SHADED) && \
237                                          (c->type & WINDOW_NORMAL))
238 #define CLIENT_HAS_FRAME(c)             (FLAG_TEST (c->xfwm_flags, XFWM_FLAG_HAS_BORDER) && \
239                                          !FLAG_TEST (c->flags, CLIENT_FLAG_FULLSCREEN) && \
240                                          (FLAG_TEST (c->flags, CLIENT_FLAG_SHADED) || \
241                                           !FLAG_TEST_ALL (c->flags, CLIENT_FLAG_MAXIMIZED) ||  \
242                                           !((FLAG_TEST (c->flags, CLIENT_FLAG_HIDE_TITLEBAR) || \
243                                             (c->screen_info->params->titleless_maximize)) && \
244                                             (c->screen_info->params->borderless_maximize))))
245 
246 typedef enum
247 {
248     UNSET = 0,
249     WINDOW_NORMAL       = (1 << 0),
250     WINDOW_DESKTOP      = (1 << 1),
251     WINDOW_DOCK         = (1 << 2),
252     WINDOW_DIALOG       = (1 << 3),
253     WINDOW_MODAL_DIALOG = (1 << 4),
254     WINDOW_TOOLBAR      = (1 << 5),
255     WINDOW_MENU         = (1 << 6),
256     WINDOW_UTILITY      = (1 << 7),
257     WINDOW_SPLASHSCREEN = (1 << 8),
258     WINDOW_NOTIFICATION = (1 << 9)
259 }
260 netWindowType;
261 
262 typedef enum
263 {
264     TILE_NONE = 0,
265     TILE_LEFT,
266     TILE_RIGHT,
267     TILE_DOWN,
268     TILE_UP,
269     TILE_DOWN_LEFT,
270     TILE_DOWN_RIGHT,
271     TILE_UP_LEFT,
272     TILE_UP_RIGHT
273 }
274 tilePositionType;
275 
276 struct _Client
277 {
278     /* Reference to our screen structure */
279     ScreenInfo *screen_info;
280 
281     Window window;
282     Window frame;
283     Window transient_for;
284     Window user_time_win;
285     Window *cmap_windows;
286     Colormap cmap;
287     gint ncmap;
288     xfwmWindow title;
289     xfwmWindow sides[SIDE_COUNT];
290     xfwmWindow corners[CORNER_COUNT];
291     xfwmWindow buttons[BUTTON_COUNT];
292     Window client_leader;
293     Window group_leader;
294     xfwmPixmap appmenu[STATE_TOGGLED];
295     unsigned long win_layer;
296     unsigned long serial;
297     unsigned long initial_layer;
298     unsigned int ignore_unmap;
299     Atom type_atom;
300     Visual *visual;
301     XSizeHints *size;
302     XWMHints *wmhints;
303     XClassHint class;
304     Client *next;
305     Client *prev;
306     PropMwmHints *mwm_hints;
307     netWindowType type;
308     gint x;
309     gint y;
310     gint width;
311     gint height;
312     gint depth;
313     gint border_width;
314     gint gravity;
315     guint win_workspace;
316     GdkRectangle applied_geometry;
317     GdkRectangle saved_geometry;
318     GdkRectangle pre_fullscreen_geometry;
319     gint pre_fullscreen_layer;
320     gint pre_relayout_x;    /* to restore original location with XRandR */
321     gint pre_relayout_y;
322     gint frame_cache_width; /* to optimize frame rendering */
323     gint frame_cache_height;
324     gint blink_iterations;
325     gint button_status[BUTTON_COUNT];
326     gint struts[STRUTS_SIZE];
327     gchar *hostname;
328     gchar *name;
329     guint32 user_time;
330     GPid pid;
331     guint32 ping_time;
332     unsigned long flags;
333     unsigned long wm_flags;
334     unsigned long xfwm_flags;
335     gint fullscreen_monitors[4];
336     gint frame_extents[SIDE_COUNT];
337     tilePositionType tile_mode;
338 
339     /* Termination dialog */
340     gint dialog_pid;
341     gint dialog_fd;
342     /* Timout for asynchronous icon update */
343     guint icon_timeout_id;
344     /* Timout for asynchronous frame update */
345     guint frame_timeout_id;
346     /* Timout to manage blinking decorations for urgent windows */
347     guint blink_timeout_id;
348     /* Timout for asynchronous icon update */
349     guint ping_timeout_id;
350     /* Opacity for the compositor */
351     guint32 opacity;
352     guint32 opacity_applied;
353     guint opacity_flags;
354 
355 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
356     /* Startup notification */
357     gchar *startup_id;
358 #endif /* HAVE_LIBSTARTUP_NOTIFICATION */
359 
360 #ifdef HAVE_XSYNC
361     XSyncAlarm  xsync_alarm;
362     XSyncCounter xsync_counter;
363     XSyncValue xsync_value;
364     XSyncValue next_xsync_value;
365     guint xsync_timeout_id;
366 #endif /* HAVE_XSYNC */
367 };
368 
369 extern Client *clients;
370 extern unsigned int client_count;
371 
372 Display                 *clientGetXDisplay                      (Client *);
373 void                     clientClearLastOpTime                  (Client *);
374 void                     clientUpdateWinState                   (Client *,
375                                                                  XClientMessageEvent *);
376 void                     clientUpdateUrgency                    (Client *);
377 void                     clientCoordGravitate                   (Client *,
378                                                                  int,
379                                                                  int,
380                                                                  int *,
381                                                                  int *);
382 void                     clientAdjustCoordGravity               (Client *,
383                                                                  int,
384                                                                  XWindowChanges *,
385                                                                  unsigned long *);
386 void                     clientSendConfigureNotify              (Client *);
387 void                     clientConfigure                        (Client *,
388                                                                  XWindowChanges *,
389                                                                  unsigned long,
390                                                                  unsigned short);
391 void                     clientReconfigure                      (Client *,
392                                                                  unsigned short);
393 void                     clientMoveResizeWindow                 (Client *,
394                                                                  XWindowChanges *,
395                                                                  unsigned long);
396 void                     clientGetMWMHints                      (Client *);
397 void                     clientApplyMWMHints                    (Client *,
398                                                                  gboolean);
399 void                     clientGetWMNormalHints                 (Client *,
400                                                                  gboolean);
401 void                     clientGetWMProtocols                   (Client *);
402 void                     clientUpdateIcon                       (Client *);
403 void                     clientSaveSizePos                      (Client *);
404 gboolean                 clientRestoreSizePos                   (Client *);
405 Client                  *clientFrame                            (DisplayInfo *,
406                                                                  Window,
407                                                                  gboolean);
408 void                     clientUnframe                          (Client *,
409                                                                  gboolean);
410 void                     clientFrameAll                         (ScreenInfo *);
411 void                     clientUnframeAll                       (ScreenInfo *);
412 void                     clientInstallColormaps                 (Client *);
413 void                     clientUpdateColormaps                  (Client *);
414 void                     clientUpdateName                       (Client *);
415 void                     clientUpdateAllFrames                  (ScreenInfo *,
416                                                                  gboolean);
417 void                     clientGrabButtons                      (Client *);
418 void                     clientUngrabButtons                    (Client *);
419 Client                  *clientGetFromWindow                    (Client *,
420                                                                  Window,
421                                                                  unsigned short);
422 void                     clientShow                             (Client *,
423                                                                  gboolean);
424 void                     clientWithdraw                         (Client *,
425                                                                  guint,
426                                                                  gboolean);
427 void                     clientWithdrawAll                      (Client *,
428                                                                  guint);
429 void                     clientClearAllShowDesktop              (ScreenInfo *);
430 void                     clientToggleShowDesktop                (ScreenInfo *);
431 void                     clientActivate                         (Client *,
432                                                                  guint32,
433                                                                  gboolean);
434 void                     clientClose                            (Client *);
435 void                     clientKill                             (Client *);
436 void                     clientTerminate                        (Client *);
437 void                     clientEnterContextMenuState            (Client *);
438 void                     clientSetLayer                         (Client *,
439                                                                  guint);
440 void                     clientSetWorkspace                     (Client *,
441                                                                  guint,
442                                                                  gboolean);
443 void                     clientShade                            (Client *);
444 void                     clientUnshade                          (Client *);
445 void                     clientToggleShaded                     (Client *);
446 void                     clientStick                            (Client *,
447                                                                  gboolean);
448 void                     clientUnstick                          (Client *,
449                                                                  gboolean);
450 void                     clientToggleSticky                     (Client *,
451                                                                  gboolean);
452 void                     clientUpdateFullscreenSize             (Client *);
453 void                     clientToggleFullscreen                 (Client *);
454 void                     clientSetFullscreenMonitor             (Client *,
455                                                                  gint,
456                                                                  gint,
457                                                                  gint,
458                                                                  gint);
459 void                     clientToggleLayerAbove                 (Client *);
460 void                     clientToggleLayerBelow                 (Client *);
461 void                     clientSetLayerNormal                   (Client *);
462 void                     clientRemoveMaximizeFlag               (Client *);
463 void                     clientUpdateMaximizeSize               (Client *);
464 gboolean                 clientToggleMaximized                  (Client *,
465                                                                  int,
466                                                                  gboolean);
467 gboolean                 clientToggleMaximizedAtPoint           (Client *,
468                                                                  gint,
469                                                                  gint,
470                                                                  int,
471                                                                  gboolean);
472 gboolean                 clientTile                             (Client *,
473                                                                  gint,
474                                                                  gint,
475                                                                  tilePositionType,
476                                                                  gboolean,
477                                                                  gboolean);
478 void                     clientUntile                           (Client *);
479 gboolean                 clientToggleTile                       (Client *,
480                                                                  tilePositionType);
481 void                     clientUpdateTileSize                   (Client *);
482 void                     clientUpdateOpacity                    (Client *);
483 void                     clientUpdateAllOpacity                 (ScreenInfo *);
484 void                     clientSetOpacity                       (Client *,
485                                                                  guint32,
486                                                                  guint32,
487                                                                  guint32);
488 void                     clientIncOpacity                       (Client *);
489 void                     clientDecOpacity                       (Client *);
490 void                     clientUpdateCursor                     (Client *);
491 void                     clientUpdateAllCursor                  (ScreenInfo *);
492 void                     clientScreenResize                     (ScreenInfo *,
493                                                                  gboolean);
494 void                     clientButtonPress                      (Client *,
495                                                                  Window,
496                                                                  XfwmEventButton *);
497 xfwmPixmap *             clientGetButtonPixmap                  (Client *,
498                                                                  int,
499                                                                  int);
500 int                      clientGetButtonState                   (Client *,
501                                                                  int,
502                                                                  int);
503 Client                  *clientGetLeader                        (Client *);
504 gboolean                 clientGetGtkFrameExtents               (Client *);
505 gboolean                 clientGetGtkHideTitlebar               (Client *);
506 #ifdef HAVE_LIBSTARTUP_NOTIFICATION
507 char                    *clientGetStartupId                     (Client *);
508 #endif /* HAVE_LIBSTARTUP_NOTIFICATION */
509 
510 #endif /* INC_CLIENT_H */
511