1 /* GDK - The GIMP Drawing Kit
2 * gdkdisplay-x11.c
3 *
4 * Copyright 2001 Sun Microsystems Inc.
5 * Copyright (C) 2004 Nokia Corporation
6 *
7 * Erwann Chenede <erwann.chenede@sun.com>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
18 *
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
23 */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <unistd.h>
31
32 #include <glib.h>
33 #include "gdkx.h"
34 #include "gdkasync.h"
35 #include "gdkdisplay.h"
36 #include "gdkdisplay-x11.h"
37 #include "gdkscreen.h"
38 #include "gdkscreen-x11.h"
39 #include "gdkinternals.h"
40 #include "gdkinputprivate.h"
41 #include "xsettings-client.h"
42 #include "gdkalias.h"
43
44 #include <X11/Xatom.h>
45
46 #ifdef HAVE_XKB
47 #include <X11/XKBlib.h>
48 #endif
49
50 #ifdef HAVE_XFIXES
51 #include <X11/extensions/Xfixes.h>
52 #endif
53
54 #include <X11/extensions/shape.h>
55
56 #ifdef HAVE_XCOMPOSITE
57 #include <X11/extensions/Xcomposite.h>
58 #endif
59
60 #ifdef HAVE_XDAMAGE
61 #include <X11/extensions/Xdamage.h>
62 #endif
63
64 #ifdef HAVE_RANDR
65 #include <X11/extensions/Xrandr.h>
66 #endif
67
68
69 static void gdk_display_x11_dispose (GObject *object);
70 static void gdk_display_x11_finalize (GObject *object);
71
72 #ifdef HAVE_X11R6
73 static void gdk_internal_connection_watch (Display *display,
74 XPointer arg,
75 gint fd,
76 gboolean opening,
77 XPointer *watch_data);
78 #endif /* HAVE_X11R6 */
79
80 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
81 * but including them here has the side-effect of getting them
82 * into the internal Xlib cache
83 */
84 static const char *const precache_atoms[] = {
85 "UTF8_STRING",
86 "WM_CLIENT_LEADER",
87 "WM_DELETE_WINDOW",
88 "WM_ICON_NAME",
89 "WM_LOCALE_NAME",
90 "WM_NAME",
91 "WM_PROTOCOLS",
92 "WM_TAKE_FOCUS",
93 "WM_WINDOW_ROLE",
94 "_NET_ACTIVE_WINDOW",
95 "_NET_CURRENT_DESKTOP",
96 "_NET_FRAME_EXTENTS",
97 "_NET_STARTUP_ID",
98 "_NET_WM_CM_S0",
99 "_NET_WM_DESKTOP",
100 "_NET_WM_ICON",
101 "_NET_WM_ICON_NAME",
102 "_NET_WM_NAME",
103 "_NET_WM_PID",
104 "_NET_WM_PING",
105 "_NET_WM_STATE",
106 "_NET_WM_STATE_ABOVE",
107 "_NET_WM_STATE_BELOW",
108 "_NET_WM_STATE_FULLSCREEN",
109 "_NET_WM_STATE_MODAL",
110 "_NET_WM_STATE_MAXIMIZED_VERT",
111 "_NET_WM_STATE_MAXIMIZED_HORZ",
112 "_NET_WM_STATE_SKIP_TASKBAR",
113 "_NET_WM_STATE_SKIP_PAGER",
114 "_NET_WM_STATE_STICKY",
115 "_NET_WM_SYNC_REQUEST",
116 "_NET_WM_SYNC_REQUEST_COUNTER",
117 "_NET_WM_WINDOW_TYPE",
118 "_NET_WM_WINDOW_TYPE_NORMAL",
119 "_NET_WM_USER_TIME",
120 "_NET_VIRTUAL_ROOTS"
121 };
122
G_DEFINE_TYPE(GdkDisplayX11,_gdk_display_x11,GDK_TYPE_DISPLAY)123 G_DEFINE_TYPE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE_DISPLAY)
124
125 static void
126 _gdk_display_x11_class_init (GdkDisplayX11Class * class)
127 {
128 GObjectClass *object_class = G_OBJECT_CLASS (class);
129
130 object_class->dispose = gdk_display_x11_dispose;
131 object_class->finalize = gdk_display_x11_finalize;
132 }
133
134 static void
_gdk_display_x11_init(GdkDisplayX11 * display)135 _gdk_display_x11_init (GdkDisplayX11 *display)
136 {
137 }
138
139 /**
140 * gdk_display_open:
141 * @display_name: the name of the display to open
142 * @returns: a #GdkDisplay, or %NULL if the display
143 * could not be opened.
144 *
145 * Opens a display.
146 *
147 * Since: 2.2
148 */
149 GdkDisplay *
gdk_display_open(const gchar * display_name)150 gdk_display_open (const gchar *display_name)
151 {
152 Display *xdisplay;
153 GdkDisplay *display;
154 GdkDisplayX11 *display_x11;
155 GdkWindowAttr attr;
156 gint argc;
157 gchar *argv[1];
158 const char *sm_client_id;
159
160 XClassHint *class_hint;
161 gulong pid;
162 gint i;
163 gint ignore;
164 gint maj, min;
165
166 xdisplay = XOpenDisplay (display_name);
167 if (!xdisplay)
168 return NULL;
169
170 display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
171 display_x11 = GDK_DISPLAY_X11 (display);
172
173 display_x11->use_xshm = TRUE;
174 display_x11->xdisplay = xdisplay;
175
176 #ifdef HAVE_X11R6
177 /* Set up handlers for Xlib internal connections */
178 XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
179 #endif /* HAVE_X11R6 */
180
181 _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
182
183 /* RandR must be initialized before we initialize the screens */
184 display_x11->have_randr13 = FALSE;
185 display_x11->have_randr15 = FALSE;
186 #ifdef HAVE_RANDR
187 if (XRRQueryExtension (display_x11->xdisplay,
188 &display_x11->xrandr_event_base, &ignore))
189 {
190 int major, minor;
191
192 XRRQueryVersion (display_x11->xdisplay, &major, &minor);
193
194 if ((major == 1 && minor >= 3) || major > 1)
195 display_x11->have_randr13 = TRUE;
196
197 #ifdef HAVE_RANDR15
198 if (minor >= 5 || major > 1)
199 display_x11->have_randr15 = TRUE;
200 #endif
201
202 gdk_x11_register_standard_event_type (display, display_x11->xrandr_event_base, RRNumberEvents);
203 }
204 #endif
205
206 /* initialize the display's screens */
207 display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
208 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
209 display_x11->screens[i] = _gdk_x11_screen_new (display, i);
210
211 /* We need to initialize events after we have the screen
212 * structures in places
213 */
214 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
215 _gdk_x11_events_init_screen (display_x11->screens[i]);
216
217 /*set the default screen */
218 display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
219
220 attr.window_type = GDK_WINDOW_TOPLEVEL;
221 attr.wclass = GDK_INPUT_OUTPUT;
222 attr.x = 10;
223 attr.y = 10;
224 attr.width = 10;
225 attr.height = 10;
226 attr.event_mask = 0;
227
228 display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window,
229 &attr, GDK_WA_X | GDK_WA_Y);
230 (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
231
232 display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
233
234 display_x11->leader_window_title_set = FALSE;
235
236 display_x11->have_render = GDK_UNKNOWN;
237
238 #ifdef HAVE_XFIXES
239 if (XFixesQueryExtension (display_x11->xdisplay,
240 &display_x11->xfixes_event_base,
241 &ignore))
242 {
243 display_x11->have_xfixes = TRUE;
244
245 gdk_x11_register_standard_event_type (display,
246 display_x11->xfixes_event_base,
247 XFixesNumberEvents);
248 }
249 else
250 #endif
251 display_x11->have_xfixes = FALSE;
252
253 #ifdef HAVE_XCOMPOSITE
254 if (XCompositeQueryExtension (display_x11->xdisplay,
255 &ignore, &ignore))
256 {
257 int major, minor;
258
259 XCompositeQueryVersion (display_x11->xdisplay, &major, &minor);
260
261 /* Prior to Composite version 0.4, composited windows clipped their
262 * parents, so you had to use IncludeInferiors to draw to the parent
263 * This isn't useful for our purposes, so require 0.4
264 */
265 display_x11->have_xcomposite = major > 0 || (major == 0 && minor >= 4);
266 }
267 else
268 #endif
269 display_x11->have_xcomposite = FALSE;
270
271 #ifdef HAVE_XDAMAGE
272 if (XDamageQueryExtension (display_x11->xdisplay,
273 &display_x11->xdamage_event_base,
274 &ignore))
275 {
276 display_x11->have_xdamage = TRUE;
277
278 gdk_x11_register_standard_event_type (display,
279 display_x11->xdamage_event_base,
280 XDamageNumberEvents);
281 }
282 else
283 #endif
284 display_x11->have_xdamage = FALSE;
285
286 display_x11->have_shapes = FALSE;
287 display_x11->have_input_shapes = FALSE;
288
289 if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &display_x11->shape_event_base, &ignore))
290 {
291 display_x11->have_shapes = TRUE;
292 #ifdef ShapeInput
293 if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
294 display_x11->have_input_shapes = (maj == 1 && min >= 1);
295 #endif
296 }
297
298 display_x11->trusted_client = TRUE;
299 {
300 Window root, child;
301 int rootx, rooty, winx, winy;
302 unsigned int xmask;
303
304 gdk_error_trap_push ();
305 XQueryPointer (display_x11->xdisplay,
306 GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window,
307 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
308 gdk_flush ();
309 if (G_UNLIKELY (gdk_error_trap_pop () == BadWindow))
310 {
311 g_warning ("Connection to display %s appears to be untrusted. Pointer and keyboard grabs and inter-client communication may not work as expected.", gdk_display_get_name (display));
312 display_x11->trusted_client = FALSE;
313 }
314 }
315
316 if (_gdk_synchronize)
317 XSynchronize (display_x11->xdisplay, True);
318
319 class_hint = XAllocClassHint();
320 class_hint->res_name = g_get_prgname ();
321
322 class_hint->res_class = (char *)gdk_get_program_class ();
323
324 /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
325 * from argv[0], so we just synthesize an argument array here.
326 */
327 argc = 1;
328 argv[0] = g_get_prgname ();
329
330 XmbSetWMProperties (display_x11->xdisplay,
331 display_x11->leader_window,
332 NULL, NULL, argv, argc, NULL, NULL,
333 class_hint);
334 XFree (class_hint);
335
336 sm_client_id = _gdk_get_sm_client_id ();
337 if (sm_client_id)
338 _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
339
340 pid = getpid ();
341 XChangeProperty (display_x11->xdisplay,
342 display_x11->leader_window,
343 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
344 XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
345
346 /* We don't yet know a valid time. */
347 display_x11->user_time = 0;
348
349 #ifdef HAVE_XKB
350 {
351 gint xkb_major = XkbMajorVersion;
352 gint xkb_minor = XkbMinorVersion;
353 if (XkbLibraryVersion (&xkb_major, &xkb_minor))
354 {
355 xkb_major = XkbMajorVersion;
356 xkb_minor = XkbMinorVersion;
357
358 if (XkbQueryExtension (display_x11->xdisplay,
359 NULL, &display_x11->xkb_event_type, NULL,
360 &xkb_major, &xkb_minor))
361 {
362 Bool detectable_autorepeat_supported;
363
364 display_x11->use_xkb = TRUE;
365
366 XkbSelectEvents (display_x11->xdisplay,
367 XkbUseCoreKbd,
368 XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
369 XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
370
371 /* keep this in sync with _gdk_keymap_state_changed() */
372 XkbSelectEventDetails (display_x11->xdisplay,
373 XkbUseCoreKbd, XkbStateNotify,
374 XkbAllStateComponentsMask,
375 XkbGroupLockMask|XkbModifierLockMask);
376
377 XkbSetDetectableAutoRepeat (display_x11->xdisplay,
378 True,
379 &detectable_autorepeat_supported);
380
381 GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
382 detectable_autorepeat_supported ?
383 "supported" : "not supported"));
384
385 display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
386 }
387 }
388 }
389 #endif
390
391 display_x11->use_sync = FALSE;
392 #ifdef HAVE_XSYNC
393 {
394 int major, minor;
395 int error_base, event_base;
396
397 if (XSyncQueryExtension (display_x11->xdisplay,
398 &event_base, &error_base) &&
399 XSyncInitialize (display_x11->xdisplay,
400 &major, &minor))
401 display_x11->use_sync = TRUE;
402 }
403 #endif
404
405 _gdk_windowing_image_init (display);
406 _gdk_events_init (display);
407 _gdk_input_init (display);
408 _gdk_dnd_init (display);
409
410 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
411 _gdk_x11_screen_setup (display_x11->screens[i]);
412
413 g_signal_emit_by_name (gdk_display_manager_get(),
414 "display_opened", display);
415
416 return display;
417 }
418
419 #ifdef HAVE_X11R6
420 /*
421 * XLib internal connection handling
422 */
423 typedef struct _GdkInternalConnection GdkInternalConnection;
424
425 struct _GdkInternalConnection
426 {
427 gint fd;
428 GSource *source;
429 Display *display;
430 };
431
432 static gboolean
process_internal_connection(GIOChannel * gioc,GIOCondition cond,gpointer data)433 process_internal_connection (GIOChannel *gioc,
434 GIOCondition cond,
435 gpointer data)
436 {
437 GdkInternalConnection *connection = (GdkInternalConnection *)data;
438
439 GDK_THREADS_ENTER ();
440
441 XProcessInternalConnection ((Display*)connection->display, connection->fd);
442
443 GDK_THREADS_LEAVE ();
444
445 return TRUE;
446 }
447
448 gulong
_gdk_windowing_window_get_next_serial(GdkDisplay * display)449 _gdk_windowing_window_get_next_serial (GdkDisplay *display)
450 {
451 return NextRequest (GDK_DISPLAY_XDISPLAY (display));
452 }
453
454
455 static GdkInternalConnection *
gdk_add_connection_handler(Display * display,guint fd)456 gdk_add_connection_handler (Display *display,
457 guint fd)
458 {
459 GIOChannel *io_channel;
460 GdkInternalConnection *connection;
461
462 connection = g_new (GdkInternalConnection, 1);
463
464 connection->fd = fd;
465 connection->display = display;
466
467 io_channel = g_io_channel_unix_new (fd);
468
469 connection->source = g_io_create_watch (io_channel, G_IO_IN);
470 g_source_set_callback (connection->source,
471 (GSourceFunc)process_internal_connection, connection, NULL);
472 g_source_attach (connection->source, NULL);
473
474 g_io_channel_unref (io_channel);
475
476 return connection;
477 }
478
479 static void
gdk_remove_connection_handler(GdkInternalConnection * connection)480 gdk_remove_connection_handler (GdkInternalConnection *connection)
481 {
482 g_source_destroy (connection->source);
483 g_free (connection);
484 }
485
486 static void
gdk_internal_connection_watch(Display * display,XPointer arg,gint fd,gboolean opening,XPointer * watch_data)487 gdk_internal_connection_watch (Display *display,
488 XPointer arg,
489 gint fd,
490 gboolean opening,
491 XPointer *watch_data)
492 {
493 if (opening)
494 *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
495 else
496 gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
497 }
498 #endif /* HAVE_X11R6 */
499
500 /**
501 * gdk_display_get_name:
502 * @display: a #GdkDisplay
503 *
504 * Gets the name of the display.
505 *
506 * Returns: a string representing the display name. This string is owned
507 * by GDK and should not be modified or freed.
508 *
509 * Since: 2.2
510 */
511 const gchar *
gdk_display_get_name(GdkDisplay * display)512 gdk_display_get_name (GdkDisplay *display)
513 {
514 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
515
516 return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
517 }
518
519 /**
520 * gdk_display_get_n_screens:
521 * @display: a #GdkDisplay
522 *
523 * Gets the number of screen managed by the @display.
524 *
525 * Returns: number of screens.
526 *
527 * Since: 2.2
528 */
529 gint
gdk_display_get_n_screens(GdkDisplay * display)530 gdk_display_get_n_screens (GdkDisplay *display)
531 {
532 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
533
534 return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
535 }
536
537 /**
538 * gdk_display_get_screen:
539 * @display: a #GdkDisplay
540 * @screen_num: the screen number
541 *
542 * Returns a screen object for one of the screens of the display.
543 *
544 * Returns: the #GdkScreen object
545 *
546 * Since: 2.2
547 */
548 GdkScreen *
gdk_display_get_screen(GdkDisplay * display,gint screen_num)549 gdk_display_get_screen (GdkDisplay *display,
550 gint screen_num)
551 {
552 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
553 g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
554
555 return GDK_DISPLAY_X11 (display)->screens[screen_num];
556 }
557
558 /**
559 * gdk_display_get_default_screen:
560 * @display: a #GdkDisplay
561 *
562 * Get the default #GdkScreen for @display.
563 *
564 * Returns: the default #GdkScreen object for @display
565 *
566 * Since: 2.2
567 */
568 GdkScreen *
gdk_display_get_default_screen(GdkDisplay * display)569 gdk_display_get_default_screen (GdkDisplay *display)
570 {
571 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
572
573 return GDK_DISPLAY_X11 (display)->default_screen;
574 }
575
576 gboolean
_gdk_x11_display_is_root_window(GdkDisplay * display,Window xroot_window)577 _gdk_x11_display_is_root_window (GdkDisplay *display,
578 Window xroot_window)
579 {
580 GdkDisplayX11 *display_x11;
581 gint i;
582
583 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
584
585 display_x11 = GDK_DISPLAY_X11 (display);
586
587 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
588 {
589 if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
590 return TRUE;
591 }
592 return FALSE;
593 }
594
595 struct XPointerUngrabInfo {
596 GdkDisplay *display;
597 guint32 time;
598 };
599
600 static void
pointer_ungrab_callback(GdkDisplay * display,gpointer data,gulong serial)601 pointer_ungrab_callback (GdkDisplay *display,
602 gpointer data,
603 gulong serial)
604 {
605 _gdk_display_pointer_grab_update (display, serial);
606 }
607
608
609 #define XSERVER_TIME_IS_LATER(time1, time2) \
610 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
611 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
612 )
613
614 /**
615 * gdk_display_pointer_ungrab:
616 * @display: a #GdkDisplay.
617 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
618 *
619 * Release any pointer grab.
620 *
621 * Since: 2.2
622 */
623 void
gdk_display_pointer_ungrab(GdkDisplay * display,guint32 time_)624 gdk_display_pointer_ungrab (GdkDisplay *display,
625 guint32 time_)
626 {
627 Display *xdisplay;
628 GdkDisplayX11 *display_x11;
629 GdkPointerGrabInfo *grab;
630 unsigned long serial;
631
632 g_return_if_fail (GDK_IS_DISPLAY (display));
633
634 display_x11 = GDK_DISPLAY_X11 (display);
635 xdisplay = GDK_DISPLAY_XDISPLAY (display);
636
637 serial = NextRequest (xdisplay);
638
639 _gdk_input_ungrab_pointer (display, time_);
640 XUngrabPointer (xdisplay, time_);
641 XFlush (xdisplay);
642
643 grab = _gdk_display_get_last_pointer_grab (display);
644 if (grab &&
645 (time_ == GDK_CURRENT_TIME ||
646 grab->time == GDK_CURRENT_TIME ||
647 !XSERVER_TIME_IS_LATER (grab->time, time_)))
648 {
649 grab->serial_end = serial;
650 _gdk_x11_roundtrip_async (display,
651 pointer_ungrab_callback,
652 NULL);
653 }
654 }
655
656 /**
657 * gdk_display_keyboard_ungrab:
658 * @display: a #GdkDisplay.
659 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
660 *
661 * Release any keyboard grab
662 *
663 * Since: 2.2
664 */
665 void
gdk_display_keyboard_ungrab(GdkDisplay * display,guint32 time)666 gdk_display_keyboard_ungrab (GdkDisplay *display,
667 guint32 time)
668 {
669 Display *xdisplay;
670 GdkDisplayX11 *display_x11;
671
672 g_return_if_fail (GDK_IS_DISPLAY (display));
673
674 display_x11 = GDK_DISPLAY_X11 (display);
675 xdisplay = GDK_DISPLAY_XDISPLAY (display);
676
677 XUngrabKeyboard (xdisplay, time);
678 XFlush (xdisplay);
679
680 if (time == GDK_CURRENT_TIME ||
681 display->keyboard_grab.time == GDK_CURRENT_TIME ||
682 !XSERVER_TIME_IS_LATER (display->keyboard_grab.time, time))
683 _gdk_display_unset_has_keyboard_grab (display, FALSE);
684 }
685
686 /**
687 * gdk_display_beep:
688 * @display: a #GdkDisplay
689 *
690 * Emits a short beep on @display
691 *
692 * Since: 2.2
693 */
694 void
gdk_display_beep(GdkDisplay * display)695 gdk_display_beep (GdkDisplay *display)
696 {
697 g_return_if_fail (GDK_IS_DISPLAY (display));
698
699 #ifdef HAVE_XKB
700 XkbBell (GDK_DISPLAY_XDISPLAY (display), None, 0, None);
701 #else
702 XBell (GDK_DISPLAY_XDISPLAY (display), 0);
703 #endif
704 }
705
706 /**
707 * gdk_display_sync:
708 * @display: a #GdkDisplay
709 *
710 * Flushes any requests queued for the windowing system and waits until all
711 * requests have been handled. This is often used for making sure that the
712 * display is synchronized with the current state of the program. Calling
713 * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
714 * generated from earlier requests are handled before the error trap is
715 * removed.
716 *
717 * This is most useful for X11. On windowing systems where requests are
718 * handled synchronously, this function will do nothing.
719 *
720 * Since: 2.2
721 */
722 void
gdk_display_sync(GdkDisplay * display)723 gdk_display_sync (GdkDisplay *display)
724 {
725 g_return_if_fail (GDK_IS_DISPLAY (display));
726
727 XSync (GDK_DISPLAY_XDISPLAY (display), False);
728 }
729
730 /**
731 * gdk_display_flush:
732 * @display: a #GdkDisplay
733 *
734 * Flushes any requests queued for the windowing system; this happens automatically
735 * when the main loop blocks waiting for new events, but if your application
736 * is drawing without returning control to the main loop, you may need
737 * to call this function explicitely. A common case where this function
738 * needs to be called is when an application is executing drawing commands
739 * from a thread other than the thread where the main loop is running.
740 *
741 * This is most useful for X11. On windowing systems where requests are
742 * handled synchronously, this function will do nothing.
743 *
744 * Since: 2.4
745 */
746 void
gdk_display_flush(GdkDisplay * display)747 gdk_display_flush (GdkDisplay *display)
748 {
749 g_return_if_fail (GDK_IS_DISPLAY (display));
750
751 if (!display->closed)
752 XFlush (GDK_DISPLAY_XDISPLAY (display));
753 }
754
755 /**
756 * gdk_display_get_default_group:
757 * @display: a #GdkDisplay
758 *
759 * Returns the default group leader window for all toplevel windows
760 * on @display. This window is implicitly created by GDK.
761 * See gdk_window_set_group().
762 *
763 * Return value: The default group leader window for @display
764 *
765 * Since: 2.4
766 **/
767 GdkWindow *
gdk_display_get_default_group(GdkDisplay * display)768 gdk_display_get_default_group (GdkDisplay *display)
769 {
770 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
771
772 return GDK_DISPLAY_X11 (display)->leader_gdk_window;
773 }
774
775 /**
776 * gdk_x11_display_grab:
777 * @display: a #GdkDisplay
778 *
779 * Call XGrabServer() on @display.
780 * To ungrab the display again, use gdk_x11_display_ungrab().
781 *
782 * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
783 *
784 * Since: 2.2
785 **/
786 void
gdk_x11_display_grab(GdkDisplay * display)787 gdk_x11_display_grab (GdkDisplay *display)
788 {
789 GdkDisplayX11 *display_x11;
790
791 g_return_if_fail (GDK_IS_DISPLAY (display));
792
793 display_x11 = GDK_DISPLAY_X11 (display);
794
795 if (display_x11->grab_count == 0)
796 XGrabServer (display_x11->xdisplay);
797 display_x11->grab_count++;
798 }
799
800 /**
801 * gdk_x11_display_ungrab:
802 * @display: a #GdkDisplay
803 *
804 * Ungrab @display after it has been grabbed with
805 * gdk_x11_display_grab().
806 *
807 * Since: 2.2
808 **/
809 void
gdk_x11_display_ungrab(GdkDisplay * display)810 gdk_x11_display_ungrab (GdkDisplay *display)
811 {
812 GdkDisplayX11 *display_x11;
813
814 g_return_if_fail (GDK_IS_DISPLAY (display));
815
816 display_x11 = GDK_DISPLAY_X11 (display);;
817 g_return_if_fail (display_x11->grab_count > 0);
818
819 display_x11->grab_count--;
820 if (display_x11->grab_count == 0)
821 {
822 XUngrabServer (display_x11->xdisplay);
823 XFlush (display_x11->xdisplay);
824 }
825 }
826
827 static void
gdk_display_x11_dispose(GObject * object)828 gdk_display_x11_dispose (GObject *object)
829 {
830 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
831 gint i;
832
833 g_list_foreach (display_x11->input_devices, (GFunc) g_object_run_dispose, NULL);
834
835 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
836 _gdk_screen_close (display_x11->screens[i]);
837
838 _gdk_events_uninit (GDK_DISPLAY_OBJECT (object));
839
840 G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
841 }
842
843 static void
gdk_display_x11_finalize(GObject * object)844 gdk_display_x11_finalize (GObject *object)
845 {
846 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
847 gint i;
848
849 /* Keymap */
850 if (display_x11->keymap)
851 g_object_unref (display_x11->keymap);
852
853 /* Free motif Dnd */
854 if (display_x11->motif_target_lists)
855 {
856 for (i = 0; i < display_x11->motif_n_target_lists; i++)
857 g_list_free (display_x11->motif_target_lists[i]);
858 g_free (display_x11->motif_target_lists);
859 }
860
861 _gdk_x11_cursor_display_finalize (GDK_DISPLAY_OBJECT(display_x11));
862
863 /* Atom Hashtable */
864 g_hash_table_destroy (display_x11->atom_from_virtual);
865 g_hash_table_destroy (display_x11->atom_to_virtual);
866
867 /* Leader Window */
868 XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
869
870 /* list of filters for client messages */
871 g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
872 g_list_free (display_x11->client_filters);
873
874 /* List of event window extraction functions */
875 g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
876 g_slist_free (display_x11->event_types);
877
878 /* input GdkDevice list */
879 g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
880 g_list_free (display_x11->input_devices);
881
882 /* input GdkWindow list */
883 g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
884 g_list_free (display_x11->input_windows);
885
886 /* Free all GdkScreens */
887 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
888 g_object_unref (display_x11->screens[i]);
889 g_free (display_x11->screens);
890
891 g_free (display_x11->startup_notification_id);
892
893 /* X ID hashtable */
894 g_hash_table_destroy (display_x11->xid_ht);
895
896 XCloseDisplay (display_x11->xdisplay);
897
898 G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
899 }
900
901 /**
902 * gdk_x11_lookup_xdisplay:
903 * @xdisplay: a pointer to an X Display
904 *
905 * Find the #GdkDisplay corresponding to @display, if any exists.
906 *
907 * Return value: the #GdkDisplay, if found, otherwise %NULL.
908 *
909 * Since: 2.2
910 **/
911 GdkDisplay *
gdk_x11_lookup_xdisplay(Display * xdisplay)912 gdk_x11_lookup_xdisplay (Display *xdisplay)
913 {
914 GSList *tmp_list;
915
916 for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
917 {
918 if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
919 return tmp_list->data;
920 }
921
922 return NULL;
923 }
924
925 /**
926 * _gdk_x11_display_screen_for_xrootwin:
927 * @display: a #GdkDisplay
928 * @xrootwin: window ID for one of of the screen's of the display.
929 *
930 * Given the root window ID of one of the screen's of a #GdkDisplay,
931 * finds the screen.
932 *
933 * Return value: (transfer none): the #GdkScreen corresponding to
934 * @xrootwin, or %NULL.
935 **/
936 GdkScreen *
_gdk_x11_display_screen_for_xrootwin(GdkDisplay * display,Window xrootwin)937 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
938 Window xrootwin)
939 {
940 gint i;
941
942 for (i = 0; i < ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay); i++)
943 {
944 GdkScreen *screen = gdk_display_get_screen (display, i);
945 if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
946 return screen;
947 }
948
949 return NULL;
950 }
951
952 /**
953 * gdk_x11_display_get_xdisplay:
954 * @display: a #GdkDisplay
955 * @returns: an X display.
956 *
957 * Returns the X display of a #GdkDisplay.
958 *
959 * Since: 2.2
960 */
961 Display *
gdk_x11_display_get_xdisplay(GdkDisplay * display)962 gdk_x11_display_get_xdisplay (GdkDisplay *display)
963 {
964 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
965 return GDK_DISPLAY_X11 (display)->xdisplay;
966 }
967
968 void
_gdk_windowing_set_default_display(GdkDisplay * display)969 _gdk_windowing_set_default_display (GdkDisplay *display)
970 {
971 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
972 const gchar *startup_id;
973
974 if (!display)
975 {
976 gdk_display = NULL;
977 return;
978 }
979
980 gdk_display = GDK_DISPLAY_XDISPLAY (display);
981
982 g_free (display_x11->startup_notification_id);
983 display_x11->startup_notification_id = NULL;
984
985 startup_id = g_getenv ("DESKTOP_STARTUP_ID");
986 if (startup_id && *startup_id != '\0')
987 {
988 gchar *time_str;
989
990 if (!g_utf8_validate (startup_id, -1, NULL))
991 g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
992 else
993 display_x11->startup_notification_id = g_strdup (startup_id);
994
995 /* Find the launch time from the startup_id, if it's there. Newer spec
996 * states that the startup_id is of the form <unique>_TIME<timestamp>
997 */
998 time_str = g_strrstr (startup_id, "_TIME");
999 if (time_str != NULL)
1000 {
1001 gulong retval;
1002 gchar *end;
1003 errno = 0;
1004
1005 /* Skip past the "_TIME" part */
1006 time_str += 5;
1007
1008 retval = strtoul (time_str, &end, 0);
1009 if (end != time_str && errno == 0)
1010 display_x11->user_time = retval;
1011 }
1012
1013 /* Clear the environment variable so it won't be inherited by
1014 * child processes and confuse things.
1015 */
1016 g_unsetenv ("DESKTOP_STARTUP_ID");
1017
1018 /* Set the startup id on the leader window so it
1019 * applies to all windows we create on this display
1020 */
1021 XChangeProperty (display_x11->xdisplay,
1022 display_x11->leader_window,
1023 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
1024 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
1025 PropModeReplace,
1026 (guchar *)startup_id, strlen (startup_id));
1027 }
1028 }
1029
1030 static void
broadcast_xmessage(GdkDisplay * display,const char * message_type,const char * message_type_begin,const char * message)1031 broadcast_xmessage (GdkDisplay *display,
1032 const char *message_type,
1033 const char *message_type_begin,
1034 const char *message)
1035 {
1036 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1037 GdkScreen *screen = gdk_display_get_default_screen (display);
1038 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1039 Window xroot_window = GDK_WINDOW_XID (root_window);
1040
1041 Atom type_atom;
1042 Atom type_atom_begin;
1043 Window xwindow;
1044
1045 if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1046 return;
1047
1048 {
1049 XSetWindowAttributes attrs;
1050
1051 attrs.override_redirect = True;
1052 attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
1053
1054 xwindow =
1055 XCreateWindow (xdisplay,
1056 xroot_window,
1057 -100, -100, 1, 1,
1058 0,
1059 CopyFromParent,
1060 CopyFromParent,
1061 (Visual *)CopyFromParent,
1062 CWOverrideRedirect | CWEventMask,
1063 &attrs);
1064 }
1065
1066 type_atom = gdk_x11_get_xatom_by_name_for_display (display,
1067 message_type);
1068 type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
1069 message_type_begin);
1070
1071 {
1072 XClientMessageEvent xclient;
1073 const char *src;
1074 const char *src_end;
1075 char *dest;
1076 char *dest_end;
1077
1078 memset(&xclient, 0, sizeof (xclient));
1079 xclient.type = ClientMessage;
1080 xclient.message_type = type_atom_begin;
1081 xclient.display =xdisplay;
1082 xclient.window = xwindow;
1083 xclient.format = 8;
1084
1085 src = message;
1086 src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1087
1088 while (src != src_end)
1089 {
1090 dest = &xclient.data.b[0];
1091 dest_end = dest + 20;
1092
1093 while (dest != dest_end &&
1094 src != src_end)
1095 {
1096 *dest = *src;
1097 ++dest;
1098 ++src;
1099 }
1100
1101 while (dest != dest_end)
1102 {
1103 *dest = 0;
1104 ++dest;
1105 }
1106
1107 XSendEvent (xdisplay,
1108 xroot_window,
1109 False,
1110 PropertyChangeMask,
1111 (XEvent *)&xclient);
1112
1113 xclient.message_type = type_atom;
1114 }
1115 }
1116
1117 XDestroyWindow (xdisplay, xwindow);
1118 XFlush (xdisplay);
1119 }
1120
1121 /**
1122 * gdk_x11_display_broadcast_startup_message:
1123 * @display: a #GdkDisplay
1124 * @message_type: startup notification message type ("new", "change",
1125 * or "remove")
1126 * @...: a list of key/value pairs (as strings), terminated by a
1127 * %NULL key. (A %NULL value for a key will cause that key to be
1128 * skipped in the output.)
1129 *
1130 * Sends a startup notification message of type @message_type to
1131 * @display.
1132 *
1133 * This is a convenience function for use by code that implements the
1134 * freedesktop startup notification specification. Applications should
1135 * not normally need to call it directly. See the <ulink
1136 * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
1137 * Notification Protocol specification</ulink> for
1138 * definitions of the message types and keys that can be used.
1139 *
1140 * Since: 2.12
1141 **/
1142 void
gdk_x11_display_broadcast_startup_message(GdkDisplay * display,const char * message_type,...)1143 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
1144 const char *message_type,
1145 ...)
1146 {
1147 GString *message;
1148 va_list ap;
1149 const char *key, *value, *p;
1150
1151 message = g_string_new (message_type);
1152 g_string_append_c (message, ':');
1153
1154 va_start (ap, message_type);
1155 while ((key = va_arg (ap, const char *)))
1156 {
1157 value = va_arg (ap, const char *);
1158 if (!value)
1159 continue;
1160
1161 g_string_append_printf (message, " %s=\"", key);
1162 for (p = value; *p; p++)
1163 {
1164 switch (*p)
1165 {
1166 case ' ':
1167 case '"':
1168 case '\\':
1169 g_string_append_c (message, '\\');
1170 break;
1171 }
1172
1173 g_string_append_c (message, *p);
1174 }
1175 g_string_append_c (message, '\"');
1176 }
1177 va_end (ap);
1178
1179 broadcast_xmessage (display,
1180 "_NET_STARTUP_INFO",
1181 "_NET_STARTUP_INFO_BEGIN",
1182 message->str);
1183
1184 g_string_free (message, TRUE);
1185 }
1186
1187 /**
1188 * gdk_notify_startup_complete:
1189 *
1190 * Indicates to the GUI environment that the application has finished
1191 * loading. If the applications opens windows, this function is
1192 * normally called after opening the application's initial set of
1193 * windows.
1194 *
1195 * GTK+ will call this function automatically after opening the first
1196 * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
1197 * to disable that feature.
1198 *
1199 * Since: 2.2
1200 **/
1201 void
gdk_notify_startup_complete(void)1202 gdk_notify_startup_complete (void)
1203 {
1204 GdkDisplay *display;
1205 GdkDisplayX11 *display_x11;
1206
1207 display = gdk_display_get_default ();
1208 if (!display)
1209 return;
1210
1211 display_x11 = GDK_DISPLAY_X11 (display);
1212
1213 if (display_x11->startup_notification_id == NULL)
1214 return;
1215
1216 gdk_notify_startup_complete_with_id (display_x11->startup_notification_id);
1217 }
1218
1219 /**
1220 * gdk_notify_startup_complete_with_id:
1221 * @startup_id: a startup-notification identifier, for which notification
1222 * process should be completed
1223 *
1224 * Indicates to the GUI environment that the application has finished
1225 * loading, using a given identifier.
1226 *
1227 * GTK+ will call this function automatically for #GtkWindow with custom
1228 * startup-notification identifier unless
1229 * gtk_window_set_auto_startup_notification() is called to disable
1230 * that feature.
1231 *
1232 * Since: 2.12
1233 **/
1234 void
gdk_notify_startup_complete_with_id(const gchar * startup_id)1235 gdk_notify_startup_complete_with_id (const gchar* startup_id)
1236 {
1237 GdkDisplay *display;
1238
1239 display = gdk_display_get_default ();
1240 if (!display)
1241 return;
1242
1243 gdk_x11_display_broadcast_startup_message (display, "remove",
1244 "ID", startup_id,
1245 NULL);
1246 }
1247
1248 /**
1249 * gdk_display_supports_selection_notification:
1250 * @display: a #GdkDisplay
1251 *
1252 * Returns whether #GdkEventOwnerChange events will be
1253 * sent when the owner of a selection changes.
1254 *
1255 * Return value: whether #GdkEventOwnerChange events will
1256 * be sent.
1257 *
1258 * Since: 2.6
1259 **/
1260 gboolean
gdk_display_supports_selection_notification(GdkDisplay * display)1261 gdk_display_supports_selection_notification (GdkDisplay *display)
1262 {
1263 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1264
1265 return display_x11->have_xfixes;
1266 }
1267
1268 /**
1269 * gdk_display_request_selection_notification:
1270 * @display: a #GdkDisplay
1271 * @selection: the #GdkAtom naming the selection for which
1272 * ownership change notification is requested
1273 *
1274 * Request #GdkEventOwnerChange events for ownership changes
1275 * of the selection named by the given atom.
1276 *
1277 * Return value: whether #GdkEventOwnerChange events will
1278 * be sent.
1279 *
1280 * Since: 2.6
1281 **/
1282 gboolean
gdk_display_request_selection_notification(GdkDisplay * display,GdkAtom selection)1283 gdk_display_request_selection_notification (GdkDisplay *display,
1284 GdkAtom selection)
1285
1286 {
1287 #ifdef HAVE_XFIXES
1288 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1289 Atom atom;
1290
1291 if (display_x11->have_xfixes)
1292 {
1293 atom = gdk_x11_atom_to_xatom_for_display (display,
1294 selection);
1295 XFixesSelectSelectionInput (display_x11->xdisplay,
1296 display_x11->leader_window,
1297 atom,
1298 XFixesSetSelectionOwnerNotifyMask |
1299 XFixesSelectionWindowDestroyNotifyMask |
1300 XFixesSelectionClientCloseNotifyMask);
1301 return TRUE;
1302 }
1303 else
1304 #endif
1305 return FALSE;
1306 }
1307
1308 /**
1309 * gdk_display_supports_clipboard_persistence
1310 * @display: a #GdkDisplay
1311 *
1312 * Returns whether the speicifed display supports clipboard
1313 * persistance; i.e. if it's possible to store the clipboard data after an
1314 * application has quit. On X11 this checks if a clipboard daemon is
1315 * running.
1316 *
1317 * Returns: %TRUE if the display supports clipboard persistance.
1318 *
1319 * Since: 2.6
1320 */
1321 gboolean
gdk_display_supports_clipboard_persistence(GdkDisplay * display)1322 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1323 {
1324 Atom clipboard_manager;
1325
1326 /* It might make sense to cache this */
1327 clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1328 return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay, clipboard_manager) != None;
1329 }
1330
1331 /**
1332 * gdk_display_store_clipboard
1333 * @display: a #GdkDisplay
1334 * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1335 * @time_: a timestamp
1336 * @targets: an array of targets that should be saved, or %NULL
1337 * if all available targets should be saved.
1338 * @n_targets: length of the @targets array
1339 *
1340 * Issues a request to the clipboard manager to store the
1341 * clipboard data. On X11, this is a special program that works
1342 * according to the freedesktop clipboard specification, available at
1343 * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1344 * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1345 *
1346 * Since: 2.6
1347 */
1348 void
gdk_display_store_clipboard(GdkDisplay * display,GdkWindow * clipboard_window,guint32 time_,const GdkAtom * targets,gint n_targets)1349 gdk_display_store_clipboard (GdkDisplay *display,
1350 GdkWindow *clipboard_window,
1351 guint32 time_,
1352 const GdkAtom *targets,
1353 gint n_targets)
1354 {
1355 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1356 Atom clipboard_manager, save_targets;
1357
1358 g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
1359
1360 clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1361 save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1362
1363 gdk_error_trap_push ();
1364
1365 if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1366 {
1367 Atom property_name = None;
1368 Atom *xatoms;
1369 int i;
1370
1371 if (n_targets > 0)
1372 {
1373 property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1374
1375 xatoms = g_new (Atom, n_targets);
1376 for (i = 0; i < n_targets; i++)
1377 xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1378
1379 XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1380 property_name, XA_ATOM,
1381 32, PropModeReplace, (guchar *)xatoms, n_targets);
1382 g_free (xatoms);
1383
1384 }
1385
1386 XConvertSelection (display_x11->xdisplay,
1387 clipboard_manager, save_targets, property_name,
1388 GDK_WINDOW_XID (clipboard_window), time_);
1389
1390 }
1391 gdk_error_trap_pop ();
1392
1393 }
1394
1395 /**
1396 * gdk_x11_display_get_user_time:
1397 * @display: a #GdkDisplay
1398 *
1399 * Returns the timestamp of the last user interaction on
1400 * @display. The timestamp is taken from events caused
1401 * by user interaction such as key presses or pointer
1402 * movements. See gdk_x11_window_set_user_time().
1403 *
1404 * Returns: the timestamp of the last user interaction
1405 *
1406 * Since: 2.8
1407 */
1408 guint32
gdk_x11_display_get_user_time(GdkDisplay * display)1409 gdk_x11_display_get_user_time (GdkDisplay *display)
1410 {
1411 return GDK_DISPLAY_X11 (display)->user_time;
1412 }
1413
1414 /**
1415 * gdk_display_supports_shapes:
1416 * @display: a #GdkDisplay
1417 *
1418 * Returns %TRUE if gdk_window_shape_combine_mask() can
1419 * be used to create shaped windows on @display.
1420 *
1421 * Returns: %TRUE if shaped windows are supported
1422 *
1423 * Since: 2.10
1424 */
1425 gboolean
gdk_display_supports_shapes(GdkDisplay * display)1426 gdk_display_supports_shapes (GdkDisplay *display)
1427 {
1428 return GDK_DISPLAY_X11 (display)->have_shapes;
1429 }
1430
1431 /**
1432 * gdk_display_supports_input_shapes:
1433 * @display: a #GdkDisplay
1434 *
1435 * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1436 * be used to modify the input shape of windows on @display.
1437 *
1438 * Returns: %TRUE if windows with modified input shape are supported
1439 *
1440 * Since: 2.10
1441 */
1442 gboolean
gdk_display_supports_input_shapes(GdkDisplay * display)1443 gdk_display_supports_input_shapes (GdkDisplay *display)
1444 {
1445 return GDK_DISPLAY_X11 (display)->have_input_shapes;
1446 }
1447
1448
1449 /**
1450 * gdk_x11_display_get_startup_notification_id:
1451 * @display: a #GdkDisplay
1452 *
1453 * Gets the startup notification ID for a display.
1454 *
1455 * Returns: the startup notification ID for @display
1456 *
1457 * Since: 2.12
1458 */
1459 const gchar *
gdk_x11_display_get_startup_notification_id(GdkDisplay * display)1460 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
1461 {
1462 return GDK_DISPLAY_X11 (display)->startup_notification_id;
1463 }
1464
1465 /**
1466 * gdk_display_supports_composite:
1467 * @display: a #GdkDisplay
1468 *
1469 * Returns %TRUE if gdk_window_set_composited() can be used
1470 * to redirect drawing on the window using compositing.
1471 *
1472 * Currently this only works on X11 with XComposite and
1473 * XDamage extensions available.
1474 *
1475 * Returns: %TRUE if windows may be composited.
1476 *
1477 * Since: 2.12
1478 */
1479 gboolean
gdk_display_supports_composite(GdkDisplay * display)1480 gdk_display_supports_composite (GdkDisplay *display)
1481 {
1482 GdkDisplayX11 *x11_display = GDK_DISPLAY_X11 (display);
1483
1484 return x11_display->have_xcomposite &&
1485 x11_display->have_xdamage &&
1486 x11_display->have_xfixes;
1487 }
1488
1489
1490 #define __GDK_DISPLAY_X11_C__
1491 #include "gdkaliasdef.c"
1492