1 /* Marco X display handler */
2 
3 /*
4  * Copyright (C) 2001 Havoc Pennington
5  * Copyright (C) 2002 Red Hat, Inc.
6  * Copyright (C) 2003 Rob Adams
7  * Copyright (C) 2004-2006 Elijah Newren
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301, USA.
23  */
24 
25 #ifndef META_DISPLAY_PRIVATE_H
26 #define META_DISPLAY_PRIVATE_H
27 
28 #ifndef PACKAGE
29 	#error "config.h not included"
30 #endif
31 
32 #include <glib.h>
33 #include <X11/Xlib.h>
34 #include "eventqueue.h"
35 #include "common.h"
36 #include "boxes.h"
37 #include "display.h"
38 
39 #ifdef HAVE_STARTUP_NOTIFICATION
40 	#include <libsn/sn.h>
41 #endif
42 
43 #ifdef HAVE_XSYNC
44 	#include <X11/extensions/sync.h>
45 #endif
46 
47 typedef struct _MetaKeyBinding MetaKeyBinding;
48 typedef struct _MetaStack      MetaStack;
49 typedef struct _MetaUISlave    MetaUISlave;
50 typedef struct _MetaWorkspace  MetaWorkspace;
51 
52 typedef struct _MetaGroupPropHooks  MetaGroupPropHooks;
53 
54 typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
55 
56 typedef void (*MetaWindowPingFunc) (MetaDisplay* display, Window xwindow, guint32 timestamp, gpointer user_data);
57 
58 #define _NET_WM_STATE_REMOVE        0    /* remove/unset property */
59 #define _NET_WM_STATE_ADD           1    /* add/set property */
60 #define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
61 
62 /* This is basically a bogus number, just has to be large enough
63  * to handle the expected case of the alt+tab operation, where
64  * we want to ignore serials from UnmapNotify on the tab popup,
65  * and the LeaveNotify/EnterNotify from the pointer ungrab
66  */
67 #define N_IGNORED_SERIALS           4
68 
69 typedef enum {
70   META_TILE_NONE,
71   META_TILE_LEFT,
72   META_TILE_RIGHT,
73   META_TILE_MAXIMIZED, /* only used for previews */
74   META_TILE_TOP_LEFT,
75   META_TILE_TOP_RIGHT,
76   META_TILE_BOTTOM_LEFT,
77   META_TILE_BOTTOM_RIGHT
78 } MetaTileMode;
79 
80 struct _MetaDisplay {
81 	char* name;
82 	Display* xdisplay;
83 
84 	Window leader_window;
85 	Window timestamp_pinging_window;
86 
87 	/* Pull in all the names of atoms as fields; we will intern them when the
88 	 * class is constructed.
89 	 */
90 	#define item(x)  Atom atom_##x;
91 		#include "atomnames.h"
92 	#undef item
93 
94 	/* This is the actual window from focus events,
95 	 * not the one we last set
96 	 */
97 	MetaWindow* focus_window;
98 
99 	/* window we are expecting a FocusIn event for or the current focus
100 	 * window if we are not expecting any FocusIn/FocusOut events; not
101 	 * perfect because applications can call XSetInputFocus directly.
102 	 * (It could also be messed up if a timestamp later than current
103 	 * time is sent to meta_display_set_input_focus_window, though that
104 	 * would be a programming error).  See bug 154598 for more info.
105 	 */
106 	MetaWindow* expected_focus_window;
107 
108 	/* last timestamp passed to XSetInputFocus */
109 	guint32 last_focus_time;
110 
111 	/* last user interaction time in any app */
112 	guint32 last_user_time;
113 
114 	/* whether we're using mousenav (only relevant for sloppy&mouse focus modes;
115 	 * !mouse_mode means "keynav mode")
116 	 */
117 	guint mouse_mode: 1;
118 
119 	/* Helper var used when focus_new_windows setting is 'strict'; only
120 	 * relevant in 'strict' mode and if the focus window is a terminal.
121 	 * In that case, we don't allow new windows to take focus away from
122 	 * a terminal, but if the user explicitly did something that should
123 	 * allow a different window to gain focus (e.g. global keybinding or
124 	 * clicking on a dock), then we will allow the transfer.
125 	 */
126 	guint allow_terminal_deactivation: 1;
127 
128 	guint static_gravity_works: 1;
129 
130         guint tab_popup_mouse_pressed : 1;
131 
132 	/*< private-ish >*/
133 	guint error_trap_synced_at_last_pop: 1;
134 	MetaEventQueue* events;
135 	GSList* screens;
136 	MetaScreen* active_screen;
137 	GHashTable* window_ids;
138 	int error_traps;
139 	int (*error_trap_handler) (Display* display, XErrorEvent* error);
140 	int server_grab_count;
141 
142 	/* serials of leave/unmap events that may
143 	 * correspond to an enter event we should
144 	 * ignore
145 	 */
146 	unsigned long ignored_serials[N_IGNORED_SERIALS];
147 	Window ungrab_should_not_cause_focus_window;
148 
149 	guint32 current_time;
150 
151 	/* Pings which we're waiting for a reply from */
152 	GSList* pending_pings;
153 
154 	/* Pending autoraise */
155 	guint       autoraise_timeout_id;
156 	MetaWindow* autoraise_window;
157 
158 	/* Alt+click button grabs */
159 	unsigned int window_grab_modifiers;
160 
161 	/* current window operation */
162 	MetaGrabOp  grab_op;
163 	MetaScreen* grab_screen;
164 	MetaWindow* grab_window;
165 	Window      grab_xwindow;
166 	int         grab_button;
167 	int         grab_anchor_root_x;
168 	int         grab_anchor_root_y;
169 	MetaRectangle grab_anchor_window_pos;
170 	MetaTileMode  grab_tile_mode;
171 	int           grab_tile_monitor_number;
172 	int         grab_latest_motion_x;
173 	int         grab_latest_motion_y;
174 	gulong      grab_mask;
175 	guint       grab_have_pointer : 1;
176 	guint       grab_have_keyboard : 1;
177 	guint       grab_wireframe_active : 1;
178 	guint       grab_was_cancelled : 1;    /* Only used in wireframe mode */
179 	guint       grab_frame_action : 1;
180 	MetaRectangle grab_wireframe_rect;
181 	MetaRectangle grab_wireframe_last_xor_rect;
182 	MetaRectangle grab_initial_window_pos;
183 	int         grab_initial_x, grab_initial_y;  /* These are only relevant for */
184 	gboolean    grab_threshold_movement_reached; /* raise_on_click == FALSE.    */
185 	MetaResizePopup* grab_resize_popup;
186 	gint64      grab_last_moveresize_time;
187 	guint32     grab_motion_notify_time;
188 	int         grab_wireframe_last_display_width;
189 	int         grab_wireframe_last_display_height;
190 	GList*      grab_old_window_stacking;
191 	MetaEdgeResistanceData* grab_edge_resistance_data;
192 	unsigned int grab_last_user_action_was_snap;
193 
194 	/* we use property updates as sentinels for certain window focus events
195 	 * to avoid some race conditions on EnterNotify events
196 	 */
197 	int         sentinel_counter;
198 
199 	#ifdef HAVE_XKB
200 		int         xkb_base_event_type;
201 		guint32     last_bell_time;
202 	#endif
203 
204 	#ifdef HAVE_XSYNC
205 		/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
206 		XSyncAlarm  grab_sync_request_alarm;
207 	#endif
208 
209 	int       grab_resize_timeout_id;
210 
211 	/* Keybindings stuff */
212 	MetaKeyBinding* key_bindings;
213 	int             n_key_bindings;
214 	int             min_keycode;
215 	int             max_keycode;
216 	KeySym* keymap;
217 	int keysyms_per_keycode;
218 	XModifierKeymap* modmap;
219 	unsigned int ignored_modifier_mask;
220 	unsigned int num_lock_mask;
221 	unsigned int scroll_lock_mask;
222 	unsigned int hyper_mask;
223 	unsigned int super_mask;
224 	unsigned int meta_mask;
225 
226 	/* Xinerama cache */
227 	unsigned int xinerama_cache_invalidated: 1;
228 
229 	/* Opening the display */
230 	unsigned int display_opening: 1;
231 
232 	/* Closing down the display */
233 	int closing;
234 
235 	/* To detect double clicks
236 	 *
237 	 * https://github.com/stefano-k/Mate-Desktop-Environment/commit/b0e5fb03eb21dae8f02692f11ef391bfc5ccba33
238 	 */
239 	guint button_click_number;
240 	Window button_click_window;
241 	int button_click_x;
242 	int button_click_y;
243 	guint32 button_click_time;
244 
245 	/* Managed by group.c */
246 	GHashTable* groups_by_leader;
247 
248 	/* currently-active window menu if any */
249 	MetaWindowMenu* window_menu;
250 	MetaWindow* window_with_menu;
251 
252 	/* Managed by window-props.c */
253 	gpointer* prop_hooks_table;
254 	GHashTable* prop_hooks;
255 
256 	/* Managed by group-props.c */
257 	MetaGroupPropHooks* group_prop_hooks;
258 
259 	/* Managed by compositor.c */
260 	MetaCompositor* compositor;
261 
262 	#ifdef HAVE_STARTUP_NOTIFICATION
263 		SnDisplay* sn_display;
264 	#endif
265 
266 	#ifdef HAVE_XSYNC
267 		int xsync_event_base;
268 		int xsync_error_base;
269 	#endif
270 
271 	#ifdef HAVE_SHAPE
272 		int shape_event_base;
273 		int shape_error_base;
274 	#endif
275 
276 	#ifdef HAVE_RENDER
277 		int render_event_base;
278 		int render_error_base;
279 	#endif
280 
281 	#ifdef HAVE_COMPOSITE_EXTENSIONS
282 		int composite_event_base;
283 		int composite_error_base;
284 		int damage_event_base;
285 		int damage_error_base;
286 		int xfixes_event_base;
287 		int xfixes_error_base;
288 	#endif
289 
290 	#ifdef HAVE_XSYNC
291 		unsigned int have_xsync : 1;
292 		#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
293 	#else
294 		#define META_DISPLAY_HAS_XSYNC(display) FALSE
295 	#endif
296 
297 	#ifdef HAVE_SHAPE
298 		unsigned int have_shape : 1;
299 		#define META_DISPLAY_HAS_SHAPE(display) ((display)->have_shape)
300 	#else
301 		#define META_DISPLAY_HAS_SHAPE(display) FALSE
302 	#endif
303 
304 	#ifdef HAVE_RENDER
305 		unsigned int have_render : 1;
306 		#define META_DISPLAY_HAS_RENDER(display) ((display)->have_render)
307 	#else
308 		#define META_DISPLAY_HAS_RENDER(display) FALSE
309 	#endif
310 
311 	#ifdef HAVE_COMPOSITE_EXTENSIONS
312 		unsigned int have_composite : 1;
313 		unsigned int have_damage : 1;
314 		unsigned int have_xfixes : 1;
315 		#define META_DISPLAY_HAS_COMPOSITE(display) ((display)->have_composite)
316 		#define META_DISPLAY_HAS_DAMAGE(display) ((display)->have_damage)
317 		#define META_DISPLAY_HAS_XFIXES(display) ((display)->have_xfixes)
318 	#else
319 		#define META_DISPLAY_HAS_COMPOSITE(display) FALSE
320 		#define META_DISPLAY_HAS_DAMAGE(display) FALSE
321 		#define META_DISPLAY_HAS_XFIXES(display) FALSE
322 	#endif
323 };
324 
325 /* Xserver time can wraparound, thus comparing two timestamps needs to take
326  * this into account.  Here's a little macro to help out.  If no wraparound
327  * has occurred, this is equivalent to
328  *   time1 < time2
329  * Of course, the rest of the ugliness of this macro comes from accounting
330  * for the fact that wraparound can occur and the fact that a timestamp of
331  * 0 must be special-cased since it means older than anything else.
332  *
333  * Note that this is NOT an equivalent for time1 <= time2; if that's what
334  * you need then you'll need to swap the order of the arguments and negate
335  * the result.
336  */
337 #define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
338 	( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \
339 		(( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \
340 	)
341 #define XSERVER_TIME_IS_BEFORE(time1, time2) \
342 	( (time1) == 0 || \
343 		(XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \
344 		(time2) != 0) \
345 	)
346 
347 gboolean      meta_display_open                (void);
348 void          meta_display_close               (MetaDisplay *display,
349                                                 guint32      timestamp);
350 MetaScreen*   meta_display_screen_for_x_screen (MetaDisplay *display,
351                                                 Screen      *screen);
352 MetaScreen*   meta_display_screen_for_xwindow  (MetaDisplay *display,
353                                                 Window       xindow);
354 void          meta_display_grab                (MetaDisplay *display);
355 void          meta_display_ungrab              (MetaDisplay *display);
356 
357 void          meta_display_unmanage_screen     (MetaDisplay *display,
358                                                 MetaScreen  *screen,
359                                                 guint32      timestamp);
360 
361 void          meta_display_unmanage_windows_for_screen (MetaDisplay *display,
362                                                         MetaScreen  *screen,
363                                                         guint32      timestamp);
364 
365 /* Utility function to compare the stacking of two windows */
366 int           meta_display_stack_cmp           (const void *a,
367                                                 const void *b);
368 
369 /* A given MetaWindow may have various X windows that "belong"
370  * to it, such as the frame window.
371  */
372 MetaWindow* meta_display_lookup_x_window     (MetaDisplay *display,
373                                               Window       xwindow);
374 void        meta_display_register_x_window   (MetaDisplay *display,
375                                               Window      *xwindowp,
376                                               MetaWindow  *window);
377 void        meta_display_unregister_x_window (MetaDisplay *display,
378                                               Window       xwindow);
379 /* Return whether the xwindow is a no focus window for any of the screens */
380 gboolean    meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
381                                                        Window xwindow);
382 
383 GSList*     meta_display_list_windows        (MetaDisplay *display);
384 
385 MetaDisplay* meta_display_for_x_display  (Display     *xdisplay);
386 MetaDisplay* meta_get_display            (void);
387 
388 Cursor         meta_display_create_x_cursor (MetaDisplay *display,
389                                              MetaCursor   cursor);
390 
391 void     meta_display_set_grab_op_cursor (MetaDisplay *display,
392                                           MetaScreen  *screen,
393                                           MetaGrabOp   op,
394                                           gboolean     change_pointer,
395                                           Window       grab_xwindow,
396                                           guint32      timestamp);
397 
398 gboolean meta_display_begin_grab_op (MetaDisplay *display,
399                                      MetaScreen  *screen,
400                                      MetaWindow  *window,
401                                      MetaGrabOp   op,
402                                      gboolean     pointer_already_grabbed,
403                                      gboolean     frame_action,
404                                      int          button,
405                                      gulong       modmask,
406                                      guint32      timestamp,
407                                      int          root_x,
408                                      int          root_y);
409 void     meta_display_end_grab_op   (MetaDisplay *display,
410                                      guint32      timestamp);
411 
412 void    meta_display_check_threshold_reached (MetaDisplay *display,
413                                               int          x,
414                                               int          y);
415 void     meta_display_grab_window_buttons    (MetaDisplay *display,
416                                               Window       xwindow);
417 void     meta_display_ungrab_window_buttons  (MetaDisplay *display,
418                                               Window       xwindow);
419 
420 void meta_display_grab_focus_window_button   (MetaDisplay *display,
421                                               MetaWindow  *window);
422 void meta_display_ungrab_focus_window_button (MetaDisplay *display,
423                                               MetaWindow  *window);
424 
425 /* Next two functions are defined in edge-resistance.c */
426 void meta_display_cleanup_edges              (MetaDisplay *display);
427 
428 /* make a request to ensure the event serial has changed */
429 void     meta_display_increment_event_serial (MetaDisplay *display);
430 
431 void     meta_display_update_active_window_hint (MetaDisplay *display);
432 
433 guint32  meta_display_get_current_time           (MetaDisplay *display);
434 guint32  meta_display_get_current_time_roundtrip (MetaDisplay *display);
435 
436 /* utility goo */
437 const char* meta_event_mode_to_string   (int m);
438 const char* meta_event_detail_to_string (int d);
439 
440 void meta_display_queue_retheme_all_windows (MetaDisplay *display);
441 void meta_display_retheme_all (void);
442 
443 void meta_display_set_cursor_theme (const char *theme,
444 				    int         size);
445 
446 void meta_display_ping_window      (MetaDisplay        *display,
447                                     MetaWindow         *window,
448                                     guint32             timestamp,
449                                     MetaWindowPingFunc  ping_reply_func,
450                                     MetaWindowPingFunc  ping_timeout_func,
451                                     void               *user_data);
452 gboolean meta_display_window_has_pending_pings (MetaDisplay        *display,
453 						MetaWindow         *window);
454 
455 typedef enum
456 {
457   META_TAB_LIST_NORMAL,
458   META_TAB_LIST_DOCKS,
459   META_TAB_LIST_GROUP,
460   META_TAB_LIST_NORMAL_ALL_WORKSPACES
461 } MetaTabList;
462 
463 typedef enum
464 {
465   META_TAB_SHOW_ICON,      /* Alt-Tab mode */
466   META_TAB_SHOW_INSTANTLY  /* Alt-Esc mode */
467 } MetaTabShowType;
468 
469 GList* meta_display_get_tab_list (MetaDisplay   *display,
470                                   MetaTabList    type,
471                                   MetaScreen    *screen,
472                                   MetaWorkspace *workspace);
473 
474 MetaWindow* meta_display_get_tab_next (MetaDisplay   *display,
475                                        MetaTabList    type,
476 				       MetaScreen    *screen,
477                                        MetaWorkspace *workspace,
478                                        MetaWindow    *window,
479                                        gboolean       backward);
480 
481 MetaWindow* meta_display_get_tab_current (MetaDisplay   *display,
482                                           MetaTabList    type,
483                                           MetaScreen    *screen,
484                                           MetaWorkspace *workspace);
485 
486 int meta_resize_gravity_from_grab_op (MetaGrabOp op);
487 
488 gboolean meta_grab_op_is_moving   (MetaGrabOp op);
489 gboolean meta_grab_op_is_resizing (MetaGrabOp op);
490 
491 void meta_display_devirtualize_modifiers (MetaDisplay        *display,
492                                           MetaVirtualModifier modifiers,
493                                           unsigned int       *mask);
494 
495 void meta_display_increment_focus_sentinel (MetaDisplay *display);
496 void meta_display_decrement_focus_sentinel (MetaDisplay *display);
497 gboolean meta_display_focus_sentinel_clear (MetaDisplay *display);
498 
499 /* meta_display_set_input_focus_window is like XSetInputFocus, except
500  * that (a) it can't detect timestamps later than the current time,
501  * since Marco isn't part of the XServer, and thus gives erroneous
502  * behavior in this circumstance (so don't do it), (b) it uses
503  * display->last_focus_time since we don't have access to the true
504  * Xserver one, (c) it makes use of display->user_time since checking
505  * whether a window should be allowed to be focused should depend
506  * on user_time events (see bug 167358, comment 15 in particular)
507  */
508 void meta_display_set_input_focus_window   (MetaDisplay *display,
509                                             MetaWindow  *window,
510                                             gboolean     focus_frame,
511                                             guint32      timestamp);
512 
513 /* meta_display_focus_the_no_focus_window is called when the
514  * designated no_focus_window should be focused, but is otherwise the
515  * same as meta_display_set_input_focus_window
516  */
517 void meta_display_focus_the_no_focus_window (MetaDisplay *display,
518                                              MetaScreen  *screen,
519                                              guint32      timestamp);
520 
521 void meta_display_queue_autoraise_callback  (MetaDisplay *display,
522                                              MetaWindow  *window);
523 void meta_display_remove_autoraise_callback (MetaDisplay *display);
524 
525 #endif /* META_DISPLAY_PRIVATE_H */
526