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