1 /* GDK - The GIMP Drawing Kit
4 * Copyright 2001 Sun Microsystems Inc.
5 * Copyright (C) 2004 Nokia Corporation
7 * Erwann Chenede <erwann.chenede@sun.com>
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.
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.
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.
34 #include "gdkdisplay.h"
35 #include "gdkdisplay-x11.h"
36 #include "gdkscreen.h"
37 #include "gdkscreen-x11.h"
38 #include "gdkinternals.h"
39 #include "gdkinputprivate.h"
40 #include "xsettings-client.h"
43 #include <X11/Xatom.h>
46 #include <X11/XKBlib.h>
50 #include <X11/extensions/Xfixes.h>
54 #include <X11/extensions/shape.h>
57 #ifdef HAVE_XCOMPOSITE
58 #include <X11/extensions/Xcomposite.h>
62 #include <X11/extensions/Xdamage.h>
66 #include <X11/extensions/Xrandr.h>
70 static void gdk_display_x11_dispose (GObject *object);
71 static void gdk_display_x11_finalize (GObject *object);
74 static void gdk_internal_connection_watch (Display *display,
78 XPointer *watch_data);
79 #endif /* HAVE_X11R6 */
81 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
82 * but including them here has the side-effect of getting them
83 * into the internal Xlib cache
85 static const char *const precache_atoms[] = {
100 "_NET_WM_STATE_STICKY",
101 "_NET_WM_STATE_MAXIMIZED_VERT",
102 "_NET_WM_STATE_MAXIMIZED_HORZ",
103 "_NET_WM_STATE_FULLSCREEN",
104 "_NET_WM_SYNC_REQUEST",
105 "_NET_WM_SYNC_REQUEST_COUNTER",
106 "_NET_WM_WINDOW_TYPE",
107 "_NET_WM_WINDOW_TYPE_NORMAL",
112 G_DEFINE_TYPE (GdkDisplayX11, _gdk_display_x11, GDK_TYPE_DISPLAY)
115 _gdk_display_x11_class_init (GdkDisplayX11Class * class)
117 GObjectClass *object_class = G_OBJECT_CLASS (class);
119 object_class->dispose = gdk_display_x11_dispose;
120 object_class->finalize = gdk_display_x11_finalize;
124 _gdk_display_x11_init (GdkDisplayX11 *display)
130 * @display_name: the name of the display to open
131 * @returns: a #GdkDisplay, or %NULL if the display
132 * could not be opened.
139 gdk_display_open (const gchar *display_name)
143 GdkDisplayX11 *display_x11;
147 const char *sm_client_id;
149 XClassHint *class_hint;
152 #if defined(HAVE_XFIXES) || defined(HAVE_SHAPE_EXT)
157 xdisplay = XOpenDisplay (display_name);
161 display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
162 display_x11 = GDK_DISPLAY_X11 (display);
164 display_x11->use_xshm = TRUE;
165 display_x11->xdisplay = xdisplay;
168 /* Set up handlers for Xlib internal connections */
169 XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
170 #endif /* HAVE_X11R6 */
172 /* RandR must be initialized before we initialize the screens */
173 display_x11->have_randr12 = FALSE;
175 if (XRRQueryExtension (display_x11->xdisplay,
176 &display_x11->xrandr_event_base, &ignore))
180 XRRQueryVersion (display_x11->xdisplay, &major, &minor);
182 if ((major == 1 && minor >= 2) || major > 1)
183 display_x11->have_randr12 = TRUE;
187 /* initialize the display's screens */
188 display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
189 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
190 display_x11->screens[i] = _gdk_x11_screen_new (display, i);
192 /* We need to initialize events after we have the screen
193 * structures in places
195 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
196 _gdk_x11_events_init_screen (display_x11->screens[i]);
198 /*set the default screen */
199 display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
201 attr.window_type = GDK_WINDOW_TOPLEVEL;
202 attr.wclass = GDK_INPUT_OUTPUT;
209 _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
211 display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window,
212 &attr, GDK_WA_X | GDK_WA_Y);
213 (_gdk_x11_window_get_toplevel (display_x11->leader_gdk_window))->is_leader = TRUE;
215 display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
217 display_x11->leader_window_title_set = FALSE;
219 display_x11->have_render = GDK_UNKNOWN;
222 if (XFixesQueryExtension (display_x11->xdisplay,
223 &display_x11->xfixes_event_base,
226 display_x11->have_xfixes = TRUE;
228 gdk_x11_register_standard_event_type (display,
229 display_x11->xfixes_event_base,
234 display_x11->have_xfixes = FALSE;
236 #ifdef HAVE_XCOMPOSITE
237 if (XCompositeQueryExtension (display_x11->xdisplay,
242 XCompositeQueryVersion (display_x11->xdisplay, &major, &minor);
244 /* Prior to Composite version 0.4, composited windows clipped their
245 * parents, so you had to use IncludeInferiors to draw to the parent
246 * This isn't useful for our purposes, so require 0.4
248 display_x11->have_xcomposite = major > 0 || (major == 0 && minor >= 4);
252 display_x11->have_xcomposite = FALSE;
255 if (XDamageQueryExtension (display_x11->xdisplay,
256 &display_x11->xdamage_event_base,
259 display_x11->have_xdamage = TRUE;
261 gdk_x11_register_standard_event_type (display,
262 display_x11->xdamage_event_base,
263 XDamageNumberEvents);
267 display_x11->have_xdamage = FALSE;
269 display_x11->have_shapes = FALSE;
270 display_x11->have_input_shapes = FALSE;
271 #ifdef HAVE_SHAPE_EXT
272 if (XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display), &ignore, &ignore))
274 display_x11->have_shapes = TRUE;
276 if (XShapeQueryVersion (GDK_DISPLAY_XDISPLAY (display), &maj, &min))
277 display_x11->have_input_shapes = (maj == 1 && min >= 1);
282 display_x11->trusted_client = TRUE;
285 int rootx, rooty, winx, winy;
288 gdk_error_trap_push ();
289 XQueryPointer (display_x11->xdisplay,
290 GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window,
291 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
293 if (G_UNLIKELY (gdk_error_trap_pop () == BadWindow))
295 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));
296 display_x11->trusted_client = FALSE;
300 if (_gdk_synchronize)
301 XSynchronize (display_x11->xdisplay, True);
303 class_hint = XAllocClassHint();
304 class_hint->res_name = g_get_prgname ();
306 class_hint->res_class = (char *)gdk_get_program_class ();
308 /* XmbSetWMProperties sets the RESOURCE_NAME environment variable
309 * from argv[0], so we just synthesize an argument array here.
312 argv[0] = g_get_prgname ();
314 XmbSetWMProperties (display_x11->xdisplay,
315 display_x11->leader_window,
316 NULL, NULL, argv, argc, NULL, NULL,
320 sm_client_id = _gdk_get_sm_client_id ();
322 _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
325 XChangeProperty (display_x11->xdisplay,
326 display_x11->leader_window,
327 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
328 XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
330 /* We don't yet know a valid time. */
331 display_x11->user_time = 0;
335 gint xkb_major = XkbMajorVersion;
336 gint xkb_minor = XkbMinorVersion;
337 if (XkbLibraryVersion (&xkb_major, &xkb_minor))
339 xkb_major = XkbMajorVersion;
340 xkb_minor = XkbMinorVersion;
342 if (XkbQueryExtension (display_x11->xdisplay,
343 NULL, &display_x11->xkb_event_type, NULL,
344 &xkb_major, &xkb_minor))
346 Bool detectable_autorepeat_supported;
348 display_x11->use_xkb = TRUE;
350 XkbSelectEvents (display_x11->xdisplay,
352 XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
353 XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
355 /* keep this in sync with _gdk_keymap_state_changed() */
356 XkbSelectEventDetails (display_x11->xdisplay,
357 XkbUseCoreKbd, XkbStateNotify,
358 XkbAllStateComponentsMask,
359 XkbGroupLockMask|XkbModifierLockMask);
361 XkbSetDetectableAutoRepeat (display_x11->xdisplay,
363 &detectable_autorepeat_supported);
365 GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
366 detectable_autorepeat_supported ?
367 "supported" : "not supported"));
369 display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
375 display_x11->use_sync = FALSE;
379 int error_base, event_base;
381 if (XSyncQueryExtension (display_x11->xdisplay,
382 &event_base, &error_base) &&
383 XSyncInitialize (display_x11->xdisplay,
385 display_x11->use_sync = TRUE;
389 _gdk_windowing_image_init (display);
390 _gdk_events_init (display);
391 _gdk_input_init (display);
392 _gdk_dnd_init (display);
394 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
395 gdk_display_request_selection_notification (display,
396 GDK_SCREEN_X11 (display_x11->screens[i])->cm_selection_atom);
398 g_signal_emit_by_name (gdk_display_manager_get(),
399 "display_opened", display);
406 * XLib internal connection handling
408 typedef struct _GdkInternalConnection GdkInternalConnection;
410 struct _GdkInternalConnection
418 process_internal_connection (GIOChannel *gioc,
422 GdkInternalConnection *connection = (GdkInternalConnection *)data;
424 GDK_THREADS_ENTER ();
426 XProcessInternalConnection ((Display*)connection->display, connection->fd);
428 GDK_THREADS_LEAVE ();
433 static GdkInternalConnection *
434 gdk_add_connection_handler (Display *display,
437 GIOChannel *io_channel;
438 GdkInternalConnection *connection;
440 connection = g_new (GdkInternalConnection, 1);
443 connection->display = display;
445 io_channel = g_io_channel_unix_new (fd);
447 connection->source = g_io_create_watch (io_channel, G_IO_IN);
448 g_source_set_callback (connection->source,
449 (GSourceFunc)process_internal_connection, connection, NULL);
450 g_source_attach (connection->source, NULL);
452 g_io_channel_unref (io_channel);
458 gdk_remove_connection_handler (GdkInternalConnection *connection)
460 g_source_destroy (connection->source);
465 gdk_internal_connection_watch (Display *display,
469 XPointer *watch_data)
472 *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
474 gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
476 #endif /* HAVE_X11R6 */
479 * gdk_display_get_name:
480 * @display: a #GdkDisplay
482 * Gets the name of the display.
484 * Returns: a string representing the display name. This string is owned
485 * by GDK and should not be modified or freed.
489 G_CONST_RETURN gchar *
490 gdk_display_get_name (GdkDisplay *display)
492 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
494 return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
498 * gdk_display_get_n_screens:
499 * @display: a #GdkDisplay
501 * Gets the number of screen managed by the @display.
503 * Returns: number of screens.
508 gdk_display_get_n_screens (GdkDisplay *display)
510 g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
512 return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
516 * gdk_display_get_screen:
517 * @display: a #GdkDisplay
518 * @screen_num: the screen number
520 * Returns a screen object for one of the screens of the display.
522 * Returns: the #GdkScreen object
527 gdk_display_get_screen (GdkDisplay *display,
530 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
531 g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
533 return GDK_DISPLAY_X11 (display)->screens[screen_num];
537 * gdk_display_get_default_screen:
538 * @display: a #GdkDisplay
540 * Get the default #GdkScreen for @display.
542 * Returns: the default #GdkScreen object for @display
547 gdk_display_get_default_screen (GdkDisplay *display)
549 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
551 return GDK_DISPLAY_X11 (display)->default_screen;
555 _gdk_x11_display_is_root_window (GdkDisplay *display,
558 GdkDisplayX11 *display_x11;
561 g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
563 display_x11 = GDK_DISPLAY_X11 (display);
565 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
567 if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
573 #define XSERVER_TIME_IS_LATER(time1, time2) \
574 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
575 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
579 * gdk_display_pointer_ungrab:
580 * @display: a #GdkDisplay.
581 * @time_: a timestap (e.g. %GDK_CURRENT_TIME).
583 * Release any pointer grab.
588 gdk_display_pointer_ungrab (GdkDisplay *display,
592 GdkDisplayX11 *display_x11;
594 g_return_if_fail (GDK_IS_DISPLAY (display));
596 display_x11 = GDK_DISPLAY_X11 (display);
597 xdisplay = GDK_DISPLAY_XDISPLAY (display);
599 _gdk_input_ungrab_pointer (display, time);
600 XUngrabPointer (xdisplay, time);
603 if (time == GDK_CURRENT_TIME ||
604 display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
605 !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
606 display_x11->pointer_xgrab_window = NULL;
610 * gdk_display_pointer_is_grabbed:
611 * @display: a #GdkDisplay
613 * Test if the pointer is grabbed.
615 * Returns: %TRUE if an active X pointer grab is in effect
620 gdk_display_pointer_is_grabbed (GdkDisplay *display)
622 g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
624 return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
625 !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
629 * gdk_display_keyboard_ungrab:
630 * @display: a #GdkDisplay.
631 * @time_: a timestap (e.g #GDK_CURRENT_TIME).
633 * Release any keyboard grab
638 gdk_display_keyboard_ungrab (GdkDisplay *display,
642 GdkDisplayX11 *display_x11;
644 g_return_if_fail (GDK_IS_DISPLAY (display));
646 display_x11 = GDK_DISPLAY_X11 (display);
647 xdisplay = GDK_DISPLAY_XDISPLAY (display);
649 XUngrabKeyboard (xdisplay, time);
652 if (time == GDK_CURRENT_TIME ||
653 display_x11->keyboard_xgrab_time == GDK_CURRENT_TIME ||
654 !XSERVER_TIME_IS_LATER (display_x11->keyboard_xgrab_time, time))
655 display_x11->keyboard_xgrab_window = NULL;
660 * @display: a #GdkDisplay
662 * Emits a short beep on @display
667 gdk_display_beep (GdkDisplay *display)
669 g_return_if_fail (GDK_IS_DISPLAY (display));
671 XBell (GDK_DISPLAY_XDISPLAY (display), 0);
676 * @display: a #GdkDisplay
678 * Flushes any requests queued for the windowing system and waits until all
679 * requests have been handled. This is often used for making sure that the
680 * display is synchronized with the current state of the program. Calling
681 * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
682 * generated from earlier requests are handled before the error trap is
685 * This is most useful for X11. On windowing systems where requests are
686 * handled synchronously, this function will do nothing.
691 gdk_display_sync (GdkDisplay *display)
693 g_return_if_fail (GDK_IS_DISPLAY (display));
695 XSync (GDK_DISPLAY_XDISPLAY (display), False);
700 * @display: a #GdkDisplay
702 * Flushes any requests queued for the windowing system; this happens automatically
703 * when the main loop blocks waiting for new events, but if your application
704 * is drawing without returning control to the main loop, you may need
705 * to call this function explicitely. A common case where this function
706 * needs to be called is when an application is executing drawing commands
707 * from a thread other than the thread where the main loop is running.
709 * This is most useful for X11. On windowing systems where requests are
710 * handled synchronously, this function will do nothing.
715 gdk_display_flush (GdkDisplay *display)
717 g_return_if_fail (GDK_IS_DISPLAY (display));
719 if (!display->closed)
720 XFlush (GDK_DISPLAY_XDISPLAY (display));
724 * gdk_display_get_default_group:
725 * @display: a #GdkDisplay
727 * Returns the default group leader window for all toplevel windows
728 * on @display. This window is implicitly created by GDK.
729 * See gdk_window_set_group().
731 * Return value: The default group leader window for @display
736 gdk_display_get_default_group (GdkDisplay *display)
738 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
740 return GDK_DISPLAY_X11 (display)->leader_gdk_window;
744 * gdk_x11_display_grab:
745 * @display: a #GdkDisplay
747 * Call XGrabServer() on @display.
748 * To ungrab the display again, use gdk_x11_display_ungrab().
750 * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
755 gdk_x11_display_grab (GdkDisplay *display)
757 GdkDisplayX11 *display_x11;
759 g_return_if_fail (GDK_IS_DISPLAY (display));
761 display_x11 = GDK_DISPLAY_X11 (display);
763 if (display_x11->grab_count == 0)
764 XGrabServer (display_x11->xdisplay);
765 display_x11->grab_count++;
769 * gdk_x11_display_ungrab:
770 * @display: a #GdkDisplay
772 * Ungrab @display after it has been grabbed with
773 * gdk_x11_display_grab().
778 gdk_x11_display_ungrab (GdkDisplay *display)
780 GdkDisplayX11 *display_x11;
782 g_return_if_fail (GDK_IS_DISPLAY (display));
784 display_x11 = GDK_DISPLAY_X11 (display);;
785 g_return_if_fail (display_x11->grab_count > 0);
787 display_x11->grab_count--;
788 if (display_x11->grab_count == 0)
790 XUngrabServer (display_x11->xdisplay);
791 XFlush (display_x11->xdisplay);
796 gdk_display_x11_dispose (GObject *object)
798 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
801 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
802 _gdk_screen_close (display_x11->screens[i]);
804 _gdk_events_uninit (GDK_DISPLAY_OBJECT (object));
806 G_OBJECT_CLASS (_gdk_display_x11_parent_class)->dispose (object);
810 gdk_display_x11_finalize (GObject *object)
812 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
816 if (display_x11->keymap)
817 g_object_unref (display_x11->keymap);
820 if (display_x11->motif_target_lists)
822 for (i = 0; i < display_x11->motif_n_target_lists; i++)
823 g_list_free (display_x11->motif_target_lists[i]);
824 g_free (display_x11->motif_target_lists);
828 g_hash_table_destroy (display_x11->atom_from_virtual);
829 g_hash_table_destroy (display_x11->atom_to_virtual);
832 XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
834 /* list of filters for client messages */
835 g_list_foreach (display_x11->client_filters, (GFunc) g_free, NULL);
836 g_list_free (display_x11->client_filters);
838 /* List of event window extraction functions */
839 g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
840 g_slist_free (display_x11->event_types);
842 /* input GdkDevice list */
843 g_list_foreach (display_x11->input_devices, (GFunc) g_object_unref, NULL);
844 g_list_free (display_x11->input_devices);
846 /* input GdkWindow list */
847 g_list_foreach (display_x11->input_windows, (GFunc) g_free, NULL);
848 g_list_free (display_x11->input_windows);
850 /* Free all GdkScreens */
851 for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
852 g_object_unref (display_x11->screens[i]);
853 g_free (display_x11->screens);
855 g_free (display_x11->startup_notification_id);
858 g_hash_table_destroy (display_x11->xid_ht);
860 XCloseDisplay (display_x11->xdisplay);
862 G_OBJECT_CLASS (_gdk_display_x11_parent_class)->finalize (object);
866 * gdk_x11_lookup_xdisplay:
867 * @xdisplay: a pointer to an X Display
869 * Find the #GdkDisplay corresponding to @display, if any exists.
871 * Return value: the #GdkDisplay, if found, otherwise %NULL.
876 gdk_x11_lookup_xdisplay (Display *xdisplay)
880 for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
882 if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
883 return tmp_list->data;
890 * _gdk_x11_display_screen_for_xrootwin:
891 * @display: a #GdkDisplay
892 * @xrootwin: window ID for one of of the screen's of the display.
894 * Given the root window ID of one of the screen's of a #GdkDisplay,
897 * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
900 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
905 for (i = 0; i < ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay); i++)
907 GdkScreen *screen = gdk_display_get_screen (display, i);
908 if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
916 * gdk_x11_display_get_xdisplay:
917 * @display: a #GdkDisplay
918 * @returns: an X display.
920 * Returns the X display of a #GdkDisplay.
925 gdk_x11_display_get_xdisplay (GdkDisplay *display)
927 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
928 return GDK_DISPLAY_X11 (display)->xdisplay;
932 _gdk_windowing_set_default_display (GdkDisplay *display)
934 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
935 const gchar *startup_id;
943 gdk_display = GDK_DISPLAY_XDISPLAY (display);
945 g_free (display_x11->startup_notification_id);
946 display_x11->startup_notification_id = NULL;
948 startup_id = g_getenv ("DESKTOP_STARTUP_ID");
949 if (startup_id && *startup_id != '\0')
953 if (!g_utf8_validate (startup_id, -1, NULL))
954 g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
956 display_x11->startup_notification_id = g_strdup (startup_id);
958 /* Find the launch time from the startup_id, if it's there. Newer spec
959 * states that the startup_id is of the form <unique>_TIME<timestamp>
961 time_str = g_strrstr (startup_id, "_TIME");
962 if (time_str != NULL)
968 /* Skip past the "_TIME" part */
971 retval = strtoul (time_str, &end, 0);
972 if (end != time_str && errno == 0)
973 display_x11->user_time = retval;
976 /* Clear the environment variable so it won't be inherited by
977 * child processes and confuse things.
979 g_unsetenv ("DESKTOP_STARTUP_ID");
981 /* Set the startup id on the leader window so it
982 * applies to all windows we create on this display
984 XChangeProperty (display_x11->xdisplay,
985 display_x11->leader_window,
986 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
987 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
989 (guchar *)startup_id, strlen (startup_id));
994 broadcast_xmessage (GdkDisplay *display,
995 const char *message_type,
996 const char *message_type_begin,
999 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1000 GdkScreen *screen = gdk_display_get_default_screen (display);
1001 GdkWindow *root_window = gdk_screen_get_root_window (screen);
1002 Window xroot_window = GDK_WINDOW_XID (root_window);
1005 Atom type_atom_begin;
1008 if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1012 XSetWindowAttributes attrs;
1014 attrs.override_redirect = True;
1015 attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
1018 XCreateWindow (xdisplay,
1024 (Visual *)CopyFromParent,
1025 CWOverrideRedirect | CWEventMask,
1029 type_atom = gdk_x11_get_xatom_by_name_for_display (display,
1031 type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
1032 message_type_begin);
1035 XClientMessageEvent xclient;
1037 const char *src_end;
1041 memset(&xclient, 0, sizeof (xclient));
1042 xclient.type = ClientMessage;
1043 xclient.message_type = type_atom_begin;
1044 xclient.display =xdisplay;
1045 xclient.window = xwindow;
1049 src_end = message + strlen (message) + 1; /* +1 to include nul byte */
1051 while (src != src_end)
1053 dest = &xclient.data.b[0];
1054 dest_end = dest + 20;
1056 while (dest != dest_end &&
1064 while (dest != dest_end)
1070 XSendEvent (xdisplay,
1074 (XEvent *)&xclient);
1076 xclient.message_type = type_atom;
1080 XDestroyWindow (xdisplay, xwindow);
1085 * gdk_x11_display_broadcast_startup_message:
1086 * @display: a #GdkDisplay
1087 * @message_type: startup notification message type ("new", "change",
1089 * @...: a list of key/value pairs (as strings), terminated by a
1090 * %NULL key. (A %NULL value for a key will cause that key to be
1091 * skipped in the output.)
1093 * Sends a startup notification message of type @message_type to
1096 * This is a convenience function for use by code that implements the
1097 * freedesktop startup notification specification. Applications should
1098 * not normally need to call it directly. See the <ulink
1099 * url="http://standards.freedesktop.org/startup-notification-spec/startup-notification-latest.txt">Startup
1100 * Notification Protocol specification</ulink> for
1101 * definitions of the message types and keys that can be used.
1106 gdk_x11_display_broadcast_startup_message (GdkDisplay *display,
1107 const char *message_type,
1112 const char *key, *value, *p;
1114 message = g_string_new (message_type);
1115 g_string_append_c (message, ':');
1117 va_start (ap, message_type);
1118 while ((key = va_arg (ap, const char *)))
1120 value = va_arg (ap, const char *);
1124 g_string_append_printf (message, " %s=\"", key);
1125 for (p = value; *p; p++)
1132 g_string_append_c (message, '\\');
1136 g_string_append_c (message, *p);
1138 g_string_append_c (message, '\"');
1142 broadcast_xmessage (display,
1143 "_NET_STARTUP_INFO",
1144 "_NET_STARTUP_INFO_BEGIN",
1147 g_string_free (message, TRUE);
1151 * gdk_notify_startup_complete:
1153 * Indicates to the GUI environment that the application has finished
1154 * loading. If the applications opens windows, this function is
1155 * normally called after opening the application's initial set of
1158 * GTK+ will call this function automatically after opening the first
1159 * #GtkWindow unless gtk_window_set_auto_startup_notification() is called
1160 * to disable that feature.
1165 gdk_notify_startup_complete (void)
1167 GdkDisplay *display;
1168 GdkDisplayX11 *display_x11;
1170 display = gdk_display_get_default ();
1174 display_x11 = GDK_DISPLAY_X11 (display);
1176 if (display_x11->startup_notification_id == NULL)
1179 gdk_notify_startup_complete_with_id (display_x11->startup_notification_id);
1183 * gdk_notify_startup_complete_with_id:
1184 * @startup_id: a startup-notification identifier, for which notification
1185 * process should be completed
1187 * Indicates to the GUI environment that the application has finished
1188 * loading, using a given identifier.
1190 * GTK+ will call this function automatically for #GtkWindow with custom
1191 * startup-notification identifier unless
1192 * gtk_window_set_auto_startup_notification() is called to disable
1198 gdk_notify_startup_complete_with_id (const gchar* startup_id)
1200 GdkDisplay *display;
1202 display = gdk_display_get_default ();
1206 gdk_x11_display_broadcast_startup_message (display, "remove",
1212 * gdk_display_supports_selection_notification:
1213 * @display: a #GdkDisplay
1215 * Returns whether #GdkEventOwnerChange events will be
1216 * sent when the owner of a selection changes.
1218 * Return value: whether #GdkEventOwnerChange events will
1224 gdk_display_supports_selection_notification (GdkDisplay *display)
1226 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1228 return display_x11->have_xfixes;
1232 * gdk_display_request_selection_notification:
1233 * @display: a #GdkDisplay
1234 * @selection: the #GdkAtom naming the selection for which
1235 * ownership change notification is requested
1237 * Request #GdkEventOwnerChange events for ownership changes
1238 * of the selection named by the given atom.
1240 * Return value: whether #GdkEventOwnerChange events will
1246 gdk_display_request_selection_notification (GdkDisplay *display,
1251 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1254 if (display_x11->have_xfixes)
1256 atom = gdk_x11_atom_to_xatom_for_display (display,
1258 XFixesSelectSelectionInput (display_x11->xdisplay,
1259 display_x11->leader_window,
1261 XFixesSetSelectionOwnerNotifyMask |
1262 XFixesSelectionWindowDestroyNotifyMask |
1263 XFixesSelectionClientCloseNotifyMask);
1272 * gdk_display_supports_clipboard_persistence
1273 * @display: a #GdkDisplay
1275 * Returns whether the speicifed display supports clipboard
1276 * persistance; i.e. if it's possible to store the clipboard data after an
1277 * application has quit. On X11 this checks if a clipboard daemon is
1280 * Returns: %TRUE if the display supports clipboard persistance.
1285 gdk_display_supports_clipboard_persistence (GdkDisplay *display)
1287 Atom clipboard_manager;
1289 /* It might make sense to cache this */
1290 clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1291 return XGetSelectionOwner (GDK_DISPLAY_X11 (display)->xdisplay, clipboard_manager) != None;
1295 * gdk_display_store_clipboard
1296 * @display: a #GdkDisplay
1297 * @clipboard_window: a #GdkWindow belonging to the clipboard owner
1298 * @time_: a timestamp
1299 * @targets: an array of targets that should be saved, or %NULL
1300 * if all available targets should be saved.
1301 * @n_targets: length of the @targets array
1303 * Issues a request to the clipboard manager to store the
1304 * clipboard data. On X11, this is a special program that works
1305 * according to the freedesktop clipboard specification, available at
1306 * <ulink url="http://www.freedesktop.org/Standards/clipboard-manager-spec">
1307 * http://www.freedesktop.org/Standards/clipboard-manager-spec</ulink>.
1312 gdk_display_store_clipboard (GdkDisplay *display,
1313 GdkWindow *clipboard_window,
1315 const GdkAtom *targets,
1318 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1319 Atom clipboard_manager, save_targets;
1321 clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
1322 save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
1324 gdk_error_trap_push ();
1326 if (XGetSelectionOwner (display_x11->xdisplay, clipboard_manager) != None)
1328 Atom property_name = None;
1334 property_name = gdk_x11_atom_to_xatom_for_display (display, _gdk_selection_property);
1336 xatoms = g_new (Atom, n_targets);
1337 for (i = 0; i < n_targets; i++)
1338 xatoms[i] = gdk_x11_atom_to_xatom_for_display (display, targets[i]);
1340 XChangeProperty (display_x11->xdisplay, GDK_WINDOW_XID (clipboard_window),
1341 property_name, XA_ATOM,
1342 32, PropModeReplace, (guchar *)xatoms, n_targets);
1347 XConvertSelection (display_x11->xdisplay,
1348 clipboard_manager, save_targets, property_name,
1349 GDK_WINDOW_XID (clipboard_window), time_);
1352 gdk_error_trap_pop ();
1357 * gdk_x11_display_get_user_time:
1358 * @display: a #GdkDisplay
1360 * Returns the timestamp of the last user interaction on
1361 * @display. The timestamp is taken from events caused
1362 * by user interaction such as key presses or pointer
1363 * movements. See gdk_x11_window_set_user_time().
1365 * Returns: the timestamp of the last user interaction
1370 gdk_x11_display_get_user_time (GdkDisplay *display)
1372 return GDK_DISPLAY_X11 (display)->user_time;
1376 * gdk_display_supports_shapes:
1377 * @display: a #GdkDisplay
1379 * Returns %TRUE if gdk_window_shape_combine_mask() can
1380 * be used to create shaped windows on @display.
1382 * Returns: %TRUE if shaped windows are supported
1387 gdk_display_supports_shapes (GdkDisplay *display)
1389 return GDK_DISPLAY_X11 (display)->have_shapes;
1393 * gdk_display_supports_input_shapes:
1394 * @display: a #GdkDisplay
1396 * Returns %TRUE if gdk_window_input_shape_combine_mask() can
1397 * be used to modify the input shape of windows on @display.
1399 * Returns: %TRUE if windows with modified input shape are supported
1404 gdk_display_supports_input_shapes (GdkDisplay *display)
1406 return GDK_DISPLAY_X11 (display)->have_input_shapes;
1411 * gdk_x11_display_get_startup_notification_id:
1412 * @display: a #GdkDisplay
1414 * Gets the startup notification ID for a display.
1416 * Returns: the startup notification ID for @display
1420 G_CONST_RETURN gchar *
1421 gdk_x11_display_get_startup_notification_id (GdkDisplay *display)
1423 return GDK_DISPLAY_X11 (display)->startup_notification_id;
1427 * gdk_display_supports_composite:
1428 * @display: a #GdkDisplay
1430 * Returns %TRUE if gdk_window_set_composited() can be used
1431 * to redirect drawing on the window using compositing.
1433 * Currently this only works on X11 with XComposite and
1434 * XDamage extensions available.
1436 * Returns: %TRUE if windows may be composited.
1441 gdk_display_supports_composite (GdkDisplay *display)
1443 GdkDisplayX11 *x11_display = GDK_DISPLAY_X11 (display);
1445 return x11_display->have_xcomposite &&
1446 x11_display->have_xdamage &&
1447 x11_display->have_xfixes;
1451 #define __GDK_DISPLAY_X11_C__
1452 #include "gdkaliasdef.c"