1 /*
2 * gdkscreen-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
29 #include <glib.h>
30 #include "gdkscreen.h"
31 #include "gdkscreen-x11.h"
32 #include "gdkdisplay.h"
33 #include "gdkdisplay-x11.h"
34 #include "gdkx.h"
35 #include "gdkalias.h"
36
37 #include <X11/Xatom.h>
38
39 #ifdef HAVE_SOLARIS_XINERAMA
40 #include <X11/extensions/xinerama.h>
41 #endif
42 #ifdef HAVE_XFREE_XINERAMA
43 #include <X11/extensions/Xinerama.h>
44 #endif
45
46 #ifdef HAVE_RANDR
47 #include <X11/extensions/Xrandr.h>
48 #endif
49
50 #ifdef HAVE_XFIXES
51 #include <X11/extensions/Xfixes.h>
52 #endif
53
54 static void gdk_screen_x11_dispose (GObject *object);
55 static void gdk_screen_x11_finalize (GObject *object);
56 static void init_randr_support (GdkScreen *screen);
57 static void deinit_multihead (GdkScreen *screen);
58
59 enum
60 {
61 WINDOW_MANAGER_CHANGED,
62 LAST_SIGNAL
63 };
64
65 static guint signals[LAST_SIGNAL] = { 0 };
66
67 G_DEFINE_TYPE (GdkScreenX11, _gdk_screen_x11, GDK_TYPE_SCREEN)
68
69 struct _GdkX11Monitor
70 {
71 GdkRectangle geometry;
72 XID output;
73 int width_mm;
74 int height_mm;
75 char * output_name;
76 char * manufacturer;
77 };
78
79 static void
_gdk_screen_x11_class_init(GdkScreenX11Class * klass)80 _gdk_screen_x11_class_init (GdkScreenX11Class *klass)
81 {
82 GObjectClass *object_class = G_OBJECT_CLASS (klass);
83
84 object_class->dispose = gdk_screen_x11_dispose;
85 object_class->finalize = gdk_screen_x11_finalize;
86
87 signals[WINDOW_MANAGER_CHANGED] =
88 g_signal_new (g_intern_static_string ("window_manager_changed"),
89 G_OBJECT_CLASS_TYPE (object_class),
90 G_SIGNAL_RUN_LAST,
91 G_STRUCT_OFFSET (GdkScreenX11Class, window_manager_changed),
92 NULL, NULL,
93 g_cclosure_marshal_VOID__VOID,
94 G_TYPE_NONE,
95 0);
96 }
97
98 static void
_gdk_screen_x11_init(GdkScreenX11 * screen)99 _gdk_screen_x11_init (GdkScreenX11 *screen)
100 {
101 }
102
103 /**
104 * gdk_screen_get_display:
105 * @screen: a #GdkScreen
106 *
107 * Gets the display to which the @screen belongs.
108 *
109 * Returns: the display to which @screen belongs
110 *
111 * Since: 2.2
112 **/
113 GdkDisplay *
gdk_screen_get_display(GdkScreen * screen)114 gdk_screen_get_display (GdkScreen *screen)
115 {
116 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
117
118 return GDK_SCREEN_X11 (screen)->display;
119 }
120 /**
121 * gdk_screen_get_width:
122 * @screen: a #GdkScreen
123 *
124 * Gets the width of @screen in pixels
125 *
126 * Returns: the width of @screen in pixels.
127 *
128 * Since: 2.2
129 **/
130 gint
gdk_screen_get_width(GdkScreen * screen)131 gdk_screen_get_width (GdkScreen *screen)
132 {
133 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
134
135 return WidthOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
136 }
137
138 /**
139 * gdk_screen_get_height:
140 * @screen: a #GdkScreen
141 *
142 * Gets the height of @screen in pixels
143 *
144 * Returns: the height of @screen in pixels.
145 *
146 * Since: 2.2
147 **/
148 gint
gdk_screen_get_height(GdkScreen * screen)149 gdk_screen_get_height (GdkScreen *screen)
150 {
151 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
152
153 return HeightOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
154 }
155
156 /**
157 * gdk_screen_get_width_mm:
158 * @screen: a #GdkScreen
159 *
160 * Gets the width of @screen in millimeters.
161 * Note that on some X servers this value will not be correct.
162 *
163 * Returns: the width of @screen in millimeters.
164 *
165 * Since: 2.2
166 **/
167 gint
gdk_screen_get_width_mm(GdkScreen * screen)168 gdk_screen_get_width_mm (GdkScreen *screen)
169 {
170 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
171
172 return WidthMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
173 }
174
175 /**
176 * gdk_screen_get_height_mm:
177 * @screen: a #GdkScreen
178 *
179 * Returns the height of @screen in millimeters.
180 * Note that on some X servers this value will not be correct.
181 *
182 * Returns: the heigth of @screen in millimeters.
183 *
184 * Since: 2.2
185 **/
186 gint
gdk_screen_get_height_mm(GdkScreen * screen)187 gdk_screen_get_height_mm (GdkScreen *screen)
188 {
189 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
190
191 return HeightMMOfScreen (GDK_SCREEN_X11 (screen)->xscreen);
192 }
193
194 /**
195 * gdk_screen_get_number:
196 * @screen: a #GdkScreen
197 *
198 * Gets the index of @screen among the screens in the display
199 * to which it belongs. (See gdk_screen_get_display())
200 *
201 * Returns: the index
202 *
203 * Since: 2.2
204 **/
205 gint
gdk_screen_get_number(GdkScreen * screen)206 gdk_screen_get_number (GdkScreen *screen)
207 {
208 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
209
210 return GDK_SCREEN_X11 (screen)->screen_num;
211 }
212
213 /**
214 * gdk_screen_get_root_window:
215 * @screen: a #GdkScreen
216 *
217 * Gets the root window of @screen.
218 *
219 * Returns: (transfer none): the root window
220 *
221 * Since: 2.2
222 **/
223 GdkWindow *
gdk_screen_get_root_window(GdkScreen * screen)224 gdk_screen_get_root_window (GdkScreen *screen)
225 {
226 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
227
228 return GDK_SCREEN_X11 (screen)->root_window;
229 }
230
231 /**
232 * gdk_screen_get_default_colormap:
233 * @screen: a #GdkScreen
234 *
235 * Gets the default colormap for @screen.
236 *
237 * Returns: (transfer none): the default #GdkColormap.
238 *
239 * Since: 2.2
240 **/
241 GdkColormap *
gdk_screen_get_default_colormap(GdkScreen * screen)242 gdk_screen_get_default_colormap (GdkScreen *screen)
243 {
244 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
245
246 return GDK_SCREEN_X11 (screen)->default_colormap;
247 }
248
249 /**
250 * gdk_screen_set_default_colormap:
251 * @screen: a #GdkScreen
252 * @colormap: a #GdkColormap
253 *
254 * Sets the default @colormap for @screen.
255 *
256 * Since: 2.2
257 **/
258 void
gdk_screen_set_default_colormap(GdkScreen * screen,GdkColormap * colormap)259 gdk_screen_set_default_colormap (GdkScreen *screen,
260 GdkColormap *colormap)
261 {
262 GdkColormap *old_colormap;
263
264 g_return_if_fail (GDK_IS_SCREEN (screen));
265 g_return_if_fail (GDK_IS_COLORMAP (colormap));
266
267 old_colormap = GDK_SCREEN_X11 (screen)->default_colormap;
268
269 GDK_SCREEN_X11 (screen)->default_colormap = g_object_ref (colormap);
270
271 if (old_colormap)
272 g_object_unref (old_colormap);
273 }
274
275 static void
gdk_screen_x11_dispose(GObject * object)276 gdk_screen_x11_dispose (GObject *object)
277 {
278 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
279
280 _gdk_x11_events_uninit_screen (GDK_SCREEN (object));
281
282 if (screen_x11->default_colormap)
283 {
284 g_object_unref (screen_x11->default_colormap);
285 screen_x11->default_colormap = NULL;
286 }
287
288 if (screen_x11->system_colormap)
289 {
290 g_object_unref (screen_x11->system_colormap);
291 screen_x11->system_colormap = NULL;
292 }
293
294 if (screen_x11->rgba_colormap)
295 {
296 g_object_unref (screen_x11->rgba_colormap);
297 screen_x11->rgba_colormap = NULL;
298 }
299
300 if (screen_x11->root_window)
301 _gdk_window_destroy (screen_x11->root_window, TRUE);
302
303 G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->dispose (object);
304
305 screen_x11->xdisplay = NULL;
306 screen_x11->xscreen = NULL;
307 screen_x11->screen_num = -1;
308 screen_x11->xroot_window = None;
309 screen_x11->wmspec_check_window = None;
310 }
311
312 static void
gdk_screen_x11_finalize(GObject * object)313 gdk_screen_x11_finalize (GObject *object)
314 {
315 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (object);
316 gint i;
317
318 if (screen_x11->root_window)
319 g_object_unref (screen_x11->root_window);
320
321 if (screen_x11->renderer)
322 g_object_unref (screen_x11->renderer);
323
324 /* Visual Part */
325 for (i = 0; i < screen_x11->nvisuals; i++)
326 g_object_unref (screen_x11->visuals[i]);
327 g_free (screen_x11->visuals);
328 g_hash_table_destroy (screen_x11->visual_hash);
329
330 g_free (screen_x11->window_manager_name);
331
332 g_hash_table_destroy (screen_x11->colormap_hash);
333
334 deinit_multihead (GDK_SCREEN (object));
335
336 G_OBJECT_CLASS (_gdk_screen_x11_parent_class)->finalize (object);
337 }
338
339 /**
340 * gdk_screen_get_n_monitors:
341 * @screen: a #GdkScreen
342 *
343 * Returns the number of monitors which @screen consists of.
344 *
345 * Returns: number of monitors which @screen consists of
346 *
347 * Since: 2.2
348 */
349 gint
gdk_screen_get_n_monitors(GdkScreen * screen)350 gdk_screen_get_n_monitors (GdkScreen *screen)
351 {
352 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
353
354 return GDK_SCREEN_X11 (screen)->n_monitors;
355 }
356
357 /**
358 * gdk_screen_get_primary_monitor:
359 * @screen: a #GdkScreen.
360 *
361 * Gets the primary monitor for @screen. The primary monitor
362 * is considered the monitor where the 'main desktop' lives.
363 * While normal application windows typically allow the window
364 * manager to place the windows, specialized desktop applications
365 * such as panels should place themselves on the primary monitor.
366 *
367 * If no primary monitor is configured by the user, the return value
368 * will be 0, defaulting to the first monitor.
369 *
370 * Returns: An integer index for the primary monitor, or 0 if none is configured.
371 *
372 * Since: 2.20
373 */
374 gint
gdk_screen_get_primary_monitor(GdkScreen * screen)375 gdk_screen_get_primary_monitor (GdkScreen *screen)
376 {
377 g_return_val_if_fail (GDK_IS_SCREEN (screen), 0);
378
379 return GDK_SCREEN_X11 (screen)->primary_monitor;
380 }
381
382 /**
383 * gdk_screen_get_monitor_width_mm:
384 * @screen: a #GdkScreen
385 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
386 *
387 * Gets the width in millimeters of the specified monitor, if available.
388 *
389 * Returns: the width of the monitor, or -1 if not available
390 *
391 * Since: 2.14
392 */
393 gint
gdk_screen_get_monitor_width_mm(GdkScreen * screen,gint monitor_num)394 gdk_screen_get_monitor_width_mm (GdkScreen *screen,
395 gint monitor_num)
396 {
397 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
398
399 g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
400 g_return_val_if_fail (monitor_num >= 0, -1);
401 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
402
403 return screen_x11->monitors[monitor_num].width_mm;
404 }
405
406 /**
407 * gdk_screen_get_monitor_height_mm:
408 * @screen: a #GdkScreen
409 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
410 *
411 * Gets the height in millimeters of the specified monitor.
412 *
413 * Returns: the height of the monitor, or -1 if not available
414 *
415 * Since: 2.14
416 */
417 gint
gdk_screen_get_monitor_height_mm(GdkScreen * screen,gint monitor_num)418 gdk_screen_get_monitor_height_mm (GdkScreen *screen,
419 gint monitor_num)
420 {
421 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
422
423 g_return_val_if_fail (GDK_IS_SCREEN (screen), -1);
424 g_return_val_if_fail (monitor_num >= 0, -1);
425 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, -1);
426
427 return screen_x11->monitors[monitor_num].height_mm;
428 }
429
430 /**
431 * gdk_screen_get_monitor_plug_name:
432 * @screen: a #GdkScreen
433 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
434 *
435 * Returns the output name of the specified monitor.
436 * Usually something like VGA, DVI, or TV, not the actual
437 * product name of the display device.
438 *
439 * Returns: a newly-allocated string containing the name of the monitor,
440 * or %NULL if the name cannot be determined
441 *
442 * Since: 2.14
443 */
444 gchar *
gdk_screen_get_monitor_plug_name(GdkScreen * screen,gint monitor_num)445 gdk_screen_get_monitor_plug_name (GdkScreen *screen,
446 gint monitor_num)
447 {
448 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
449
450 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
451 g_return_val_if_fail (monitor_num >= 0, NULL);
452 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, NULL);
453
454 return g_strdup (screen_x11->monitors[monitor_num].output_name);
455 }
456
457 /**
458 * gdk_x11_screen_get_monitor_output:
459 * @screen: a #GdkScreen
460 * @monitor_num: number of the monitor, between 0 and gdk_screen_get_n_monitors (screen)
461 *
462 * Gets the XID of the specified output/monitor.
463 * If the X server does not support version 1.2 of the RANDR
464 * extension, 0 is returned.
465 *
466 * Returns: the XID of the monitor
467 *
468 * Since: 2.14
469 */
470 XID
gdk_x11_screen_get_monitor_output(GdkScreen * screen,gint monitor_num)471 gdk_x11_screen_get_monitor_output (GdkScreen *screen,
472 gint monitor_num)
473 {
474 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
475
476 g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
477 g_return_val_if_fail (monitor_num >= 0, None);
478 g_return_val_if_fail (monitor_num < screen_x11->n_monitors, None);
479
480 return screen_x11->monitors[monitor_num].output;
481 }
482
483 /**
484 * gdk_screen_get_monitor_geometry:
485 * @screen: a #GdkScreen
486 * @monitor_num: the monitor number, between 0 and gdk_screen_get_n_monitors (screen)
487 * @dest: a #GdkRectangle to be filled with the monitor geometry
488 *
489 * Retrieves the #GdkRectangle representing the size and position of
490 * the individual monitor within the entire screen area.
491 *
492 * Note that the size of the entire screen area can be retrieved via
493 * gdk_screen_get_width() and gdk_screen_get_height().
494 *
495 * Since: 2.2
496 */
497 void
gdk_screen_get_monitor_geometry(GdkScreen * screen,gint monitor_num,GdkRectangle * dest)498 gdk_screen_get_monitor_geometry (GdkScreen *screen,
499 gint monitor_num,
500 GdkRectangle *dest)
501 {
502 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
503
504 g_return_if_fail (GDK_IS_SCREEN (screen));
505 g_return_if_fail (monitor_num >= 0);
506 g_return_if_fail (monitor_num < screen_x11->n_monitors);
507
508 if (dest)
509 *dest = screen_x11->monitors[monitor_num].geometry;
510 }
511
512 /**
513 * gdk_screen_get_rgba_colormap:
514 * @screen: a #GdkScreen.
515 *
516 * Gets a colormap to use for creating windows or pixmaps with an
517 * alpha channel. The windowing system on which GTK+ is running
518 * may not support this capability, in which case %NULL will
519 * be returned. Even if a non-%NULL value is returned, its
520 * possible that the window's alpha channel won't be honored
521 * when displaying the window on the screen: in particular, for
522 * X an appropriate windowing manager and compositing manager
523 * must be running to provide appropriate display.
524 *
525 * This functionality is not implemented in the Windows backend.
526 *
527 * For setting an overall opacity for a top-level window, see
528 * gdk_window_set_opacity().
529
530 * Return value: (transfer none): a colormap to use for windows with
531 * an alpha channel or %NULL if the capability is not available.
532 *
533 * Since: 2.8
534 **/
535 GdkColormap *
gdk_screen_get_rgba_colormap(GdkScreen * screen)536 gdk_screen_get_rgba_colormap (GdkScreen *screen)
537 {
538 GdkScreenX11 *screen_x11;
539
540 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
541
542 screen_x11 = GDK_SCREEN_X11 (screen);
543
544 if (!screen_x11->rgba_visual)
545 return NULL;
546
547 if (!screen_x11->rgba_colormap)
548 screen_x11->rgba_colormap = gdk_colormap_new (screen_x11->rgba_visual,
549 FALSE);
550
551 return screen_x11->rgba_colormap;
552 }
553
554 /**
555 * gdk_screen_get_rgba_visual:
556 * @screen: a #GdkScreen
557 *
558 * Gets a visual to use for creating windows or pixmaps with an
559 * alpha channel. See the docs for gdk_screen_get_rgba_colormap()
560 * for caveats.
561 *
562 * Return value: (transfer none): a visual to use for windows with an
563 * alpha channel or %NULL if the capability is not available.
564 *
565 * Since: 2.8
566 **/
567 GdkVisual *
gdk_screen_get_rgba_visual(GdkScreen * screen)568 gdk_screen_get_rgba_visual (GdkScreen *screen)
569 {
570 GdkScreenX11 *screen_x11;
571
572 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
573
574 screen_x11 = GDK_SCREEN_X11 (screen);
575
576 return screen_x11->rgba_visual;
577 }
578
579 /**
580 * gdk_x11_screen_get_xscreen:
581 * @screen: a #GdkScreen.
582 * @returns: (transfer none): an Xlib <type>Screen*</type>
583 *
584 * Returns the screen of a #GdkScreen.
585 *
586 * Since: 2.2
587 */
588 Screen *
gdk_x11_screen_get_xscreen(GdkScreen * screen)589 gdk_x11_screen_get_xscreen (GdkScreen *screen)
590 {
591 return GDK_SCREEN_X11 (screen)->xscreen;
592 }
593
594 /**
595 * gdk_x11_screen_get_screen_number:
596 * @screen: a #GdkScreen.
597 * @returns: the position of @screen among the screens of
598 * its display.
599 *
600 * Returns the index of a #GdkScreen.
601 *
602 * Since: 2.2
603 */
604 int
gdk_x11_screen_get_screen_number(GdkScreen * screen)605 gdk_x11_screen_get_screen_number (GdkScreen *screen)
606 {
607 return GDK_SCREEN_X11 (screen)->screen_num;
608 }
609
610 static gboolean
check_is_composited(GdkDisplay * display,GdkScreenX11 * screen_x11)611 check_is_composited (GdkDisplay *display,
612 GdkScreenX11 *screen_x11)
613 {
614 Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom);
615 Window xwindow;
616
617 xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection);
618
619 return xwindow != None;
620 }
621
622 static GdkAtom
make_cm_atom(int screen_number)623 make_cm_atom (int screen_number)
624 {
625 gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number);
626 GdkAtom atom = gdk_atom_intern (name, FALSE);
627 g_free (name);
628 return atom;
629 }
630
631 static void
init_monitor_geometry(GdkX11Monitor * monitor,int x,int y,int width,int height)632 init_monitor_geometry (GdkX11Monitor *monitor,
633 int x, int y, int width, int height)
634 {
635 monitor->geometry.x = x;
636 monitor->geometry.y = y;
637 monitor->geometry.width = width;
638 monitor->geometry.height = height;
639
640 monitor->output = None;
641 monitor->width_mm = -1;
642 monitor->height_mm = -1;
643 monitor->output_name = NULL;
644 monitor->manufacturer = NULL;
645 }
646
647 static gboolean
init_fake_xinerama(GdkScreen * screen)648 init_fake_xinerama (GdkScreen *screen)
649 {
650 #ifdef G_ENABLE_DEBUG
651 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
652 XSetWindowAttributes atts;
653 Window win;
654 gint w, h;
655
656 if (!(_gdk_debug_flags & GDK_DEBUG_XINERAMA))
657 return FALSE;
658
659 /* Fake Xinerama mode by splitting the screen into 4 monitors.
660 * Also draw a little cross to make the monitor boundaries visible.
661 */
662 w = WidthOfScreen (screen_x11->xscreen);
663 h = HeightOfScreen (screen_x11->xscreen);
664
665 screen_x11->n_monitors = 4;
666 screen_x11->monitors = g_new0 (GdkX11Monitor, 4);
667 init_monitor_geometry (&screen_x11->monitors[0], 0, 0, w / 2, h / 2);
668 init_monitor_geometry (&screen_x11->monitors[1], w / 2, 0, w / 2, h / 2);
669 init_monitor_geometry (&screen_x11->monitors[2], 0, h / 2, w / 2, h / 2);
670 init_monitor_geometry (&screen_x11->monitors[3], w / 2, h / 2, w / 2, h / 2);
671
672 atts.override_redirect = 1;
673 atts.background_pixel = WhitePixel(GDK_SCREEN_XDISPLAY (screen),
674 screen_x11->screen_num);
675 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
676 screen_x11->xroot_window, 0, h / 2, w, 1, 0,
677 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
678 screen_x11->screen_num),
679 InputOutput,
680 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
681 screen_x11->screen_num),
682 CWOverrideRedirect|CWBackPixel,
683 &atts);
684 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
685 win = XCreateWindow(GDK_SCREEN_XDISPLAY (screen),
686 screen_x11->xroot_window, w/2 , 0, 1, h, 0,
687 DefaultDepth(GDK_SCREEN_XDISPLAY (screen),
688 screen_x11->screen_num),
689 InputOutput,
690 DefaultVisual(GDK_SCREEN_XDISPLAY (screen),
691 screen_x11->screen_num),
692 CWOverrideRedirect|CWBackPixel,
693 &atts);
694 XMapRaised(GDK_SCREEN_XDISPLAY (screen), win);
695 return TRUE;
696 #endif
697
698 return FALSE;
699 }
700
701 static void
free_monitors(GdkX11Monitor * monitors,gint n_monitors)702 free_monitors (GdkX11Monitor *monitors,
703 gint n_monitors)
704 {
705 int i;
706
707 for (i = 0; i < n_monitors; ++i)
708 {
709 g_free (monitors[i].output_name);
710 g_free (monitors[i].manufacturer);
711 }
712
713 g_free (monitors);
714 }
715
716 #ifdef HAVE_RANDR
717 static int
monitor_compare_function(GdkX11Monitor * monitor1,GdkX11Monitor * monitor2)718 monitor_compare_function (GdkX11Monitor *monitor1,
719 GdkX11Monitor *monitor2)
720 {
721 /* Sort the leftmost/topmost monitors first.
722 * For "cloned" monitors, sort the bigger ones first
723 * (giving preference to taller monitors over wider
724 * monitors)
725 */
726
727 if (monitor1->geometry.x != monitor2->geometry.x)
728 return monitor1->geometry.x - monitor2->geometry.x;
729
730 if (monitor1->geometry.y != monitor2->geometry.y)
731 return monitor1->geometry.y - monitor2->geometry.y;
732
733 if (monitor1->geometry.height != monitor2->geometry.height)
734 return - (monitor1->geometry.height - monitor2->geometry.height);
735
736 if (monitor1->geometry.width != monitor2->geometry.width)
737 return - (monitor1->geometry.width - monitor2->geometry.width);
738
739 return 0;
740 }
741 #endif
742
743 #ifdef HAVE_RANDR15
744 static gboolean
init_randr15(GdkScreen * screen)745 init_randr15 (GdkScreen *screen)
746 {
747 GdkDisplay *display = gdk_screen_get_display (screen);
748 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
749 GdkScreenX11 *x11_screen = GDK_SCREEN_X11 (screen);
750 XRRMonitorInfo *rr_monitors;
751 int num_rr_monitors;
752 int i;
753 GArray *monitors;
754 XID primary_output = None;
755
756 if (!display_x11->have_randr15)
757 return FALSE;
758
759 rr_monitors = XRRGetMonitors (x11_screen->xdisplay,
760 x11_screen->xroot_window,
761 True,
762 &num_rr_monitors);
763 if (!rr_monitors)
764 return FALSE;
765
766 monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
767 num_rr_monitors);
768 for (i = 0; i < num_rr_monitors; i++)
769 {
770 GdkX11Monitor monitor;
771 init_monitor_geometry (&monitor,
772 rr_monitors[i].x,
773 rr_monitors[i].y,
774 rr_monitors[i].width,
775 rr_monitors[i].height);
776
777 monitor.width_mm = rr_monitors[i].mwidth;
778 monitor.height_mm = rr_monitors[i].mheight;
779 monitor.output = rr_monitors[i].outputs[0];
780 if (rr_monitors[i].primary)
781 primary_output = monitor.output;
782
783 g_array_append_val (monitors, monitor);
784 }
785 XRRFreeMonitors (rr_monitors);
786
787 g_array_sort (monitors,
788 (GCompareFunc) monitor_compare_function);
789 x11_screen->n_monitors = monitors->len;
790 x11_screen->monitors = (GdkX11Monitor *) g_array_free (monitors, FALSE);
791
792 x11_screen->primary_monitor = 0;
793
794 for (i = 0; i < x11_screen->n_monitors; i++)
795 {
796 if (x11_screen->monitors[i].output == primary_output)
797 {
798 x11_screen->primary_monitor = i;
799 break;
800 }
801 }
802
803 return x11_screen->n_monitors > 0;
804 }
805 #endif
806
807 static gboolean
init_randr13(GdkScreen * screen)808 init_randr13 (GdkScreen *screen)
809 {
810 #ifdef HAVE_RANDR
811 GdkDisplay *display = gdk_screen_get_display (screen);
812 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
813 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
814 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
815 XRRScreenResources *resources;
816 RROutput primary_output;
817 RROutput first_output = None;
818 int i;
819 GArray *monitors;
820 gboolean randr12_compat = FALSE;
821
822 if (!display_x11->have_randr13)
823 return FALSE;
824
825 resources = XRRGetScreenResourcesCurrent (screen_x11->xdisplay,
826 screen_x11->xroot_window);
827 if (!resources)
828 return FALSE;
829
830 monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor),
831 resources->noutput);
832
833 for (i = 0; i < resources->noutput; ++i)
834 {
835 XRROutputInfo *output =
836 XRRGetOutputInfo (dpy, resources, resources->outputs[i]);
837
838 /* Non RandR1.2 X driver have output name "default" */
839 randr12_compat |= !g_strcmp0 (output->name, "default");
840
841 if (output->connection == RR_Disconnected)
842 {
843 XRRFreeOutputInfo (output);
844 continue;
845 }
846
847 if (output->crtc)
848 {
849 GdkX11Monitor monitor;
850 XRRCrtcInfo *crtc = XRRGetCrtcInfo (dpy, resources, output->crtc);
851
852 monitor.geometry.x = crtc->x;
853 monitor.geometry.y = crtc->y;
854 monitor.geometry.width = crtc->width;
855 monitor.geometry.height = crtc->height;
856
857 monitor.output = resources->outputs[i];
858 monitor.width_mm = output->mm_width;
859 monitor.height_mm = output->mm_height;
860 monitor.output_name = g_strdup (output->name);
861 /* FIXME: need EDID parser */
862 monitor.manufacturer = NULL;
863
864 g_array_append_val (monitors, monitor);
865
866 XRRFreeCrtcInfo (crtc);
867 }
868
869 XRRFreeOutputInfo (output);
870 }
871
872 if (resources->noutput > 0)
873 first_output = resources->outputs[0];
874
875 XRRFreeScreenResources (resources);
876
877 /* non RandR 1.2 X driver doesn't return any usable multihead data */
878 if (randr12_compat)
879 {
880 guint n_monitors = monitors->len;
881
882 free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE),
883 n_monitors);
884
885 return FALSE;
886 }
887
888 g_array_sort (monitors,
889 (GCompareFunc) monitor_compare_function);
890 screen_x11->n_monitors = monitors->len;
891 screen_x11->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
892
893 screen_x11->primary_monitor = 0;
894
895 primary_output = XRRGetOutputPrimary (screen_x11->xdisplay,
896 screen_x11->xroot_window);
897
898 for (i = 0; i < screen_x11->n_monitors; ++i)
899 {
900 if (screen_x11->monitors[i].output == primary_output)
901 {
902 screen_x11->primary_monitor = i;
903 break;
904 }
905
906 /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
907 if (primary_output == None &&
908 g_ascii_strncasecmp (screen_x11->monitors[i].output_name, "LVDS", 4) == 0)
909 {
910 screen_x11->primary_monitor = i;
911 break;
912 }
913
914 /* No primary specified and no LVDS found */
915 if (screen_x11->monitors[i].output == first_output)
916 screen_x11->primary_monitor = i;
917 }
918
919 return screen_x11->n_monitors > 0;
920 #endif
921
922 return FALSE;
923 }
924
925 static gboolean
init_solaris_xinerama(GdkScreen * screen)926 init_solaris_xinerama (GdkScreen *screen)
927 {
928 #ifdef HAVE_SOLARIS_XINERAMA
929 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
930 int screen_no = gdk_screen_get_number (screen);
931 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
932 XRectangle monitors[MAXFRAMEBUFFERS];
933 unsigned char hints[16];
934 gint result;
935 int n_monitors;
936 int i;
937
938 if (!XineramaGetState (dpy, screen_no))
939 return FALSE;
940
941 result = XineramaGetInfo (dpy, screen_no, monitors, hints, &n_monitors);
942
943 /* Yes I know it should be Success but the current implementation
944 * returns the num of monitor
945 */
946 if (result == 0)
947 {
948 return FALSE;
949 }
950
951 screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
952 screen_x11->n_monitors = n_monitors;
953
954 for (i = 0; i < n_monitors; i++)
955 {
956 init_monitor_geometry (&screen_x11->monitors[i],
957 monitors[i].x, monitors[i].y,
958 monitors[i].width, monitors[i].height);
959 }
960
961 screen_x11->primary_monitor = 0;
962
963 return TRUE;
964 #endif /* HAVE_SOLARIS_XINERAMA */
965
966 return FALSE;
967 }
968
969 static gboolean
init_xfree_xinerama(GdkScreen * screen)970 init_xfree_xinerama (GdkScreen *screen)
971 {
972 #ifdef HAVE_XFREE_XINERAMA
973 Display *dpy = GDK_SCREEN_XDISPLAY (screen);
974 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
975 XineramaScreenInfo *monitors;
976 int i, n_monitors;
977
978 if (!XineramaIsActive (dpy))
979 return FALSE;
980
981 monitors = XineramaQueryScreens (dpy, &n_monitors);
982
983 if (n_monitors <= 0 || monitors == NULL)
984 {
985 /* If Xinerama doesn't think we have any monitors, try acting as
986 * though we had no Xinerama. If the "no monitors" condition
987 * is because XRandR 1.2 is currently switching between CRTCs,
988 * we'll be notified again when we have our monitor back,
989 * and can go back into Xinerama-ish mode at that point.
990 */
991 if (monitors)
992 XFree (monitors);
993
994 return FALSE;
995 }
996
997 screen_x11->n_monitors = n_monitors;
998 screen_x11->monitors = g_new0 (GdkX11Monitor, n_monitors);
999
1000 for (i = 0; i < n_monitors; ++i)
1001 {
1002 init_monitor_geometry (&screen_x11->monitors[i],
1003 monitors[i].x_org, monitors[i].y_org,
1004 monitors[i].width, monitors[i].height);
1005 }
1006
1007 XFree (monitors);
1008
1009 screen_x11->primary_monitor = 0;
1010
1011 return TRUE;
1012 #endif /* HAVE_XFREE_XINERAMA */
1013
1014 return FALSE;
1015 }
1016
1017 static void
deinit_multihead(GdkScreen * screen)1018 deinit_multihead (GdkScreen *screen)
1019 {
1020 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1021
1022 free_monitors (screen_x11->monitors, screen_x11->n_monitors);
1023
1024 screen_x11->n_monitors = 0;
1025 screen_x11->monitors = NULL;
1026 }
1027
1028 static gboolean
compare_monitor(GdkX11Monitor * m1,GdkX11Monitor * m2)1029 compare_monitor (GdkX11Monitor *m1,
1030 GdkX11Monitor *m2)
1031 {
1032 if (m1->geometry.x != m2->geometry.x ||
1033 m1->geometry.y != m2->geometry.y ||
1034 m1->geometry.width != m2->geometry.width ||
1035 m1->geometry.height != m2->geometry.height)
1036 return FALSE;
1037
1038 if (m1->width_mm != m2->width_mm ||
1039 m1->height_mm != m2->height_mm)
1040 return FALSE;
1041
1042 if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
1043 return FALSE;
1044
1045 if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
1046 return FALSE;
1047
1048 return TRUE;
1049 }
1050
1051 static gboolean
compare_monitors(GdkX11Monitor * monitors1,gint n_monitors1,GdkX11Monitor * monitors2,gint n_monitors2)1052 compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
1053 GdkX11Monitor *monitors2, gint n_monitors2)
1054 {
1055 gint i;
1056
1057 if (n_monitors1 != n_monitors2)
1058 return FALSE;
1059
1060 for (i = 0; i < n_monitors1; i++)
1061 {
1062 if (!compare_monitor (monitors1 + i, monitors2 + i))
1063 return FALSE;
1064 }
1065
1066 return TRUE;
1067 }
1068
1069 static void
init_multihead(GdkScreen * screen)1070 init_multihead (GdkScreen *screen)
1071 {
1072 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1073 int opcode, firstevent, firsterror;
1074
1075 /* There are four different implementations of multihead support:
1076 *
1077 * 1. Fake Xinerama for debugging purposes
1078 * 2. RandR 1.2
1079 * 3. Solaris Xinerama
1080 * 4. XFree86/Xorg Xinerama
1081 *
1082 * We use them in that order.
1083 */
1084 if (init_fake_xinerama (screen))
1085 return;
1086
1087 #ifdef HAVE_RANDR15
1088 if (init_randr15 (screen))
1089 return;
1090 #endif
1091
1092 if (init_randr13 (screen))
1093 return;
1094
1095 if (XQueryExtension (GDK_SCREEN_XDISPLAY (screen), "XINERAMA",
1096 &opcode, &firstevent, &firsterror))
1097 {
1098 if (init_solaris_xinerama (screen))
1099 return;
1100
1101 if (init_xfree_xinerama (screen))
1102 return;
1103 }
1104
1105 /* No multihead support of any kind for this screen */
1106 screen_x11->n_monitors = 1;
1107 screen_x11->monitors = g_new0 (GdkX11Monitor, 1);
1108 screen_x11->primary_monitor = 0;
1109
1110 init_monitor_geometry (screen_x11->monitors, 0, 0,
1111 WidthOfScreen (screen_x11->xscreen),
1112 HeightOfScreen (screen_x11->xscreen));
1113 }
1114
1115 GdkScreen *
_gdk_x11_screen_new(GdkDisplay * display,gint screen_number)1116 _gdk_x11_screen_new (GdkDisplay *display,
1117 gint screen_number)
1118 {
1119 GdkScreen *screen;
1120 GdkScreenX11 *screen_x11;
1121 GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
1122
1123 screen = g_object_new (GDK_TYPE_SCREEN_X11, NULL);
1124
1125 screen_x11 = GDK_SCREEN_X11 (screen);
1126 screen_x11->display = display;
1127 screen_x11->xdisplay = display_x11->xdisplay;
1128 screen_x11->xscreen = ScreenOfDisplay (display_x11->xdisplay, screen_number);
1129 screen_x11->screen_num = screen_number;
1130 screen_x11->xroot_window = RootWindow (display_x11->xdisplay,screen_number);
1131 screen_x11->wmspec_check_window = None;
1132 /* we want this to be always non-null */
1133 screen_x11->window_manager_name = g_strdup ("unknown");
1134
1135 init_multihead (screen);
1136 init_randr_support (screen);
1137
1138 _gdk_visual_init (screen);
1139 _gdk_windowing_window_init (screen);
1140
1141 return screen;
1142 }
1143
1144 /*
1145 * It is important that we first request the selection
1146 * notification, and then setup the initial state of
1147 * is_composited to avoid a race condition here.
1148 */
1149 void
_gdk_x11_screen_setup(GdkScreen * screen)1150 _gdk_x11_screen_setup (GdkScreen *screen)
1151 {
1152 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1153
1154 screen_x11->cm_selection_atom = make_cm_atom (screen_x11->screen_num);
1155 gdk_display_request_selection_notification (screen_x11->display,
1156 screen_x11->cm_selection_atom);
1157 screen_x11->is_composited = check_is_composited (screen_x11->display, screen_x11);
1158 }
1159
1160 /**
1161 * gdk_screen_is_composited:
1162 * @screen: a #GdkScreen
1163 *
1164 * Returns whether windows with an RGBA visual can reasonably
1165 * be expected to have their alpha channel drawn correctly on
1166 * the screen.
1167 *
1168 * On X11 this function returns whether a compositing manager is
1169 * compositing @screen.
1170 *
1171 * Return value: Whether windows with RGBA visuals can reasonably be
1172 * expected to have their alpha channels drawn correctly on the screen.
1173 *
1174 * Since: 2.10
1175 **/
1176 gboolean
gdk_screen_is_composited(GdkScreen * screen)1177 gdk_screen_is_composited (GdkScreen *screen)
1178 {
1179 GdkScreenX11 *screen_x11;
1180
1181 g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE);
1182
1183 screen_x11 = GDK_SCREEN_X11 (screen);
1184
1185 return screen_x11->is_composited;
1186 }
1187
1188 static void
init_randr_support(GdkScreen * screen)1189 init_randr_support (GdkScreen * screen)
1190 {
1191 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1192
1193 XSelectInput (GDK_SCREEN_XDISPLAY (screen),
1194 screen_x11->xroot_window,
1195 StructureNotifyMask);
1196
1197 #ifdef HAVE_RANDR
1198 XRRSelectInput (GDK_SCREEN_XDISPLAY (screen),
1199 screen_x11->xroot_window,
1200 RRScreenChangeNotifyMask |
1201 RRCrtcChangeNotifyMask |
1202 RROutputPropertyNotifyMask);
1203 #endif
1204 }
1205
1206 static void
process_monitors_change(GdkScreen * screen)1207 process_monitors_change (GdkScreen *screen)
1208 {
1209 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1210 gint n_monitors;
1211 gint primary_monitor;
1212 GdkX11Monitor *monitors;
1213 gboolean changed;
1214
1215 primary_monitor = screen_x11->primary_monitor;
1216 n_monitors = screen_x11->n_monitors;
1217 monitors = screen_x11->monitors;
1218
1219 screen_x11->n_monitors = 0;
1220 screen_x11->monitors = NULL;
1221
1222 init_multihead (screen);
1223
1224 changed =
1225 !compare_monitors (monitors, n_monitors,
1226 screen_x11->monitors, screen_x11->n_monitors) ||
1227 screen_x11->primary_monitor != primary_monitor;
1228
1229 free_monitors (monitors, n_monitors);
1230
1231 if (changed)
1232 g_signal_emit_by_name (screen, "monitors-changed");
1233 }
1234
1235 void
_gdk_x11_screen_size_changed(GdkScreen * screen,XEvent * event)1236 _gdk_x11_screen_size_changed (GdkScreen *screen,
1237 XEvent *event)
1238 {
1239 gint width, height;
1240 #ifdef HAVE_RANDR
1241 GdkDisplayX11 *display_x11;
1242 #endif
1243
1244 width = gdk_screen_get_width (screen);
1245 height = gdk_screen_get_height (screen);
1246
1247 #ifdef HAVE_RANDR
1248 display_x11 = GDK_DISPLAY_X11 (gdk_screen_get_display (screen));
1249
1250 if (display_x11->have_randr13 && event->type == ConfigureNotify)
1251 return;
1252
1253 XRRUpdateConfiguration (event);
1254 #else
1255 if (event->type == ConfigureNotify)
1256 {
1257 XConfigureEvent *rcevent = (XConfigureEvent *) event;
1258 Screen *xscreen = gdk_x11_screen_get_xscreen (screen);
1259
1260 xscreen->width = rcevent->width;
1261 xscreen->height = rcevent->height;
1262 }
1263 else
1264 return;
1265 #endif
1266
1267 process_monitors_change (screen);
1268
1269 if (width != gdk_screen_get_width (screen) ||
1270 height != gdk_screen_get_height (screen))
1271 g_signal_emit_by_name (screen, "size-changed");
1272 }
1273
1274 void
_gdk_x11_screen_window_manager_changed(GdkScreen * screen)1275 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
1276 {
1277 g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
1278 }
1279
1280 void
_gdk_x11_screen_process_owner_change(GdkScreen * screen,XEvent * event)1281 _gdk_x11_screen_process_owner_change (GdkScreen *screen,
1282 XEvent *event)
1283 {
1284 #ifdef HAVE_XFIXES
1285 XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event;
1286 GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
1287 Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display,
1288 screen_x11->cm_selection_atom);
1289
1290 if (selection_event->selection == xcm_selection_atom)
1291 {
1292 gboolean composited = selection_event->owner != None;
1293
1294 if (composited != screen_x11->is_composited)
1295 {
1296 screen_x11->is_composited = composited;
1297
1298 g_signal_emit_by_name (screen, "composited-changed");
1299 }
1300 }
1301 #endif
1302 }
1303
1304 /**
1305 * _gdk_windowing_substitute_screen_number:
1306 * @display_name : The name of a display, in the form used by
1307 * gdk_display_open (). If %NULL a default value
1308 * will be used. On X11, this is derived from the DISPLAY
1309 * environment variable.
1310 * @screen_number : The number of a screen within the display
1311 * referred to by @display_name.
1312 *
1313 * Modifies a @display_name to make @screen_number the default
1314 * screen when the display is opened.
1315 *
1316 * Return value: a newly allocated string holding the resulting
1317 * display name. Free with g_free().
1318 */
1319 gchar *
_gdk_windowing_substitute_screen_number(const gchar * display_name,gint screen_number)1320 _gdk_windowing_substitute_screen_number (const gchar *display_name,
1321 gint screen_number)
1322 {
1323 GString *str;
1324 gchar *p;
1325
1326 if (!display_name)
1327 display_name = getenv ("DISPLAY");
1328
1329 if (!display_name)
1330 return NULL;
1331
1332 str = g_string_new (display_name);
1333
1334 p = strrchr (str->str, '.');
1335 if (p && p > strchr (str->str, ':'))
1336 g_string_truncate (str, p - str->str);
1337
1338 g_string_append_printf (str, ".%d", screen_number);
1339
1340 return g_string_free (str, FALSE);
1341 }
1342
1343 /**
1344 * gdk_screen_make_display_name:
1345 * @screen: a #GdkScreen
1346 *
1347 * Determines the name to pass to gdk_display_open() to get
1348 * a #GdkDisplay with this screen as the default screen.
1349 *
1350 * Return value: a newly allocated string, free with g_free()
1351 *
1352 * Since: 2.2
1353 **/
1354 gchar *
gdk_screen_make_display_name(GdkScreen * screen)1355 gdk_screen_make_display_name (GdkScreen *screen)
1356 {
1357 const gchar *old_display;
1358
1359 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1360
1361 old_display = gdk_display_get_name (gdk_screen_get_display (screen));
1362
1363 return _gdk_windowing_substitute_screen_number (old_display,
1364 gdk_screen_get_number (screen));
1365 }
1366
1367 /**
1368 * gdk_screen_get_active_window
1369 * @screen: a #GdkScreen
1370 *
1371 * Returns the screen's currently active window.
1372 *
1373 * On X11, this is done by inspecting the _NET_ACTIVE_WINDOW property
1374 * on the root window, as described in the <ulink
1375 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1376 * Manager Hints</ulink>. If there is no currently currently active
1377 * window, or the window manager does not support the
1378 * _NET_ACTIVE_WINDOW hint, this function returns %NULL.
1379 *
1380 * On other platforms, this function may return %NULL, depending on whether
1381 * it is implementable on that platform.
1382 *
1383 * The returned window should be unrefed using g_object_unref() when
1384 * no longer needed.
1385 *
1386 * Return value: the currently active window, or %NULL.
1387 *
1388 * Since: 2.10
1389 **/
1390 GdkWindow *
gdk_screen_get_active_window(GdkScreen * screen)1391 gdk_screen_get_active_window (GdkScreen *screen)
1392 {
1393 GdkScreenX11 *screen_x11;
1394 GdkWindow *ret = NULL;
1395 Atom type_return;
1396 gint format_return;
1397 gulong nitems_return;
1398 gulong bytes_after_return;
1399 guchar *data = NULL;
1400
1401 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1402
1403 if (!gdk_x11_screen_supports_net_wm_hint (screen,
1404 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1405 return NULL;
1406
1407 screen_x11 = GDK_SCREEN_X11 (screen);
1408
1409 if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1410 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1411 "_NET_ACTIVE_WINDOW"),
1412 0, 1, False, XA_WINDOW, &type_return,
1413 &format_return, &nitems_return,
1414 &bytes_after_return, &data)
1415 == Success)
1416 {
1417 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
1418 {
1419 GdkNativeWindow window = *(GdkNativeWindow *) data;
1420
1421 if (window != None)
1422 {
1423 ret = gdk_window_foreign_new_for_display (screen_x11->display,
1424 *(GdkNativeWindow *) data);
1425 }
1426 }
1427 }
1428
1429 if (data)
1430 XFree (data);
1431
1432 return ret;
1433 }
1434
1435 /**
1436 * gdk_screen_get_window_stack:
1437 * @screen: a #GdkScreen
1438 *
1439 * Returns a #GList of #GdkWindow<!-- -->s representing the current
1440 * window stack.
1441 *
1442 * On X11, this is done by inspecting the _NET_CLIENT_LIST_STACKING
1443 * property on the root window, as described in the <ulink
1444 * url="http://www.freedesktop.org/Standards/wm-spec">Extended Window
1445 * Manager Hints</ulink>. If the window manager does not support the
1446 * _NET_CLIENT_LIST_STACKING hint, this function returns %NULL.
1447 *
1448 * On other platforms, this function may return %NULL, depending on whether
1449 * it is implementable on that platform.
1450 *
1451 * The returned list is newly allocated and owns references to the
1452 * windows it contains, so it should be freed using g_list_free() and
1453 * its windows unrefed using g_object_unref() when no longer needed.
1454 *
1455 * Return value: (transfer full) (element-type GdkWindow):
1456 * a list of #GdkWindow<!-- -->s for the current window stack,
1457 * or %NULL.
1458 *
1459 * Since: 2.10
1460 **/
1461 GList *
gdk_screen_get_window_stack(GdkScreen * screen)1462 gdk_screen_get_window_stack (GdkScreen *screen)
1463 {
1464 GdkScreenX11 *screen_x11;
1465 GList *ret = NULL;
1466 Atom type_return;
1467 gint format_return;
1468 gulong nitems_return;
1469 gulong bytes_after_return;
1470 guchar *data = NULL;
1471
1472 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1473
1474 if (!gdk_x11_screen_supports_net_wm_hint (screen,
1475 gdk_atom_intern_static_string ("_NET_CLIENT_LIST_STACKING")))
1476 return NULL;
1477
1478 screen_x11 = GDK_SCREEN_X11 (screen);
1479
1480 if (XGetWindowProperty (screen_x11->xdisplay, screen_x11->xroot_window,
1481 gdk_x11_get_xatom_by_name_for_display (screen_x11->display,
1482 "_NET_CLIENT_LIST_STACKING"),
1483 0, G_MAXLONG, False, XA_WINDOW, &type_return,
1484 &format_return, &nitems_return,
1485 &bytes_after_return, &data)
1486 == Success)
1487 {
1488 if ((type_return == XA_WINDOW) && (format_return == 32) &&
1489 (data) && (nitems_return > 0))
1490 {
1491 gulong *stack = (gulong *) data;
1492 GdkWindow *win;
1493 int i;
1494
1495 for (i = 0; i < nitems_return; i++)
1496 {
1497 win = gdk_window_foreign_new_for_display (screen_x11->display,
1498 (GdkNativeWindow)stack[i]);
1499
1500 if (win != NULL)
1501 ret = g_list_append (ret, win);
1502 }
1503 }
1504 }
1505
1506 if (data)
1507 XFree (data);
1508
1509 return ret;
1510 }
1511
1512 #define __GDK_SCREEN_X11_C__
1513 #include "gdkaliasdef.c"
1514