]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkdisplay-x11.c
Check for XFIXES extension.
[~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  *
6  * Erwann Chenede <erwann.chenede@sun.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #include <config.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #include <glib.h>
31 #include "gdkx.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
34 #include "gdkscreen.h"
35 #include "gdkscreen-x11.h"
36 #include "gdkinternals.h"
37 #include "gdkinputprivate.h"
38 #include "xsettings-client.h"
39
40 #include <X11/Xatom.h>
41
42 #ifdef HAVE_XKB
43 #include <X11/XKBlib.h>
44 #endif
45
46 #ifdef HAVE_XFIXES
47 #include <X11/extensions/Xfixes.h>
48 #endif
49
50 static void                 gdk_display_x11_class_init         (GdkDisplayX11Class *class);
51 static void                 gdk_display_x11_dispose            (GObject            *object);
52 static void                 gdk_display_x11_finalize           (GObject            *object);
53
54 #ifdef HAVE_X11R6
55 static void gdk_internal_connection_watch (Display  *display,
56                                            XPointer  arg,
57                                            gint      fd,
58                                            gboolean  opening,
59                                            XPointer *watch_data);
60 #endif /* HAVE_X11R6 */
61
62 static gpointer parent_class = NULL;
63
64 /* Note that we never *directly* use WM_LOCALE_NAME, WM_PROTOCOLS,
65  * but including them here has the side-effect of getting them
66  * into the internal Xlib cache
67  */
68 static const char *const precache_atoms[] = {
69   "UTF8_STRING",
70   "WM_CLIENT_LEADER",
71   "WM_DELETE_WINDOW",
72   "WM_LOCALE_NAME",
73   "WM_PROTOCOLS",
74   "WM_TAKE_FOCUS",
75   "_NET_WM_DESKTOP",
76   "_NET_WM_ICON",
77   "_NET_WM_ICON_NAME",
78   "_NET_WM_NAME",
79   "_NET_WM_PID",
80   "_NET_WM_PING",
81   "_NET_WM_STATE",
82   "_NET_WM_STATE_STICKY",
83   "_NET_WM_STATE_MAXIMIZED_VERT",
84   "_NET_WM_STATE_MAXIMIZED_HORZ",
85   "_NET_WM_STATE_FULLSCREEN",
86   "_NET_WM_WINDOW_TYPE",
87   "_NET_WM_WINDOW_TYPE_NORMAL",
88   "_NET_WM_USER_TIME",
89 };
90
91 GType
92 _gdk_display_x11_get_type (void)
93 {
94   static GType object_type = 0;
95
96   if (!object_type)
97     {
98       static const GTypeInfo object_info =
99         {
100           sizeof (GdkDisplayX11Class),
101           (GBaseInitFunc) NULL,
102           (GBaseFinalizeFunc) NULL,
103           (GClassInitFunc) gdk_display_x11_class_init,
104           NULL,                 /* class_finalize */
105           NULL,                 /* class_data */
106           sizeof (GdkDisplayX11),
107           0,                    /* n_preallocs */
108           (GInstanceInitFunc) NULL,
109         };
110       
111       object_type = g_type_register_static (GDK_TYPE_DISPLAY,
112                                             "GdkDisplayX11",
113                                             &object_info, 0);
114     }
115   
116   return object_type;
117 }
118
119 static void
120 gdk_display_x11_class_init (GdkDisplayX11Class * class)
121 {
122   GObjectClass *object_class = G_OBJECT_CLASS (class);
123   
124   object_class->dispose = gdk_display_x11_dispose;
125   object_class->finalize = gdk_display_x11_finalize;
126   
127   parent_class = g_type_class_peek_parent (class);
128 }
129
130 /**
131  * gdk_display_open:
132  * @display_name: the name of the display to open
133  * @returns: a #GdkDisplay, or %NULL if the display
134  *  could not be opened.
135  *
136  * Opens a display.
137  *
138  * Since: 2.2
139  */
140 GdkDisplay *
141 gdk_display_open (const gchar *display_name)
142 {
143   Display *xdisplay;
144   GdkDisplay *display;
145   GdkDisplayX11 *display_x11;
146   GdkWindowAttr attr;
147   gint argc;
148   gchar **argv;
149   const char *sm_client_id;
150   
151   XClassHint *class_hint;
152   gulong pid;
153   gint i;
154   gint ignore;
155
156   xdisplay = XOpenDisplay (display_name);
157   if (!xdisplay)
158     return NULL;
159   
160   display = g_object_new (GDK_TYPE_DISPLAY_X11, NULL);
161   display_x11 = GDK_DISPLAY_X11 (display);
162
163   display_x11->use_xshm = TRUE;
164   display_x11->xdisplay = xdisplay;
165
166 #ifdef HAVE_X11R6  
167   /* Set up handlers for Xlib internal connections */
168   XAddConnectionWatch (xdisplay, gdk_internal_connection_watch, NULL);
169 #endif /* HAVE_X11R6 */
170   
171   /* initialize the display's screens */ 
172   display_x11->screens = g_new (GdkScreen *, ScreenCount (display_x11->xdisplay));
173   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
174     display_x11->screens[i] = _gdk_x11_screen_new (display, i);
175
176   /* We need to initialize events after we have the screen
177    * structures in places
178    */
179   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
180     _gdk_x11_events_init_screen (display_x11->screens[i]);
181   
182   /*set the default screen */
183   display_x11->default_screen = display_x11->screens[DefaultScreen (display_x11->xdisplay)];
184
185   attr.window_type = GDK_WINDOW_TOPLEVEL;
186   attr.wclass = GDK_INPUT_OUTPUT;
187   attr.x = 10;
188   attr.y = 10;
189   attr.width = 10;
190   attr.height = 10;
191   attr.event_mask = 0;
192
193   display_x11->leader_gdk_window = gdk_window_new (GDK_SCREEN_X11 (display_x11->default_screen)->root_window, 
194                                                    &attr, GDK_WA_X | GDK_WA_Y);
195   display_x11->leader_window = GDK_WINDOW_XID (display_x11->leader_gdk_window);
196
197   display_x11->leader_window_title_set = FALSE;
198
199   display_x11->have_render = GDK_UNKNOWN;
200
201 #ifdef HAVE_XFIXES
202   if (XFixesQueryExtension (display_x11->xdisplay, 
203                             &display_x11->xfixes_event_base, 
204                             &ignore))
205     {
206       display_x11->have_xfixes = TRUE;
207
208       gdk_x11_register_standard_event_type (display,
209                                             display_x11->xfixes_event_base, 
210                                             XFixesNumberEvents);
211     }
212   else
213 #endif
214   display_x11->have_xfixes = FALSE;
215
216   if (_gdk_synchronize)
217     XSynchronize (display_x11->xdisplay, True);
218   
219   _gdk_x11_precache_atoms (display, precache_atoms, G_N_ELEMENTS (precache_atoms));
220
221   class_hint = XAllocClassHint();
222   class_hint->res_name = g_get_prgname ();
223   
224   class_hint->res_class = (char *)gdk_get_program_class ();
225   _gdk_get_command_line_args (&argc, &argv);
226   XmbSetWMProperties (display_x11->xdisplay,
227                       display_x11->leader_window,
228                       NULL, NULL, argv, argc, NULL, NULL,
229                       class_hint);
230   XFree (class_hint);
231
232   sm_client_id = _gdk_get_sm_client_id ();
233   if (sm_client_id)
234     _gdk_windowing_display_set_sm_client_id (display, sm_client_id);
235
236   pid = getpid ();
237   XChangeProperty (display_x11->xdisplay,
238                    display_x11->leader_window,
239                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PID"),
240                    XA_CARDINAL, 32, PropModeReplace, (guchar *) & pid, 1);
241
242   /* We don't yet know a valid time. */
243   display_x11->user_time = 0;
244   
245 #ifdef HAVE_XKB
246   {
247     gint xkb_major = XkbMajorVersion;
248     gint xkb_minor = XkbMinorVersion;
249     if (XkbLibraryVersion (&xkb_major, &xkb_minor))
250       {
251         xkb_major = XkbMajorVersion;
252         xkb_minor = XkbMinorVersion;
253             
254         if (XkbQueryExtension (display_x11->xdisplay, 
255                                NULL, &display_x11->xkb_event_type, NULL,
256                                &xkb_major, &xkb_minor))
257           {
258             Bool detectable_autorepeat_supported;
259             
260             display_x11->use_xkb = TRUE;
261
262             XkbSelectEvents (display_x11->xdisplay,
263                              XkbUseCoreKbd,
264                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask,
265                              XkbNewKeyboardNotifyMask | XkbMapNotifyMask | XkbStateNotifyMask);
266
267             XkbSetDetectableAutoRepeat (display_x11->xdisplay,
268                                         True,
269                                         &detectable_autorepeat_supported);
270
271             GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.",
272                                        detectable_autorepeat_supported ? 
273                                        "supported" : "not supported"));
274             
275             display_x11->have_xkb_autorepeat = detectable_autorepeat_supported;
276           }
277       }
278   }
279 #endif
280
281   _gdk_windowing_image_init (display);
282   _gdk_events_init (display);
283   _gdk_input_init (display);
284   _gdk_dnd_init (display);
285
286   g_signal_emit_by_name (gdk_display_manager_get(),
287                          "display_opened", display);
288
289   return display;
290 }
291
292 #ifdef HAVE_X11R6
293 /*
294  * XLib internal connection handling
295  */
296 typedef struct _GdkInternalConnection GdkInternalConnection;
297
298 struct _GdkInternalConnection
299 {
300   gint           fd;
301   GSource       *source;
302   Display       *display;
303 };
304
305 static gboolean
306 process_internal_connection (GIOChannel  *gioc,
307                              GIOCondition cond,
308                              gpointer     data)
309 {
310   GdkInternalConnection *connection = (GdkInternalConnection *)data;
311
312   GDK_THREADS_ENTER ();
313
314   XProcessInternalConnection ((Display*)connection->display, connection->fd);
315
316   GDK_THREADS_LEAVE ();
317
318   return TRUE;
319 }
320
321 static GdkInternalConnection *
322 gdk_add_connection_handler (Display *display,
323                             guint    fd)
324 {
325   GIOChannel *io_channel;
326   GdkInternalConnection *connection;
327
328   connection = g_new (GdkInternalConnection, 1);
329
330   connection->fd = fd;
331   connection->display = display;
332   
333   io_channel = g_io_channel_unix_new (fd);
334   
335   connection->source = g_io_create_watch (io_channel, G_IO_IN);
336   g_source_set_callback (connection->source,
337                          (GSourceFunc)process_internal_connection, connection, NULL);
338   g_source_attach (connection->source, NULL);
339   
340   g_io_channel_unref (io_channel);
341   
342   return connection;
343 }
344
345 static void
346 gdk_remove_connection_handler (GdkInternalConnection *connection)
347 {
348   g_source_destroy (connection->source);
349   g_free (connection);
350 }
351
352 static void
353 gdk_internal_connection_watch (Display  *display,
354                                XPointer  arg,
355                                gint      fd,
356                                gboolean  opening,
357                                XPointer *watch_data)
358 {
359   if (opening)
360     *watch_data = (XPointer)gdk_add_connection_handler (display, fd);
361   else
362     gdk_remove_connection_handler ((GdkInternalConnection *)*watch_data);
363 }
364 #endif /* HAVE_X11R6 */
365
366 /**
367  * gdk_display_get_name:
368  * @display: a #GdkDisplay
369  *
370  * Gets the name of the display.
371  * 
372  * Returns: a string representing the display name. This string is owned
373  * by GDK and should not be modified or freed.
374  * 
375  * Since: 2.2
376  */
377 G_CONST_RETURN gchar *
378 gdk_display_get_name (GdkDisplay * display)
379 {
380   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
381   
382   return (gchar *) DisplayString (GDK_DISPLAY_X11 (display)->xdisplay);
383 }
384
385 /**
386  * gdk_display_get_n_screens:
387  * @display: a #GdkDisplay
388  *
389  * Gets the number of screen managed by the @display.
390  * 
391  * Returns: number of screens.
392  * 
393  * Since: 2.2
394  */
395 gint
396 gdk_display_get_n_screens (GdkDisplay * display)
397 {
398   g_return_val_if_fail (GDK_IS_DISPLAY (display), 0);
399   
400   return ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay);
401 }
402
403 /**
404  * gdk_display_get_screen:
405  * @display: a #GdkDisplay
406  * @screen_num: the screen number
407  *
408  * Returns a screen object for one of the screens of the display.
409  *
410  * Returns: the #GdkScreen object
411  *
412  * Since: 2.2
413  */
414 GdkScreen *
415 gdk_display_get_screen (GdkDisplay * display, gint screen_num)
416 {
417   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
418   g_return_val_if_fail (ScreenCount (GDK_DISPLAY_X11 (display)->xdisplay) > screen_num, NULL);
419   
420   return GDK_DISPLAY_X11 (display)->screens[screen_num];
421 }
422
423 /**
424  * gdk_display_get_default_screen:
425  * @display: a #GdkDisplay
426  *
427  * Get the default #GdkScreen for @display.
428  * 
429  * Returns: the default #GdkScreen object for @display
430  *
431  * Since: 2.2
432  */
433 GdkScreen *
434 gdk_display_get_default_screen (GdkDisplay * display)
435 {
436   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
437   
438   return GDK_DISPLAY_X11 (display)->default_screen;
439 }
440
441 gboolean
442 _gdk_x11_display_is_root_window (GdkDisplay *display,
443                                  Window      xroot_window)
444 {
445   GdkDisplayX11 *display_x11;
446   gint i;
447   
448   g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
449   
450   display_x11 = GDK_DISPLAY_X11 (display);
451   
452   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
453     {
454       if (GDK_SCREEN_XROOTWIN (display_x11->screens[i]) == xroot_window)
455         return TRUE;
456     }
457   return FALSE;
458 }
459
460 /**
461  * gdk_display_pointer_ungrab:
462  * @display: a #GdkDisplay.
463  * @time_: a timestap (e.g. GDK_CURRENT_TIME).
464  *
465  * Release any pointer grab.
466  *
467  * Since: 2.2
468  */
469 void
470 gdk_display_pointer_ungrab (GdkDisplay *display,
471                             guint32     time)
472 {
473   Display *xdisplay;
474   
475   g_return_if_fail (GDK_IS_DISPLAY (display));
476
477   xdisplay = GDK_DISPLAY_XDISPLAY (display);
478   
479   _gdk_input_ungrab_pointer (display, time);
480   XUngrabPointer (xdisplay, time);
481   XFlush (xdisplay);
482   
483   GDK_DISPLAY_X11 (display)->pointer_xgrab_window = NULL;
484 }
485
486 /**
487  * gdk_display_pointer_is_grabbed:
488  * @display: a #GdkDisplay
489  *
490  * Test if the pointer is grabbed.
491  *
492  * Returns: %TRUE if an active X pointer grab is in effect
493  *
494  * Since: 2.2
495  */
496 gboolean
497 gdk_display_pointer_is_grabbed (GdkDisplay * display)
498 {
499   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
500   
501   return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL);
502 }
503
504 /**
505  * gdk_display_keyboard_ungrab:
506  * @display: a #GdkDisplay.
507  * @time_: a timestap (e.g #GDK_CURRENT_TIME).
508  *
509  * Release any keyboard grab
510  *
511  * Since: 2.2
512  */
513 void
514 gdk_display_keyboard_ungrab (GdkDisplay *display,
515                              guint32     time)
516 {
517   Display *xdisplay;
518   
519   g_return_if_fail (GDK_IS_DISPLAY (display));
520
521   xdisplay = GDK_DISPLAY_XDISPLAY (display);
522   
523   XUngrabKeyboard (xdisplay, time);
524   XFlush (xdisplay);
525   
526   GDK_DISPLAY_X11 (display)->keyboard_xgrab_window = NULL;
527 }
528
529 /**
530  * gdk_display_beep:
531  * @display: a #GdkDisplay
532  *
533  * Emits a short beep on @display
534  *
535  * Since: 2.2
536  */
537 void
538 gdk_display_beep (GdkDisplay * display)
539 {
540   g_return_if_fail (GDK_IS_DISPLAY (display));
541   
542   XBell (GDK_DISPLAY_XDISPLAY (display), 0);
543 }
544
545 /**
546  * gdk_display_sync:
547  * @display: a #GdkDisplay
548  *
549  * Flushes any requests queued for the windowing system and waits until all
550  * requests have been handled. This is often used for making sure that the
551  * display is synchronized with the current state of the program. Calling
552  * gdk_display_sync() before gdk_error_trap_pop() makes sure that any errors
553  * generated from earlier requests are handled before the error trap is 
554  * removed.
555  *
556  * This is most useful for X11. On windowing systems where requests are
557  * handled synchronously, this function will do nothing.
558  *
559  * Since: 2.2
560  */
561 void
562 gdk_display_sync (GdkDisplay * display)
563 {
564   g_return_if_fail (GDK_IS_DISPLAY (display));
565   
566   XSync (GDK_DISPLAY_XDISPLAY (display), False);
567 }
568
569 /**
570  * gdk_display_flush:
571  * @display: a #GdkDisplay
572  *
573  * Flushes any requests queued for the windowing system; this happens automatically
574  * when the main loop blocks waiting for new events, but if your application
575  * is drawing without returning control to the main loop, you may need
576  * to call this function explicitely. A common case where this function
577  * needs to be called is when an application is executing drawing commands
578  * from a thread other than the thread where the main loop is running.
579  *
580  * This is most useful for X11. On windowing systems where requests are
581  * handled synchronously, this function will do nothing.
582  *
583  * Since: 2.4
584  */
585 void 
586 gdk_display_flush (GdkDisplay *display)
587 {
588   g_return_if_fail (GDK_IS_DISPLAY (display));
589
590   if (!display->closed)
591     XFlush (GDK_DISPLAY_XDISPLAY (display));
592 }
593
594 /**
595  * gdk_display_get_default_group:
596  * @display: a #GdkDisplay
597  * 
598  * Returns the default group leader window for all toplevel windows
599  * on @display. This window is implicitly created by GDK. 
600  * See gdk_window_set_group().
601  * 
602  * Return value: The default group leader window for @display
603  *
604  * Since: 2.4
605  **/
606 GdkWindow *gdk_display_get_default_group (GdkDisplay *display)
607 {
608   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
609
610   return GDK_DISPLAY_X11 (display)->leader_gdk_window;
611 }
612
613 /**
614  * gdk_x11_display_grab:
615  * @display: a #GdkDisplay 
616  * 
617  * Call XGrabServer() on @display. 
618  * To ungrab the display again, use gdk_x11_display_ungrab(). 
619  *
620  * gdk_x11_display_grab()/gdk_x11_display_ungrab() calls can be nested.
621  *
622  * Since: 2.2
623  **/
624 void
625 gdk_x11_display_grab (GdkDisplay * display)
626 {
627   GdkDisplayX11 *display_x11;
628   
629   g_return_if_fail (GDK_IS_DISPLAY (display));
630   
631   display_x11 = GDK_DISPLAY_X11 (display);
632   
633   if (display_x11->grab_count == 0)
634     XGrabServer (display_x11->xdisplay);
635   display_x11->grab_count++;
636 }
637
638 /**
639  * gdk_x11_display_ungrab:
640  * @display: a #GdkDisplay
641  * 
642  * Ungrab @display after it has been grabbed with 
643  * gdk_x11_display_grab(). 
644  *
645  * Since: 2.2
646  **/
647 void
648 gdk_x11_display_ungrab (GdkDisplay * display)
649 {
650   GdkDisplayX11 *display_x11;
651   
652   g_return_if_fail (GDK_IS_DISPLAY (display));
653   
654   display_x11 = GDK_DISPLAY_X11 (display);;
655   g_return_if_fail (display_x11->grab_count > 0);
656   
657   display_x11->grab_count--;
658   if (display_x11->grab_count == 0)
659     {
660       XUngrabServer (display_x11->xdisplay);
661       XFlush (display_x11->xdisplay);
662     }
663 }
664
665 static void
666 gdk_display_x11_dispose (GObject *object)
667 {
668   GdkDisplayX11 *display_x11;
669   gint i;
670   
671   display_x11 = GDK_DISPLAY_X11 (object);
672   
673   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
674     _gdk_screen_close (display_x11->screens[i]);
675
676   g_source_destroy (display_x11->event_source);
677
678   XCloseDisplay (display_x11->xdisplay);
679   display_x11->xdisplay = NULL;
680
681   G_OBJECT_CLASS (parent_class)->dispose (object);
682 }
683
684 static void
685 gdk_display_x11_finalize (GObject *object)
686 {
687   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (object);
688   int i;
689   GList *tmp;
690   /* FIXME need to write GdkKeymap finalize fct 
691      g_object_unref (display_x11->keymap);
692    */
693   /* Free motif Dnd */
694   if (display_x11->motif_target_lists)
695     {
696       for (i = 0; i < display_x11->motif_n_target_lists; i++)
697         g_list_free (display_x11->motif_target_lists[i]);
698       g_free (display_x11->motif_target_lists);
699     }
700
701   /* Atom Hashtable */
702   g_hash_table_destroy (display_x11->atom_from_virtual);
703   g_hash_table_destroy (display_x11->atom_to_virtual);
704   /* Leader Window */
705   XDestroyWindow (display_x11->xdisplay, display_x11->leader_window);
706   /* list of filters for client messages */
707   g_list_free (display_x11->client_filters);
708   /* List of event window extraction functions */
709   g_slist_foreach (display_x11->event_types, (GFunc)g_free, NULL);
710   g_slist_free (display_x11->event_types);
711   /* X ID hashtable */
712   g_hash_table_destroy (display_x11->xid_ht);
713   /* input GdkDevice list */
714   /* FIXME need to write finalize fct */
715   for (tmp = display_x11->input_devices; tmp; tmp = tmp->next)
716     g_object_unref (tmp->data);
717   g_list_free (display_x11->input_devices);
718   /* input GdkWindow list */
719   for (tmp = display_x11->input_windows; tmp; tmp = tmp->next)
720     g_object_unref (tmp->data);
721   g_list_free (display_x11->input_windows);
722   /* Free all GdkScreens */
723   for (i = 0; i < ScreenCount (display_x11->xdisplay); i++)
724     g_object_unref (display_x11->screens[i]);
725   g_free (display_x11->screens);
726   g_free (display_x11->startup_notification_id);
727   
728   G_OBJECT_CLASS (parent_class)->finalize (object);
729 }
730
731 /**
732  * gdk_x11_lookup_xdisplay:
733  * @xdisplay: a pointer to an X Display
734  * 
735  * Find the #GdkDisplay corresponding to @display, if any exists.
736  * 
737  * Return value: the #GdkDisplay, if found, otherwise %NULL.
738  *
739  * Since: 2.2
740  **/
741 GdkDisplay *
742 gdk_x11_lookup_xdisplay (Display *xdisplay)
743 {
744   GSList *tmp_list;
745
746   for (tmp_list = _gdk_displays; tmp_list; tmp_list = tmp_list->next)
747     {
748       if (GDK_DISPLAY_XDISPLAY (tmp_list->data) == xdisplay)
749         return tmp_list->data;
750     }
751   
752   return NULL;
753 }
754
755 /**
756  * _gdk_x11_display_screen_for_xrootwin:
757  * @display: a #Display
758  * @xrootwin: window ID for one of of the screen's of the display.
759  * 
760  * Given the root window ID of one of the screen's of a #GdkDisplay,
761  * finds the screen.
762  * 
763  * Return value: the #GdkScreen corresponding to @xrootwin, or %NULL.
764  **/
765 GdkScreen *
766 _gdk_x11_display_screen_for_xrootwin (GdkDisplay *display,
767                                       Window      xrootwin)
768 {
769   gint n_screens, i;
770
771   n_screens = gdk_display_get_n_screens (display);
772   for (i = 0; i < n_screens; i++)
773     {
774       GdkScreen *screen = gdk_display_get_screen (display, i);
775       if (GDK_SCREEN_XROOTWIN (screen) == xrootwin)
776         return screen;
777     }
778
779   return NULL;
780 }
781
782 /**
783  * gdk_x11_display_get_xdisplay:
784  * @display: a #GdkDisplay
785  * @returns: an X display.
786  *
787  * Returns the X display of a #GdkDisplay.
788  *
789  * Since: 2.2
790  */
791 Display *
792 gdk_x11_display_get_xdisplay (GdkDisplay  *display)
793 {
794   return GDK_DISPLAY_X11 (display)->xdisplay;
795 }
796
797 void
798 _gdk_windowing_set_default_display (GdkDisplay *display)
799 {
800   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
801   const gchar *startup_id;
802   
803   if (display)
804     gdk_display = GDK_DISPLAY_XDISPLAY (display);
805   else
806     gdk_display = NULL;
807
808   g_free (display_x11->startup_notification_id);
809   display_x11->startup_notification_id = NULL;
810   
811   startup_id = g_getenv ("DESKTOP_STARTUP_ID");
812   if (startup_id && *startup_id != '\0')
813     {
814       if (!g_utf8_validate (startup_id, -1, NULL))
815         g_warning ("DESKTOP_STARTUP_ID contains invalid UTF-8");
816       else
817         display_x11->startup_notification_id = g_strdup (startup_id);
818       
819       /* Clear the environment variable so it won't be inherited by
820        * child processes and confuse things.  
821        */
822       g_unsetenv ("DESKTOP_STARTUP_ID");
823
824       /* Set the startup id on the leader window so it
825        * applies to all windows we create on this display
826        */
827       XChangeProperty (display_x11->xdisplay,
828                        display_x11->leader_window,
829                        gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
830                        gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
831                        PropModeReplace,
832                        startup_id, strlen (startup_id));
833     }
834 }
835
836 static char*
837 escape_for_xmessage (const char *str)
838 {
839   GString *retval;
840   const char *p;
841   
842   retval = g_string_new (NULL);
843
844   p = str;
845   while (*p)
846     {
847       switch (*p)
848         {
849         case ' ':
850         case '"':
851         case '\\':
852           g_string_append_c (retval, '\\');
853           break;
854         }
855
856       g_string_append_c (retval, *p);
857       ++p;
858     }
859
860   return g_string_free (retval, FALSE);
861 }
862
863 static void
864 broadcast_xmessage   (GdkDisplay   *display,
865                       const char   *message_type,
866                       const char   *message_type_begin,
867                       const char   *message)
868 {
869   Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
870   GdkScreen *screen = gdk_display_get_default_screen (display);
871   GdkWindow *root_window = gdk_screen_get_root_window (screen);
872   Window xroot_window = GDK_WINDOW_XID (root_window);
873   
874   Atom type_atom;
875   Atom type_atom_begin;
876   Window xwindow;
877
878   {
879     XSetWindowAttributes attrs;
880
881     attrs.override_redirect = True;
882     attrs.event_mask = PropertyChangeMask | StructureNotifyMask;
883
884     xwindow =
885       XCreateWindow (xdisplay,
886                      xroot_window,
887                      -100, -100, 1, 1,
888                      0,
889                      CopyFromParent,
890                      CopyFromParent,
891                      CopyFromParent,
892                      CWOverrideRedirect | CWEventMask,
893                      &attrs);
894   }
895
896   type_atom = gdk_x11_get_xatom_by_name_for_display (display,
897                                                      message_type);
898   type_atom_begin = gdk_x11_get_xatom_by_name_for_display (display,
899                                                            message_type_begin);
900   
901   {
902     XEvent xevent;
903     const char *src;
904     const char *src_end;
905     char *dest;
906     char *dest_end;
907     
908     xevent.xclient.type = ClientMessage;
909     xevent.xclient.message_type = type_atom_begin;
910     xevent.xclient.display =xdisplay;
911     xevent.xclient.window = xwindow;
912     xevent.xclient.format = 8;
913
914     src = message;
915     src_end = message + strlen (message) + 1; /* +1 to include nul byte */
916     
917     while (src != src_end)
918       {
919         dest = &xevent.xclient.data.b[0];
920         dest_end = dest + 20;        
921         
922         while (dest != dest_end &&
923                src != src_end)
924           {
925             *dest = *src;
926             ++dest;
927             ++src;
928           }
929
930         while (dest != dest_end)
931           {
932             *dest = 0;
933             ++dest;
934           }
935         
936         XSendEvent (xdisplay,
937                     xroot_window,
938                     False,
939                     PropertyChangeMask,
940                     &xevent);
941
942         xevent.xclient.message_type = type_atom;
943       }
944   }
945
946   XDestroyWindow (xdisplay, xwindow);
947   XFlush (xdisplay);
948 }
949
950 /**
951  * gdk_notify_startup_complete:
952  * 
953  * Indicates to the GUI environment that the application has finished
954  * loading. If the applications opens windows, this function is
955  * normally called after opening the application's initial set of
956  * windows.
957  * 
958  * GTK+ will call this function automatically after opening the first
959  * #GtkWindow unless gtk_window_set_auto_startup_notification() is called 
960  * to disable that feature.
961  *
962  * Since: 2.2
963  **/
964 void
965 gdk_notify_startup_complete (void)
966 {
967   GdkDisplay *display;
968   GdkDisplayX11 *display_x11;
969   gchar *escaped_id;
970   gchar *message;
971
972   display = gdk_display_get_default ();
973   if (!display)
974     return;
975   
976   display_x11 = GDK_DISPLAY_X11 (display);
977
978   if (display_x11->startup_notification_id == NULL)
979     return;
980
981   escaped_id = escape_for_xmessage (display_x11->startup_notification_id);
982   message = g_strdup_printf ("remove: ID=%s", escaped_id);
983   g_free (escaped_id);
984
985   broadcast_xmessage (display,
986                       "_NET_STARTUP_INFO",
987                       "_NET_STARTUP_INFO_BEGIN",
988                       message);
989
990   g_free (message);
991 }
992
993
994 /**
995  * gdk_display_supports_selection_notification:
996  * @display: a #GdkDisplay
997  * 
998  * Returns whether #GdkEventOwnerChange events will be 
999  * sent when the owner of a selection changes.
1000  * 
1001  * Return value: whether #GdkEventOwnerChange events will 
1002  *               be sent.
1003  *
1004  * Since: 2.6
1005  **/
1006 gboolean 
1007 gdk_display_supports_selection_notification (GdkDisplay *display)
1008 {
1009   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1010
1011   return display_x11->have_xfixes;
1012 }
1013
1014 /**
1015  * gdk_display_request_selection_notification:
1016  * @display: a #GdkDisplay
1017  * @selection: the #GdkAtom naming the selection for which
1018  *             ownership change notification is requested
1019  * 
1020  * Request #GdkEventOwnerChange events for ownership changes
1021  * of the selection named by the given atom.
1022  * 
1023  * Return value: whether #GdkEventOwnerChange events will 
1024  *               be sent.
1025  *
1026  * Since: 2.6
1027  **/
1028 gboolean gdk_display_request_selection_notification  (GdkDisplay *display,
1029                                                       GdkAtom     selection)
1030
1031 {
1032 #ifdef HAVE_XFIXES
1033   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1034   Atom atom;
1035
1036   if (display_x11->have_xfixes)
1037     {
1038       atom = gdk_x11_atom_to_xatom_for_display (display, 
1039                                                 selection);
1040       XFixesSelectSelectionInput (display_x11->xdisplay, 
1041                                   display_x11->leader_window,
1042                                   atom,
1043                                   XFixesSetSelectionOwnerNotifyMask |
1044                                   XFixesSelectionWindowDestroyNotifyMask |
1045                                   XFixesSelectionClientCloseNotifyMask);
1046       return TRUE;
1047     }
1048   else
1049 #endif
1050     return FALSE;
1051 }