4 * Copyright 2001 Sun Microsystems Inc.
6 * Erwann Chenede <erwann.chenede@sun.com>
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.
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.
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.
30 #include "gdkscreen.h"
31 #include "gdkscreen-x11.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
37 #include <X11/Xatom.h>
39 #ifdef HAVE_SOLARIS_XINERAMA
40 #include <X11/extensions/xinerama.h>
42 #ifdef HAVE_XFREE_XINERAMA
43 #include <X11/extensions/Xinerama.h>
47 #include <X11/extensions/Xrandr.h>
51 #include <X11/extensions/Xfixes.h>
54 #include "gdksettings.c"
56 static void gdk_screen_x11_dispose (GObject *object);
57 static void gdk_screen_x11_finalize (GObject *object);
58 static void init_randr_support (GdkScreen *screen);
59 static void deinit_multihead (GdkScreen *screen);
63 WINDOW_MANAGER_CHANGED,
67 static guint signals[LAST_SIGNAL] = { 0 };
69 G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
71 typedef struct _NetWmSupportedAtoms NetWmSupportedAtoms;
73 struct _NetWmSupportedAtoms
81 GdkRectangle geometry;
90 _gdk_screen_x11_class_init (GdkScreenX11Class *klass)
92 GObjectClass *object_class = G_OBJECT_CLASS (klass);
94 object_class->dispose = gdk_screen_x11_dispose;
95 object_class->finalize = gdk_screen_x11_finalize;
97 signals[WINDOW_MANAGER_CHANGED] =
98 g_signal_new (g_intern_static_string ("window_manager_changed"),
99 G_OBJECT_CLASS_TYPE (object_class),
101 G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
103 g_cclosure_marshal_VOID__VOID,
109 _gdk_screen_x11_init (GdkScreenX11 *screen)
114 * gdk_screen_get_display:
115 * @screen: a #GdkScreen
117 * Gets the display to which the @screen belongs.
119 * Returns: the display to which @screen belongs
124 gdk_screen_get_display (GdkScreen *screen)
126 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
128 return GDK_SCREEN_X11 (screen)->display;
131 * gdk_screen_get_width:
132 * @screen: a #GdkScreen
134 * Gets the width of @screen in pixels
136 * Returns: the width of @screen in pixels.
141 gdk_screen_get_width (GdkScreen *screen)
143 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
145 return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
149 * gdk_screen_get_height:
150 * @screen: a #GdkScreen
152 * Gets the height of @screen in pixels
154 * Returns: the height of @screen in pixels.
159 gdk_screen_get_height (GdkScreen *screen)
161 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
163 return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
167 * gdk_screen_get_width_mm:
168 * @screen: a #GdkScreen
170 * Gets the width of @screen in millimeters.
171 * Note that on some X servers this value will not be correct.
173 * Returns: the width of @screen in millimeters.
178 gdk_screen_get_width_mm (GdkScreen *screen)
180 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
182 return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
186 * gdk_screen_get_height_mm:
187 * @screen: a #GdkScreen
189 * Returns the height of @screen in millimeters.
190 * Note that on some X servers this value will not be correct.
192 * Returns: the heigth of @screen in millimeters.
197 gdk_screen_get_height_mm (GdkScreen *screen)
199 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
201 return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
205 * gdk_screen_get_number:
206 * @screen: a #GdkScreen
208 * Gets the index of @screen among the screens in the display
209 * to which it belongs. (See gdk_screen_get_display())
216 gdk_screen_get_number (GdkScreen *screen)
218 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
220 return GDK_SCREEN_X11 (screen)->screen_num;
224 * gdk_screen_get_root_window:
225 * @screen: a #GdkScreen
227 * Gets the root window of @screen.
229 * Returns: (transfer none): the root window
234 gdk_screen_get_root_window (GdkScreen *screen)
236 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
238 return GDK_SCREEN_X11 (screen)->root_window;
242 * gdk_screen_get_default_colormap:
243 * @screen: a #GdkScreen
245 * Gets the default colormap for @screen.
247 * Returns: (transfer none): the default #GdkColormap.
252 gdk_screen_get_default_colormap (GdkScreen *screen)
254 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
256 return GDK_SCREEN_X11 (screen)->default_colormap;
260 * gdk_screen_set_default_colormap:
261 * @screen: a #GdkScreen
262 * @colormap: a #GdkColormap
264 * Sets the default @colormap for @screen.
269 gdk_screen_set_default_colormap (GdkScreen *screen,
270 GdkColormap *colormap)
272 GdkColormap *old_colormap;
274 g_return_if_fail (GDK_IS_SCREEN (screen));
275 g_return_if_fail (GDK_IS_COLORMAP (colormap));
277 old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
279 GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
282 g_object_unref (old_colormap);
286 _gdk_screen_x11_events_uninit (GdkScreen *screen)
288 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
290 if (screen_x11->xsettings_client)
292 xsettings_client_destroy (screen_x11->xsettings_client);
293 screen_x11->xsettings_client = NULL;
298 gdk_screen_x11_dispose (GObject *object)
300 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
302 _gdk_screen_x11_events_uninit (GDK_SCREEN (object));
304 if (screen_x11->default_colormap)
306 g_object_unref (screen_x11->default_colormap);
307 screen_x11->default_colormap = NULL;
310 if (screen_x11->system_colormap)
312 g_object_unref (screen_x11->system_colormap);
313 screen_x11->system_colormap = NULL;
316 if (screen_x11->rgba_colormap)
318 g_object_unref (screen_x11->rgba_colormap);
319 screen_x11->rgba_colormap = NULL;
322 if (screen_x11->root_window)
323 _gdk_window_destroy (screen_x11->root_window, TRUE);
325 G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->dispose (object);
327 screen_x11->xdisplay = NULL;
328 screen_x11->xscreen = NULL;
329 screen_x11->screen_num = -1;
330 screen_x11->xroot_window = None;
331 screen_x11->wmspec_check_window = None;
335 gdk_screen_x11_finalize (GObject *object)
337 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
340 if (screen_x11->root_window)
341 g_object_unref (screen_x11->root_window);
343 if (screen_x11->renderer)
344 g_object_unref (screen_x11->renderer);
347 for (i = 0; i < screen_x11->nvisuals; i++)
348 g_object_unref (screen_x11->visuals[i]);
349 g_free (screen_x11->visuals);
350 g_hash_table_destroy (screen_x11->visual_hash);
352 g_free (screen_x11->window_manager_name);
354 g_hash_table_destroy (screen_x11->colormap_hash);
356 deinit_multihead (GDK_SCREEN (object));
358 G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->finalize (object);
362 * gdk_screen_get_n_monitors:
363 * @screen: a #GdkScreen
365 * Returns the number of monitors which @screen consists of.
367 * Returns: number of monitors which @screen consists of
372 gdk_screen_get_n_monitors (GdkScreen *screen)
374 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
376 return GDK_SCREEN_X11 (screen)->n_monitors;
380 * gdk_screen_get_primary_monitor:
381 * @screen: a #GdkScreen.
383 * Gets the primary monitor for @screen. The primary monitor
384 * is considered the monitor where the 'main desktop' lives.
385 * While normal application windows typically allow the window
386 * manager to place the windows, specialized desktop applications
387 * such as panels should place themselves on the primary monitor.
389 * If no primary monitor is configured by the user, the return value
390 * will be 0, defaulting to the first monitor.
392 * Returns: An integer index for the primary monitor, or 0 if none is configured.
397 gdk_screen_get_primary_monitor (GdkScreen *screen)
399 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
401 return GDK_SCREEN_X11 (screen)->primary_monitor;
405 * gdk_screen_get_monitor_width_mm:
406 * @screen: a #GdkScreen
407 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
409 * Gets the width in millimeters of the specified monitor, if available.
411 * Returns: the width of the monitor, or -1 if not available
416 gdk_screen_get_monitor_width_mm (GdkScreen *screen,
419 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
421 g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
422 g_return_val_if_fail (monitor_num >= 0, -1);
423 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
425 return screen_x11->monitors[monitor_num].width_mm;
429 * gdk_screen_get_monitor_height_mm:
430 * @screen: a #GdkScreen
431 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
433 * Gets the height in millimeters of the specified monitor.
435 * Returns: the height of the monitor, or -1 if not available
440 gdk_screen_get_monitor_height_mm (GdkScreen *screen,
443 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
445 g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
446 g_return_val_if_fail (monitor_num >= 0, -1);
447 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
449 return screen_x11->monitors[monitor_num].height_mm;
453 * gdk_screen_get_monitor_plug_name:
454 * @screen: a #GdkScreen
455 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
457 * Returns the output name of the specified monitor.
458 * Usually something like VGA, DVI, or TV, not the actual
459 * product name of the display device.
461 * Returns: a newly-allocated string containing the name of the monitor,
462 * or %NULL if the name cannot be determined
467 gdk_screen_get_monitor_plug_name (GdkScreen *screen,
470 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
472 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
473 g_return_val_if_fail (monitor_num >= 0, NULL);
474 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, NULL);
476 return g_strdup (screen_x11->monitors[monitor_num].output_name);
480 * gdk_x11_screen_get_monitor_output:
481 * @screen: a #GdkScreen
482 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
484 * Gets the XID of the specified output/monitor.
485 * If the X server does not support version 1.2 of the RANDR
486 * extension, 0 is returned.
488 * Returns: the XID of the monitor
493 gdk_x11_screen_get_monitor_output (GdkScreen *screen,
496 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
498 g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
499 g_return_val_if_fail (monitor_num >= 0, None);
500 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, None);
502 return screen_x11->monitors[monitor_num].output;
506 * gdk_screen_get_monitor_geometry:
507 * @screen : a #GdkScreen
508 * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
509 * @dest : a #GdkRectangle to be filled with the monitor geometry
511 * Retrieves the #GdkRectangle representing the size and position of
512 * the individual monitor within the entire screen area.
514 * Note that the size of the entire screen area can be retrieved via
515 * gdk_screen_get_width() and gdk_screen_get_height().
520 gdk_screen_get_monitor_geometry (GdkScreen *screen,
524 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
526 g_return_if_fail (GDK_IS_SCREEN (screen));
527 g_return_if_fail (monitor_num >= 0);
528 g_return_if_fail (monitor_num < screen_x11->n_monitors);
531 *dest = screen_x11->monitors[monitor_num].geometry;
535 * gdk_screen_get_rgba_colormap:
536 * @screen: a #GdkScreen.
538 * Gets a colormap to use for creating windows or pixmaps with an
539 * alpha channel. The windowing system on which GTK+ is running
540 * may not support this capability, in which case %NULL will
541 * be returned. Even if a non-%NULL value is returned, its
542 * possible that the window's alpha channel won't be honored
543 * when displaying the window on the screen: in particular, for
544 * X an appropriate windowing manager and compositing manager
545 * must be running to provide appropriate display.
547 * This functionality is not implemented in the Windows backend.
549 * For setting an overall opacity for a top-level window, see
550 * gdk_window_set_opacity().
552 * Return value: (transfer none): a colormap to use for windows with
553 * an alpha channel or %NULL if the capability is not available.
558 gdk_screen_get_rgba_colormap (GdkScreen *screen)
560 GdkScreenX11 *screen_x11;
562 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
564 screen_x11 = GDK_SCREEN_X11 (screen);
566 if (!screen_x11->rgba_visual)
569 if (!screen_x11->rgba_colormap)
570 screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
573 return screen_x11->rgba_colormap;
577 * gdk_screen_get_rgba_visual:
578 * @screen: a #GdkScreen
580 * Gets a visual to use for creating windows or pixmaps with an
581 * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
584 * Return value: (transfer none): a visual to use for windows with an
585 * alpha channel or %NULL if the capability is not available.
590 gdk_screen_get_rgba_visual (GdkScreen *screen)
592 GdkScreenX11 *screen_x11;
594 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
596 screen_x11 = GDK_SCREEN_X11 (screen);
598 return screen_x11->rgba_visual;
602 * gdk_x11_screen_get_xscreen:
603 * @screen: a #GdkScreen.
604 * @returns: (transfer none): an Xlib <type>Screen*</type>
606 * Returns the screen of a #GdkScreen.
611 gdk_x11_screen_get_xscreen (GdkScreen *screen)
613 return GDK_SCREEN_X11 (screen)->xscreen;
617 * gdk_x11_screen_get_screen_number:
618 * @screen: a #GdkScreen.
619 * @returns: the position of @screen among the screens of
622 * Returns the index of a #GdkScreen.
627 gdk_x11_screen_get_screen_number (GdkScreen *screen)
629 return GDK_SCREEN_X11 (screen)->screen_num;
633 check_is_composited (GdkDisplay *display,
634 GdkScreenX11 *screen_x11)
636 Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom);
639 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection);
641 return xwindow != None;
645 make_cm_atom (int screen_number)
647 gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number);
648 GdkAtom atom = gdk_atom_intern (name, FALSE);
654 init_monitor_geometry (GdkX11Monitor *monitor,
655 int x, int y, int width, int height)
657 monitor->geometry.x = x;
658 monitor->geometry.y = y;
659 monitor->geometry.width = width;
660 monitor->geometry.height = height;
662 monitor->output = None;
663 monitor->width_mm = -1;
664 monitor->height_mm = -1;
665 monitor->output_name = NULL;
666 monitor->manufacturer = NULL;
670 init_fake_xinerama (GdkScreen *screen)
672 #ifdef G_ENABLE_DEBUG
673 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
674 XSetWindowAttributes atts;
678 if (!(_gdk_debug_flags & GDK_DEBUG_XINERAMA))
681 /* Fake Xinerama mode by splitting the screen into 4 monitors.
682 * Also draw a little cross to make the monitor boundaries visible.
684 w = WidthOfScreen (screen_x11->xscreen);
685 h = HeightOfScreen (screen_x11->xscreen);
687 screen_x11->n_monitors = 4;
688 screen_x11->monitors = g_new0 (GdkX11Monitor, 4);
689 init_monitor_geometry (&screen_x11->monitors[0], 0, 0, w / 2, h / 2);
690 init_monitor_geometry (&screen_x11->monitors[1], w / 2, 0, w / 2, h / 2);
691 init_monitor_geometry (&screen_x11->monitors[2], 0, h / 2, w / 2, h / 2);
692 init_monitor_geometry (&screen_x11->monitors[3], w / 2, h / 2, w / 2, h / 2);
694 atts.override_redirect = 1;
695 atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen),
696 screen_x11->screen_num);
697 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
698 screen_x11->xroot_window, 0, h / 2, w, 1, 0,
699 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
700 screen_x11->screen_num),
702 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
703 screen_x11->screen_num),
704 CWOverrideRedirect|CWBackPixel,
706 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
707 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
708 screen_x11->xroot_window, w/2 , 0, 1, h, 0,
709 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
710 screen_x11->screen_num),
712 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
713 screen_x11->screen_num),
714 CWOverrideRedirect|CWBackPixel,
716 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
724 free_monitors (GdkX11Monitor *monitors,
729 for (i = 0; i < n_monitors; ++i)
731 g_free (monitors[i].output_name);
732 g_free (monitors[i].manufacturer);
740 monitor_compare_function (GdkX11Monitor *monitor1,
741 GdkX11Monitor *monitor2)
743 /* Sort the leftmost/topmost monitors first.
744 * For "cloned" monitors, sort the bigger ones first
745 * (giving preference to taller monitors over wider
749 if (monitor1->geometry.x != monitor2->geometry.x)
750 return monitor1->geometry.x - monitor2->geometry.x;
752 if (monitor1->geometry.y != monitor2->geometry.y)
753 return monitor1->geometry.y - monitor2->geometry.y;
755 if (monitor1->geometry.height != monitor2->geometry.height)
756 return - (monitor1->geometry.height - monitor2->geometry.height);
758 if (monitor1->geometry.width != monitor2->geometry.width)
759 return - (monitor1->geometry.width - monitor2->geometry.width);
766 init_randr13 (GdkScreen *screen)
769 GdkDisplay *display = gdk_screen_get_display (screen);
770 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
771 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
772 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
773 XRRScreenResources *resources;
774 RROutput primary_output;
775 RROutput first_output = None;
778 gboolean randr12_compat = FALSE;
780 if (!display_x11->have_randr13)
783 resources = XRRGetScreenResourcesCurrent (screen_x11->xdisplay,
784 screen_x11->xroot_window);
788 monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
791 for (i = 0; i < resources->noutput; ++i)
793 XRROutputInfo *output =
794 XRRGetOutputInfo (dpy, resources, resources->outputs[i]);
796 /* Non RandR1.2 X driver have output name "default" */
797 randr12_compat |= !g_strcmp0 (output->name, "default");
799 if (output->connection == RR_Disconnected)
801 XRRFreeOutputInfo (output);
807 GdkX11Monitor monitor;
808 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);
810 monitor.geometry.x = crtc->x;
811 monitor.geometry.y = crtc->y;
812 monitor.geometry.width = crtc->width;
813 monitor.geometry.height = crtc->height;
815 monitor.output = resources->outputs[i];
816 monitor.width_mm = output->mm_width;
817 monitor.height_mm = output->mm_height;
818 monitor.output_name = g_strdup (output->name);
819 /* FIXME: need EDID parser */
820 monitor.manufacturer = NULL;
822 g_array_append_val (monitors, monitor);
824 XRRFreeCrtcInfo (crtc);
827 XRRFreeOutputInfo (output);
830 if (resources->noutput > 0)
831 first_output = resources->outputs[0];
833 XRRFreeScreenResources (resources);
835 /* non RandR 1.2 X driver doesn't return any usable multihead data */
838 guint n_monitors = monitors->len;
840 free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
846 g_array_sort (monitors,
847 (GCompareFunc) monitor_compare_function);
848 screen_x11->n_monitors = monitors->len;
849 screen_x11->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
851 screen_x11->primary_monitor = 0;
853 primary_output = XRRGetOutputPrimary (screen_x11->xdisplay,
854 screen_x11->xroot_window);
856 for (i = 0; i < screen_x11->n_monitors; ++i)
858 if (screen_x11->monitors[i].output == primary_output)
860 screen_x11->primary_monitor = i;
864 /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
865 if (primary_output == None &&
866 g_ascii_strncasecmp (screen_x11->monitors[i].output_name, "LVDS", 4) == 0)
868 screen_x11->primary_monitor = i;
872 /* No primary specified and no LVDS found */
873 if (screen_x11->monitors[i].output == first_output)
874 screen_x11->primary_monitor = i;
877 return screen_x11->n_monitors > 0;
884 init_solaris_xinerama (GdkScreen *screen)
886 #ifdef HAVE_SOLARIS_XINERAMA
887 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
888 int screen_no = gdk_screen_get_number (screen);
889 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
890 XRectangle monitors[MAXFRAMEBUFFERS];
891 unsigned char hints[16];
896 if (!XineramaGetState (dpy, screen_no))
899 result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);
901 /* Yes I know it should be Success but the current implementation
902 * returns the num of monitor
909 screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
910 screen_x11->n_monitors = n_monitors;
912 for (i = 0; i < n_monitors; i++)
914 init_monitor_geometry (&screen_x11->monitors[i],
915 monitors[i].x, monitors[i].y,
916 monitors[i].width, monitors[i].height);
919 screen_x11->primary_monitor = 0;
922 #endif /* HAVE_SOLARIS_XINERAMA */
928 init_xfree_xinerama (GdkScreen *screen)
930 #ifdef HAVE_XFREE_XINERAMA
931 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
932 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
933 XineramaScreenInfo *monitors;
936 if (!XineramaIsActive (dpy))
939 monitors = XineramaQueryScreens (dpy, &n_monitors);
941 if (n_monitors <= 0 || monitors == NULL)
943 /* If Xinerama doesn't think we have any monitors, try acting as
944 * though we had no Xinerama. If the "no monitors" condition
945 * is because XRandR 1.2 is currently switching between CRTCs,
946 * we'll be notified again when we have our monitor back,
947 * and can go back into Xinerama-ish mode at that point.
955 screen_x11->n_monitors = n_monitors;
956 screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
958 for (i = 0; i < n_monitors; ++i)
960 init_monitor_geometry (&screen_x11->monitors[i],
961 monitors[i].x_org, monitors[i].y_org,
962 monitors[i].width, monitors[i].height);
967 screen_x11->primary_monitor = 0;
970 #endif /* HAVE_XFREE_XINERAMA */
976 deinit_multihead (GdkScreen *screen)
978 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
980 free_monitors (screen_x11->monitors, screen_x11->n_monitors);
982 screen_x11->n_monitors = 0;
983 screen_x11->monitors = NULL;
987 compare_monitor (GdkX11Monitor *m1,
990 if (m1->geometry.x != m2->geometry.x ||
991 m1->geometry.y != m2->geometry.y ||
992 m1->geometry.width != m2->geometry.width ||
993 m1->geometry.height != m2->geometry.height)
996 if (m1->width_mm != m2->width_mm ||
997 m1->height_mm != m2->height_mm)
1000 if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
1003 if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
1010 compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
1011 GdkX11Monitor *monitors2, gint n_monitors2)
1015 if (n_monitors1 != n_monitors2)
1018 for (i = 0; i < n_monitors1; i++)
1020 if (!compare_monitor (monitors1 + i, monitors2 + i))
1028 init_multihead (GdkScreen *screen)
1030 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1031 int opcode, firstevent, firsterror;
1033 /* There are four different implementations of multihead support:
1035 * 1. Fake Xinerama for debugging purposes
1037 * 3. Solaris Xinerama
1038 * 4. XFree86/Xorg Xinerama
1040 * We use them in that order.
1042 if (init_fake_xinerama (screen))
1045 if (init_randr13 (screen))
1048 if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
1049 &opcode, &firstevent, &firsterror))
1051 if (init_solaris_xinerama (screen))
1054 if (init_xfree_xinerama (screen))
1058 /* No multihead support of any kind for this screen */
1059 screen_x11->n_monitors = 1;
1060 screen_x11->monitors = g_new0 (GdkX11Monitor, 1);
1061 screen_x11->primary_monitor = 0;
1063 init_monitor_geometry (screen_x11->monitors, 0, 0,
1064 WidthOfScreen (screen_x11->xscreen),
1065 HeightOfScreen (screen_x11->xscreen));
1069 _gdk_x11_screen_new (GdkDisplay *display,
1073 GdkScreenX11 *screen_x11;
1074 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1076 screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
1078 screen_x11 = GDK_SCREEN_X11 (screen);
1079 screen_x11->display = display;
1080 screen_x11->xdisplay = display_x11->xdisplay;
1081 screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
1082 screen_x11->screen_num = screen_number;
1083 screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
1084 screen_x11->wmspec_check_window = None;
1085 /* we want this to be always non-null */
1086 screen_x11->window_manager_name = g_strdup ("unknown");
1088 init_multihead (screen);
1089 init_randr_support (screen);
1091 _gdk_visual_init (screen);
1092 _gdk_windowing_window_init (screen);
1098 * It is important that we first request the selection
1099 * notification, and then setup the initial state of
1100 * is_composited to avoid a race condition here.
1103 _gdk_x11_screen_setup (GdkScreen *screen)
1105 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1107 screen_x11->cm_selection_atom = make_cm_atom (screen_x11->screen_num);
1108 gdk_display_request_selection_notification (screen_x11->display,
1109 screen_x11->cm_selection_atom);
1110 screen_x11->is_composited = check_is_composited (screen_x11->display, screen_x11);
1114 * gdk_screen_is_composited:
1115 * @screen: a #GdkScreen
1117 * Returns whether windows with an RGBA visual can reasonably
1118 * be expected to have their alpha channel drawn correctly on
1121 * On X11 this function returns whether a compositing manager is
1122 * compositing @screen.
1124 * Return value: Whether windows with RGBA visuals can reasonably be
1125 * expected to have their alpha channels drawn correctly on the screen.
1130 gdk_screen_is_composited (GdkScreen *screen)
1132 GdkScreenX11 *screen_x11;
1134 g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1136 screen_x11 = GDK_SCREEN_X11 (screen);
1138 return screen_x11->is_composited;
1142 init_randr_support (GdkScreen * screen)
1144 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1146 XSelectInput (GDK_SCREEN_XDISPLAY (screen),
1147 screen_x11->xroot_window,
1148 StructureNotifyMask);
1151 XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
1152 screen_x11->xroot_window,
1153 RRScreenChangeNotifyMask |
1154 RRCrtcChangeNotifyMask |
1155 RROutputPropertyNotifyMask);
1160 process_monitors_change (GdkScreen *screen)
1162 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1164 GdkX11Monitor *monitors;
1167 n_monitors = screen_x11->n_monitors;
1168 monitors = screen_x11->monitors;
1170 screen_x11->n_monitors = 0;
1171 screen_x11->monitors = NULL;
1173 init_multihead (screen);
1175 changed = !compare_monitors (monitors, n_monitors,
1176 screen_x11->monitors, screen_x11->n_monitors);
1178 free_monitors (monitors, n_monitors);
1181 g_signal_emit_by_name (screen, "monitors-changed");
1185 _gdk_x11_screen_size_changed (GdkScreen *screen,
1190 GdkDisplayX11 *display_x11;
1193 width = gdk_screen_get_width (screen);
1194 height = gdk_screen_get_height (screen);
1197 display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen));
1199 if (display_x11->have_randr13 && event->type == ConfigureNotify)
1201 g_signal_emit_by_name (screen, "monitors-changed");
1205 XRRUpdateConfiguration (event);
1207 if (event->type == ConfigureNotify)
1209 XConfigureEvent *rcevent = (XConfigureEvent *) event;
1210 Screen *xscreen = gdk_x11_screen_get_xscreen (screen);
1212 xscreen->width = rcevent->width;
1213 xscreen->height = rcevent->height;
1219 process_monitors_change (screen);
1221 if (width != gdk_screen_get_width (screen) ||
1222 height != gdk_screen_get_height (screen))
1223 g_signal_emit_by_name (screen, "size-changed");
1227 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
1229 g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
1233 _gdk_x11_screen_process_owner_change (GdkScreen *screen,
1237 XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event;
1238 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1239 Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display,
1240 screen_x11->cm_selection_atom);
1242 if (selection_event->selection == xcm_selection_atom)
1244 gboolean composited = selection_event->owner != None;
1246 if (composited != screen_x11->is_composited)
1248 screen_x11->is_composited = composited;
1250 g_signal_emit_by_name (screen, "composited-changed");
1257 * _gdk_windowing_substitute_screen_number:
1258 * @display_name : The name of a display, in the form used by
1259 * gdk_display_open (). If %NULL a default value
1260 * will be used. On X11, this is derived from the DISPLAY
1261 * environment variable.
1262 * @screen_number : The number of a screen within the display
1263 * referred to by @display_name.
1265 * Modifies a @display_name to make @screen_number the default
1266 * screen when the display is opened.
1268 * Return value: a newly allocated string holding the resulting
1269 * display name. Free with g_free().
1272 _gdk_windowing_substitute_screen_number (const gchar *display_name,
1279 display_name = getenv ("DISPLAY");
1284 str = g_string_new (display_name);
1286 p = strrchr (str->str, '.');
1287 if (p && p > strchr (str->str, ':'))
1288 g_string_truncate (str, p - str->str);
1290 g_string_append_printf (str, ".%d", screen_number);
1292 return g_string_free (str, FALSE);
1296 * gdk_screen_make_display_name:
1297 * @screen: a #GdkScreen
1299 * Determines the name to pass to gdk_display_open() to get
1300 * a #GdkDisplay with this screen as the default screen.
1302 * Return value: a newly allocated string, free with g_free()
1307 gdk_screen_make_display_name (GdkScreen *screen)
1309 const gchar *old_display;
1311 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1313 old_display = gdk_display_get_name (gdk_screen_get_display (screen));
1315 return _gdk_windowing_substitute_screen_number (old_display,
1316 gdk_screen_get_number (screen));
1320 * gdk_screen_get_active_window
1321 * @screen: a #GdkScreen
1323 * Returns the screen's currently active window.
1325 * On X11, this is done by inspecting the _NET_ACTIVE_WINDOW property
1326 * on the root window, as described in the <ulink
1327 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1328 * Manager Hints</ulink>. If there is no currently currently active
1329 * window, or the window manager does not support the
1330 * _NET_ACTIVE_WINDOW hint, this function returns %NULL.
1332 * On other platforms, this function may return %NULL, depending on whether
1333 * it is implementable on that platform.
1335 * The returned window should be unrefed using g_object_unref() when
1338 * Return value: the currently active window, or %NULL.
1343 gdk_screen_get_active_window (GdkScreen *screen)
1345 GdkScreenX11 *screen_x11;
1346 GdkWindow *ret = NULL;
1349 gulong nitems_return;
1350 gulong bytes_after_return;
1351 guchar *data = NULL;
1353 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1355 if (!gdk_x11_screen_supports_net_wm_hint (screen,
1356 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1359 screen_x11 = GDK_SCREEN_X11 (screen);
1361 if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1362 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1363 "_NET_ACTIVE_WINDOW"),
1364 0, 1, False, XA_WINDOW, &type_return,
1365 &format_return, &nitems_return,
1366 &bytes_after_return, &data)
1369 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
1371 GdkNativeWindow window = *(GdkNativeWindow *) data;
1375 ret = gdk_window_foreign_new_for_display (screen_x11->display,
1376 *(GdkNativeWindow *) data);
1388 * gdk_screen_get_window_stack
1389 * @screen: a #GdkScreen
1391 * Returns a #GList of #GdkWindow<!-- -->s representing the current
1394 * On X11, this is done by inspecting the _NET_CLIENT_LIST_STACKING
1395 * property on the root window, as described in the <ulink
1396 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1397 * Manager Hints</ulink>. If the window manager does not support the
1398 * _NET_CLIENT_LIST_STACKING hint, this function returns %NULL.
1400 * On other platforms, this function may return %NULL, depending on whether
1401 * it is implementable on that platform.
1403 * The returned list is newly allocated and owns references to the
1404 * windows it contains, so it should be freed using g_list_free() and
1405 * its windows unrefed using g_object_unref() when no longer needed.
1407 * Return value: a list of #GdkWindow<!-- -->s for the current window stack,
1413 gdk_screen_get_window_stack (GdkScreen *screen)
1415 GdkScreenX11 *screen_x11;
1419 gulong nitems_return;
1420 gulong bytes_after_return;
1421 guchar *data = NULL;
1423 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1425 if (!gdk_x11_screen_supports_net_wm_hint (screen,
1426 gdk_atom_intern_static_string ("_NET_CLIENT_LIST_STACKING")))
1429 screen_x11 = GDK_SCREEN_X11 (screen);
1431 if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1432 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1433 "_NET_CLIENT_LIST_STACKING"),
1434 0, G_MAXLONG, False, XA_WINDOW, &type_return,
1435 &format_return, &nitems_return,
1436 &bytes_after_return, &data)
1439 if ((type_return == XA_WINDOW) && (format_return == 32) &&
1440 (data) && (nitems_return > 0))
1442 gulong *stack = (gulong *) data;
1446 for (i = 0; i < nitems_return; i++)
1448 win = gdk_window_foreign_new_for_display (screen_x11->display,
1449 (GdkNativeWindow)stack[i]);
1452 ret = g_list_append (ret, win);
1463 /* Sends a ClientMessage to all toplevel client windows */
1465 gdk_event_send_client_message_to_all_recurse (GdkDisplay *display,
1472 unsigned long nitems, after;
1473 unsigned char *data;
1474 Window *ret_children, ret_root, ret_parent;
1475 unsigned int ret_nchildren;
1476 gboolean send = FALSE;
1477 gboolean found = FALSE;
1478 gboolean result = FALSE;
1481 gdk_error_trap_push ();
1483 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xid,
1484 gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
1485 0, 0, False, AnyPropertyType,
1486 &type, &format, &nitems, &after, &data) != Success)
1496 /* OK, we're all set, now let's find some windows to send this to */
1497 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xid,
1498 &ret_root, &ret_parent,
1499 &ret_children, &ret_nchildren))
1502 for(i = 0; i < ret_nchildren; i++)
1503 if (gdk_event_send_client_message_to_all_recurse (display, xev, ret_children[i], level + 1))
1506 XFree (ret_children);
1509 if (send || (!found && (level == 1)))
1511 xev->xclient.window = xid;
1512 _gdk_send_xevent (display, xid, False, NoEventMask, xev);
1515 result = send || found;
1518 gdk_error_trap_pop ();
1524 * gdk_screen_broadcast_client_message:
1525 * @screen: the #GdkScreen where the event will be broadcasted.
1526 * @event: the #GdkEvent.
1528 * On X11, sends an X ClientMessage event to all toplevel windows on
1531 * Toplevel windows are determined by checking for the WM_STATE property,
1532 * as described in the Inter-Client Communication Conventions Manual (ICCCM).
1533 * If no windows are found with the WM_STATE property set, the message is
1534 * sent to all children of the root window.
1536 * On Windows, broadcasts a message registered with the name
1537 * GDK_WIN32_CLIENT_MESSAGE to all top-level windows. The amount of
1538 * data is limited to one long, i.e. four bytes.
1544 gdk_screen_broadcast_client_message (GdkScreen *screen,
1548 GdkWindow *root_window;
1550 g_return_if_fail (event != NULL);
1552 root_window = gdk_screen_get_root_window (screen);
1554 /* Set up our event to send, with the exception of its target window */
1555 sev.xclient.type = ClientMessage;
1556 sev.xclient.display = GDK_WINDOW_XDISPLAY (root_window);
1557 sev.xclient.format = event->client.data_format;
1558 memcpy(&sev.xclient.data, &event->client.data, sizeof (sev.xclient.data));
1559 sev.xclient.message_type =
1560 gdk_x11_atom_to_xatom_for_display (GDK_WINDOW_DISPLAY (root_window),
1561 event->client.message_type);
1563 gdk_event_send_client_message_to_all_recurse (gdk_screen_get_display (screen),
1565 GDK_WINDOW_XID (root_window),
1570 check_transform (const gchar *xsettings_name,
1574 if (!g_value_type_transformable (src_type, dest_type))
1576 g_warning ("Cannot transform xsetting %s of type %s to type %s\n",
1578 g_type_name (src_type),
1579 g_type_name (dest_type));
1587 * gdk_screen_get_setting:
1588 * @screen: the #GdkScreen where the setting is located
1589 * @name: the name of the setting
1590 * @value: location to store the value of the setting
1592 * Retrieves a desktop-wide setting such as double-click time
1593 * for the #GdkScreen @screen.
1595 * FIXME needs a list of valid settings here, or a link to
1598 * Returns: %TRUE if the setting existed and a value was stored
1599 * in @value, %FALSE otherwise.
1604 gdk_screen_get_setting (GdkScreen *screen,
1609 const char *xsettings_name = NULL;
1610 XSettingsResult result;
1611 XSettingsSetting *setting = NULL;
1612 GdkScreenX11 *screen_x11;
1613 gboolean success = FALSE;
1615 GValue tmp_val = { 0, };
1617 g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1619 screen_x11 = GDK_SCREEN_X11 (screen);
1621 for (i = 0; i < GDK_SETTINGS_N_ELEMENTS(); i++)
1622 if (strcmp (GDK_SETTINGS_GDK_NAME (i), name) == 0)
1624 xsettings_name = GDK_SETTINGS_X_NAME (i);
1628 if (!xsettings_name)
1631 result = xsettings_client_get_setting (screen_x11->xsettings_client,
1632 xsettings_name, &setting);
1633 if (result != XSETTINGS_SUCCESS)
1636 switch (setting->type)
1638 case XSETTINGS_TYPE_INT:
1639 if (check_transform (xsettings_name, G_TYPE_INT, G_VALUE_TYPE (value)))
1641 g_value_init (&tmp_val, G_TYPE_INT);
1642 g_value_set_int (&tmp_val, setting->data.v_int);
1643 g_value_transform (&tmp_val, value);
1648 case XSETTINGS_TYPE_STRING:
1649 if (check_transform (xsettings_name, G_TYPE_STRING, G_VALUE_TYPE (value)))
1651 g_value_init (&tmp_val, G_TYPE_STRING);
1652 g_value_set_string (&tmp_val, setting->data.v_string);
1653 g_value_transform (&tmp_val, value);
1658 case XSETTINGS_TYPE_COLOR:
1659 if (!check_transform (xsettings_name, GDK_TYPE_COLOR, G_VALUE_TYPE (value)))
1663 g_value_init (&tmp_val, GDK_TYPE_COLOR);
1666 color.red = setting->data.v_color.red;
1667 color.green = setting->data.v_color.green;
1668 color.blue = setting->data.v_color.blue;
1670 g_value_set_boxed (&tmp_val, &color);
1672 g_value_transform (&tmp_val, value);
1679 g_value_unset (&tmp_val);
1683 xsettings_setting_free (setting);
1688 return _gdk_x11_get_xft_setting (screen, name, value);
1692 cleanup_atoms(gpointer data)
1694 NetWmSupportedAtoms *supported_atoms = data;
1695 if (supported_atoms->atoms)
1696 XFree (supported_atoms->atoms);
1697 g_free (supported_atoms);
1701 fetch_net_wm_check_window (GdkScreen *screen)
1703 GdkScreenX11 *screen_x11;
1704 GdkDisplay *display;
1714 screen_x11 = GDK_SCREEN_X11 (screen);
1715 display = screen_x11->display;
1717 g_return_if_fail (GDK_DISPLAY_X11 (display)->trusted_client);
1719 g_get_current_time (&tv);
1721 if (ABS (tv.tv_sec - screen_x11->last_wmspec_check_time) < 15)
1722 return; /* we've checked recently */
1724 screen_x11->last_wmspec_check_time = tv.tv_sec;
1727 XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1728 gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTING_WM_CHECK"),
1729 0, G_MAXLONG, False, XA_WINDOW, &type, &format,
1730 &n_items, &bytes_after, &data);
1732 if (type != XA_WINDOW)
1739 xwindow = (Window *)data;
1741 if (screen_x11->wmspec_check_window == *xwindow)
1747 gdk_error_trap_push ();
1749 /* Find out if this WM goes away, so we can reset everything. */
1750 XSelectInput (screen_x11->xdisplay, *xwindow, StructureNotifyMask);
1751 gdk_display_sync (display);
1753 error = gdk_error_trap_pop ();
1756 screen_x11->wmspec_check_window = *xwindow;
1757 screen_x11->need_refetch_net_supported = TRUE;
1758 screen_x11->need_refetch_wm_name = TRUE;
1760 /* Careful, reentrancy */
1761 _gdk_x11_screen_window_manager_changed (GDK_SCREEN (screen_x11));
1763 else if (error == BadWindow)
1765 /* Leftover property, try again immediately, new wm may be starting up */
1766 screen_x11->last_wmspec_check_time = 0;
1773 * gdk_x11_screen_supports_net_wm_hint:
1774 * @screen: the relevant #GdkScreen.
1775 * @property: a property atom.
1777 * This function is specific to the X11 backend of GDK, and indicates
1778 * whether the window manager supports a certain hint from the
1779 * Extended Window Manager Hints Specification. You can find this
1781 * <ulink url="http://www.freedesktop.org">http://www.freedesktop.org</ulink>.
1783 * When using this function, keep in mind that the window manager
1784 * can change over time; so you shouldn't use this function in
1785 * a way that impacts persistent application state. A common bug
1786 * is that your application can start up before the window manager
1787 * does when the user logs in, and before the window manager starts
1788 * gdk_x11_screen_supports_net_wm_hint() will return %FALSE for every property.
1789 * You can monitor the window_manager_changed signal on #GdkScreen to detect
1790 * a window manager change.
1792 * Return value: %TRUE if the window manager supports @property
1797 gdk_x11_screen_supports_net_wm_hint (GdkScreen *screen,
1801 GdkScreenX11 *screen_x11;
1802 NetWmSupportedAtoms *supported_atoms;
1803 GdkDisplay *display;
1805 g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1807 screen_x11 = GDK_SCREEN_X11 (screen);
1808 display = screen_x11->display;
1810 if (!G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
1813 supported_atoms = g_object_get_data (G_OBJECT (screen), "gdk-net-wm-supported-atoms");
1814 if (!supported_atoms)
1816 supported_atoms = g_new0 (NetWmSupportedAtoms, 1);
1817 g_object_set_data_full (G_OBJECT (screen), "gdk-net-wm-supported-atoms", supported_atoms, cleanup_atoms);
1820 fetch_net_wm_check_window (screen);
1822 if (screen_x11->wmspec_check_window == None)
1825 if (screen_x11->need_refetch_net_supported)
1827 /* WM has changed since we last got the supported list,
1834 screen_x11->need_refetch_net_supported = FALSE;
1836 if (supported_atoms->atoms)
1837 XFree (supported_atoms->atoms);
1839 supported_atoms->atoms = NULL;
1840 supported_atoms->n_atoms = 0;
1842 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), screen_x11->xroot_window,
1843 gdk_x11_get_xatom_by_name_for_display (display, "_NET_SUPPORTED"),
1844 0, G_MAXLONG, False, XA_ATOM, &type, &format,
1845 &supported_atoms->n_atoms, &bytes_after,
1846 (guchar **)&supported_atoms->atoms);
1848 if (type != XA_ATOM)
1852 if (supported_atoms->atoms == NULL)
1856 while (i < supported_atoms->n_atoms)
1858 if (supported_atoms->atoms[i] == gdk_x11_atom_to_xatom_for_display (display, property))
1868 * gdk_net_wm_supports:
1869 * @property: a property atom.
1871 * This function is specific to the X11 backend of GDK, and indicates
1872 * whether the window manager for the default screen supports a certain
1873 * hint from the Extended Window Manager Hints Specification. See
1874 * gdk_x11_screen_supports_net_wm_hint() for complete details.
1876 * Return value: %TRUE if the window manager supports @property
1879 gdk_net_wm_supports (GdkAtom property)
1881 return gdk_x11_screen_supports_net_wm_hint (gdk_screen_get_default (), property);
1885 refcounted_grab_server (Display *xdisplay)
1887 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1889 gdk_x11_display_grab (display);
1893 refcounted_ungrab_server (Display *xdisplay)
1895 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
1897 gdk_x11_display_ungrab (display);
1900 static GdkFilterReturn
1901 gdk_xsettings_client_event_filter (GdkXEvent *xevent,
1905 GdkScreenX11 *screen = data;
1907 if (xsettings_client_process_event (screen->xsettings_client, (XEvent *)xevent))
1908 return GDK_FILTER_REMOVE;
1910 return GDK_FILTER_CONTINUE;
1914 gdk_xsettings_watch_cb (Window window,
1920 GdkScreen *screen = cb_data;
1922 gdkwin = gdk_window_lookup_for_display (gdk_screen_get_display (screen), window);
1927 g_object_ref (gdkwin);
1930 gdkwin = gdk_window_foreign_new_for_display (gdk_screen_get_display (screen), window);
1932 /* gdk_window_foreign_new_for_display() can fail and return NULL if the
1933 * window has already been destroyed.
1939 gdk_window_add_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1945 /* gdkwin should not be NULL here, since if starting the watch succeeded
1946 * we have a reference on the window. It might mean that the caller didn't
1947 * remove the watch when it got a DestroyNotify event. Or maybe the
1948 * caller ignored the return value when starting the watch failed.
1950 g_warning ("gdk_xsettings_watch_cb(): Couldn't find window to unwatch");
1954 gdk_window_remove_filter (gdkwin, gdk_xsettings_client_event_filter, screen);
1955 g_object_unref (gdkwin);
1962 gdk_xsettings_notify_cb (const char *name,
1963 XSettingsAction action,
1964 XSettingsSetting *setting,
1968 GdkScreen *screen = data;
1969 GdkScreenX11 *screen_x11 = data;
1972 if (screen_x11->xsettings_in_init)
1975 new_event.type = GDK_SETTING;
1976 new_event.setting.window = gdk_screen_get_root_window (screen);
1977 new_event.setting.send_event = FALSE;
1978 new_event.setting.name = NULL;
1980 for (i = 0; i < GDK_SETTINGS_N_ELEMENTS() ; i++)
1981 if (strcmp (GDK_SETTINGS_X_NAME (i), name) == 0)
1983 new_event.setting.name = (char*) GDK_SETTINGS_GDK_NAME (i);
1987 if (!new_event.setting.name)
1992 case XSETTINGS_ACTION_NEW:
1993 new_event.setting.action = GDK_SETTING_ACTION_NEW;
1995 case XSETTINGS_ACTION_CHANGED:
1996 new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
1998 case XSETTINGS_ACTION_DELETED:
1999 new_event.setting.action = GDK_SETTING_ACTION_DELETED;
2003 gdk_event_put (&new_event);
2007 _gdk_screen_x11_events_init (GdkScreen *screen)
2009 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
2011 /* Keep a flag to avoid extra notifies that we don't need
2013 screen_x11->xsettings_in_init = TRUE;
2014 screen_x11->xsettings_client = xsettings_client_new_with_grab_funcs (screen_x11->xdisplay,
2015 screen_x11->screen_num,
2016 gdk_xsettings_notify_cb,
2017 gdk_xsettings_watch_cb,
2019 refcounted_grab_server,
2020 refcounted_ungrab_server);
2021 screen_x11->xsettings_in_init = FALSE;
2025 * gdk_x11_screen_get_window_manager_name:
2026 * @screen: a #GdkScreen
2028 * Returns the name of the window manager for @screen.
2030 * Return value: the name of the window manager screen @screen, or
2031 * "unknown" if the window manager is unknown. The string is owned by GDK
2032 * and should not be freed.
2037 gdk_x11_screen_get_window_manager_name (GdkScreen *screen)
2039 GdkScreenX11 *screen_x11;
2041 screen_x11 = GDK_SCREEN_X11 (screen);
2043 if (!G_LIKELY (GDK_DISPLAY_X11 (screen_x11->display)->trusted_client))
2044 return screen_x11->window_manager_name;
2046 fetch_net_wm_check_window (screen);
2048 if (screen_x11->need_refetch_wm_name)
2050 /* Get the name of the window manager */
2051 screen_x11->need_refetch_wm_name = FALSE;
2053 g_free (screen_x11->window_manager_name);
2054 screen_x11->window_manager_name = g_strdup ("unknown");
2056 if (screen_x11->wmspec_check_window != None)
2066 gdk_error_trap_push ();
2068 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (screen_x11->display),
2069 screen_x11->wmspec_check_window,
2070 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2072 0, G_MAXLONG, False,
2073 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
2076 &n_items, &bytes_after,
2079 gdk_display_sync (screen_x11->display);
2081 gdk_error_trap_pop ();
2085 g_free (screen_x11->window_manager_name);
2086 screen_x11->window_manager_name = g_strdup (name);
2092 return GDK_SCREEN_X11 (screen)->window_manager_name;
2095 #define __GDK_SCREEN_X11_C__
2096 #include "gdkaliasdef.c"