1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gdkwindow-x11.h"
30 #include "gdkwindow.h"
31 #include "gdkwindowimpl.h"
32 #include "gdkvisualprivate.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
36 #include "gdkeventsource.h"
37 #include "gdkdisplay-x11.h"
38 #include "gdkframeclockidle.h"
39 #include "gdkprivate-x11.h"
44 #include <netinet/in.h>
47 #include <cairo-xlib.h>
52 #include <X11/Xutil.h>
53 #include <X11/Xatom.h>
55 #include <X11/extensions/shape.h>
58 #include <X11/XKBlib.h>
61 #ifdef HAVE_XCOMPOSITE
62 #include <X11/extensions/Xcomposite.h>
66 #include <X11/extensions/Xfixes.h>
70 #include <X11/extensions/Xdamage.h>
73 const int _gdk_x11_event_mask_table[21] =
77 PointerMotionHintMask,
94 SubstructureNotifyMask,
95 ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
98 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
100 /* Forward declarations */
101 static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
102 static void gdk_window_set_static_win_gravity (GdkWindow *window,
104 static gboolean gdk_window_icon_name_set (GdkWindow *window);
105 static void set_wm_name (GdkDisplay *display,
108 static void move_to_current_desktop (GdkWindow *window);
109 static void gdk_window_x11_set_background (GdkWindow *window,
110 cairo_pattern_t *pattern);
112 static void gdk_window_impl_x11_finalize (GObject *object);
114 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
115 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
116 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
118 #define WINDOW_IS_TOPLEVEL(window) \
119 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
120 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
121 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
123 /* Return whether time1 is considered later than time2 as far as xserver
124 * time is concerned. Accounts for wraparound.
126 #define XSERVER_TIME_IS_LATER(time1, time2) \
127 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
128 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
131 struct _GdkX11Window {
135 struct _GdkX11WindowClass {
136 GdkWindowClass parent_class;
139 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
142 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
147 gdk_x11_window_init (GdkX11Window *x11_window)
152 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
155 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
157 impl->toplevel_window_type = -1;
158 impl->device_cursor = g_hash_table_new_full (NULL, NULL,
159 NULL, g_object_unref);
163 _gdk_x11_window_get_toplevel (GdkWindow *window)
165 GdkWindowImplX11 *impl;
167 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
169 if (!WINDOW_IS_TOPLEVEL (window))
172 impl = GDK_WINDOW_IMPL_X11 (window->impl);
176 impl->toplevel = g_new0 (GdkToplevelX11, 1);
177 impl->toplevel->have_focused = TRUE;
180 return impl->toplevel;
183 static const cairo_user_data_key_t gdk_x11_cairo_key;
186 * _gdk_x11_window_update_size:
187 * @impl: a #GdkWindowImplX11.
189 * Updates the state of the window (in particular the drawable's
190 * cairo surface) when its size has changed.
193 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
195 if (impl->cairo_surface)
197 cairo_xlib_surface_set_size (impl->cairo_surface,
198 gdk_window_get_width (impl->wrapper),
199 gdk_window_get_height (impl->wrapper));
204 set_sync_counter(Display *display,
205 XSyncCounter counter,
208 XSyncValue sync_value;
210 XSyncIntsToValue(&sync_value,
211 value & G_GINT64_CONSTANT(0xFFFFFFFF),
213 XSyncSetCounter(display, counter, sync_value);
217 gdk_x11_window_begin_frame (GdkWindow *window)
219 GdkWindowImplX11 *impl;
221 g_return_if_fail (GDK_IS_WINDOW (window));
223 impl = GDK_WINDOW_IMPL_X11 (window->impl);
225 if (!WINDOW_IS_TOPLEVEL (window) ||
226 impl->toplevel->extended_update_counter == None)
229 if (impl->toplevel->current_counter_value % 2 == 0)
231 impl->toplevel->current_counter_value += 1;
232 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
233 impl->toplevel->extended_update_counter,
234 impl->toplevel->current_counter_value);
239 gdk_x11_window_end_frame (GdkWindow *window)
241 GdkWindowImplX11 *impl;
243 g_return_if_fail (GDK_IS_WINDOW (window));
245 impl = GDK_WINDOW_IMPL_X11 (window->impl);
247 if (!WINDOW_IS_TOPLEVEL (window) ||
248 impl->toplevel->extended_update_counter == None)
251 if (impl->toplevel->current_counter_value % 2 == 1)
253 impl->toplevel->current_counter_value += 1;
254 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
255 impl->toplevel->extended_update_counter,
256 impl->toplevel->current_counter_value);
258 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
259 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
261 impl->toplevel->frame_pending = TRUE;
262 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
267 /*****************************************************
268 * X11 specific implementations of generic functions *
269 *****************************************************/
272 gdk_x11_cairo_surface_destroy (void *data)
274 GdkWindowImplX11 *impl = data;
276 impl->cairo_surface = NULL;
279 static cairo_surface_t *
280 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
286 visual = gdk_window_get_visual (impl->wrapper);
287 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
288 GDK_WINDOW_IMPL_X11 (impl)->xid,
289 GDK_VISUAL_XVISUAL (visual),
293 static cairo_surface_t *
294 gdk_x11_ref_cairo_surface (GdkWindow *window)
296 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
298 if (GDK_WINDOW_DESTROYED (window))
301 if (!impl->cairo_surface)
303 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
304 gdk_window_get_width (window),
305 gdk_window_get_height (window));
307 if (impl->cairo_surface)
308 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
309 impl, gdk_x11_cairo_surface_destroy);
312 cairo_surface_reference (impl->cairo_surface);
314 return impl->cairo_surface;
318 gdk_window_impl_x11_finalize (GObject *object)
321 GdkWindowImplX11 *impl;
323 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
325 impl = GDK_WINDOW_IMPL_X11 (object);
327 wrapper = impl->wrapper;
329 _gdk_x11_window_grab_check_destroy (wrapper);
331 if (!GDK_WINDOW_DESTROYED (wrapper))
333 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
335 _gdk_x11_display_remove_window (display, impl->xid);
336 if (impl->toplevel && impl->toplevel->focus_window)
337 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
340 g_free (impl->toplevel);
343 g_object_unref (impl->cursor);
345 g_hash_table_destroy (impl->device_cursor);
347 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
356 free_pixmap (gpointer datap)
358 FreePixmapData *data = datap;
360 if (!gdk_display_is_closed (data->display))
362 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
366 g_object_unref (data->display);
367 g_slice_free (FreePixmapData, data);
371 attach_free_pixmap_handler (cairo_surface_t *surface,
375 static const cairo_user_data_key_t key;
376 FreePixmapData *data;
378 data = g_slice_new (FreePixmapData);
379 data->display = g_object_ref (display);
380 data->pixmap = pixmap;
382 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
385 /* Cairo does not guarantee we get an xlib surface if we call
386 * cairo_surface_create_similar(). In some cases however, we must use a
387 * pixmap or bitmap in the X11 API.
388 * These functions ensure an Xlib surface.
391 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
395 cairo_surface_t *surface;
398 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
399 GDK_WINDOW_XID (window),
401 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
403 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
405 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
410 /* Create a surface backed with a pixmap without alpha on the same screen as window */
411 static cairo_surface_t *
412 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
416 GdkScreen *screen = gdk_window_get_screen (window);
417 GdkVisual *visual = gdk_screen_get_system_visual (screen);
418 cairo_surface_t *surface;
421 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
422 GDK_WINDOW_XID (window),
424 gdk_visual_get_depth (visual));
425 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
427 GDK_VISUAL_XVISUAL (visual),
429 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
435 tmp_unset_bg (GdkWindow *window)
437 GdkWindowImplX11 *impl;
439 impl = GDK_WINDOW_IMPL_X11 (window->impl);
443 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
444 GDK_WINDOW_XID (window), None);
448 tmp_reset_bg (GdkWindow *window)
450 GdkWindowImplX11 *impl;
452 impl = GDK_WINDOW_IMPL_X11 (window->impl);
456 gdk_window_x11_set_background (window, window->background);
459 /* Unsetting and resetting window backgrounds.
461 * In many cases it is possible to avoid flicker by unsetting the
462 * background of windows. For example if the background of the
463 * parent window is unset when a window is unmapped, a brief flicker
464 * of background painting is avoided.
467 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
470 g_return_if_fail (GDK_IS_WINDOW (window));
472 if (window->input_only || window->destroyed ||
473 (window->window_type != GDK_WINDOW_ROOT &&
474 !GDK_WINDOW_IS_MAPPED (window)))
477 if (_gdk_window_has_impl (window) &&
478 GDK_WINDOW_IS_X11 (window) &&
479 window->window_type != GDK_WINDOW_ROOT &&
480 window->window_type != GDK_WINDOW_FOREIGN)
481 tmp_unset_bg (window);
487 for (l = window->children; l != NULL; l = l->next)
488 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
493 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
495 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
498 window = _gdk_window_get_impl_window (window->parent);
499 _gdk_x11_window_tmp_unset_bg (window, FALSE);
503 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
506 g_return_if_fail (GDK_IS_WINDOW (window));
508 if (window->input_only || window->destroyed ||
509 (window->window_type != GDK_WINDOW_ROOT &&
510 !GDK_WINDOW_IS_MAPPED (window)))
514 if (_gdk_window_has_impl (window) &&
515 GDK_WINDOW_IS_X11 (window) &&
516 window->window_type != GDK_WINDOW_ROOT &&
517 window->window_type != GDK_WINDOW_FOREIGN)
518 tmp_reset_bg (window);
524 for (l = window->children; l != NULL; l = l->next)
525 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
530 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
532 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
535 window = _gdk_window_get_impl_window (window->parent);
537 _gdk_x11_window_tmp_reset_bg (window, FALSE);
541 _gdk_x11_screen_init_root_window (GdkScreen *screen)
544 GdkWindowImplX11 *impl;
545 GdkX11Screen *x11_screen;
547 x11_screen = GDK_X11_SCREEN (screen);
549 g_assert (x11_screen->root_window == NULL);
551 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
553 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
554 window->impl_window = window;
555 window->visual = gdk_screen_get_system_visual (screen);
557 impl = GDK_WINDOW_IMPL_X11 (window->impl);
559 impl->xid = x11_screen->xroot_window;
560 impl->wrapper = window;
562 window->window_type = GDK_WINDOW_ROOT;
563 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
569 window->width = WidthOfScreen (x11_screen->xscreen);
570 window->height = HeightOfScreen (x11_screen->xscreen);
571 window->viewable = TRUE;
573 /* see init_randr_support() in gdkscreen-x11.c */
574 window->event_mask = GDK_STRUCTURE_MASK;
576 _gdk_window_update_size (x11_screen->root_window);
578 _gdk_x11_display_add_window (x11_screen->display,
579 &x11_screen->xroot_window,
580 x11_screen->root_window);
584 set_wm_protocols (GdkWindow *window)
586 GdkDisplay *display = gdk_window_get_display (window);
590 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
591 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
592 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
595 if (GDK_X11_DISPLAY (display)->use_sync)
596 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
599 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
603 get_default_title (void)
607 title = g_get_application_name ();
609 title = g_get_prgname ();
617 check_leader_window_title (GdkDisplay *display)
619 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
621 if (display_x11->leader_window && !display_x11->leader_window_title_set)
623 set_wm_name (display,
624 display_x11->leader_window,
625 get_default_title ());
627 display_x11->leader_window_title_set = TRUE;
632 create_focus_window (GdkDisplay *display,
635 GdkX11Display *display_x11;
636 GdkEventMask event_mask;
640 xdisplay = GDK_DISPLAY_XDISPLAY (display);
641 display_x11 = GDK_X11_DISPLAY (display);
643 focus_window = XCreateSimpleWindow (xdisplay, parent,
647 /* FIXME: probably better to actually track the requested event mask for the toplevel
649 event_mask = (GDK_KEY_PRESS_MASK |
650 GDK_KEY_RELEASE_MASK |
651 GDK_FOCUS_CHANGE_MASK);
653 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
657 XMapWindow (xdisplay, focus_window);
663 ensure_sync_counter (GdkWindow *window)
666 if (!GDK_WINDOW_DESTROYED (window))
668 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
669 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
672 toplevel->update_counter == None &&
673 GDK_X11_DISPLAY (display)->use_sync)
675 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
680 XSyncIntToValue (&value, 0);
682 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
683 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
685 atom = gdk_x11_get_xatom_by_name_for_display (display,
686 "_NET_WM_SYNC_REQUEST_COUNTER");
688 counters[0] = toplevel->update_counter;
689 counters[1] = toplevel->extended_update_counter;
690 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
693 (guchar *)counters, 2);
695 toplevel->current_counter_value = 0;
702 setup_toplevel_window (GdkWindow *window,
705 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
706 GdkDisplay *display = gdk_window_get_display (window);
707 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
708 XID xid = GDK_WINDOW_XID (window);
709 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
710 XSizeHints size_hints;
712 Window leader_window;
714 set_wm_protocols (window);
716 if (!window->input_only)
718 /* The focus window is off the visible area, and serves to receive key
719 * press events so they don't get sent to child windows.
721 toplevel->focus_window = create_focus_window (display, xid);
722 _gdk_x11_display_add_window (x11_screen->display,
723 &toplevel->focus_window,
727 check_leader_window_title (x11_screen->display);
729 /* FIXME: Is there any point in doing this? Do any WM's pay
730 * attention to PSize, and even if they do, is this the
733 size_hints.flags = PSize;
734 size_hints.width = window->width;
735 size_hints.height = window->height;
737 XSetWMNormalHints (xdisplay, xid, &size_hints);
739 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
740 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
743 XChangeProperty (xdisplay, xid,
744 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
749 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
752 XChangeProperty (xdisplay, xid,
753 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
754 XA_WINDOW, 32, PropModeReplace,
755 (guchar *) &leader_window, 1);
757 if (toplevel->focus_window != None)
758 XChangeProperty (xdisplay, xid,
759 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
760 XA_WINDOW, 32, PropModeReplace,
761 (guchar *) &toplevel->focus_window, 1);
763 if (!window->focus_on_map)
764 gdk_x11_window_set_user_time (window, 0);
765 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
766 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
768 ensure_sync_counter (window);
770 /* Start off in a frozen state - we'll finish this when we first paint */
771 gdk_x11_window_begin_frame (window);
775 on_frame_clock_before_paint (GdkFrameClock *clock,
778 gdk_x11_window_begin_frame (window);
782 on_frame_clock_after_paint (GdkFrameClock *clock,
785 gdk_x11_window_end_frame (window);
789 _gdk_x11_display_create_window_impl (GdkDisplay *display,
791 GdkWindow *real_parent,
793 GdkEventMask event_mask,
794 GdkWindowAttr *attributes,
795 gint attributes_mask)
797 GdkWindowImplX11 *impl;
798 GdkX11Screen *x11_screen;
799 GdkX11Display *display_x11;
800 GdkFrameClock *clock;
806 XSetWindowAttributes xattributes;
807 long xattributes_mask;
808 XClassHint *class_hint;
813 display_x11 = GDK_X11_DISPLAY (display);
814 xparent = GDK_WINDOW_XID (real_parent);
815 x11_screen = GDK_X11_SCREEN (screen);
817 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
818 window->impl = GDK_WINDOW_IMPL (impl);
819 impl->wrapper = GDK_WINDOW (window);
821 xdisplay = x11_screen->xdisplay;
823 xattributes_mask = 0;
825 xvisual = gdk_x11_visual_get_xvisual (window->visual);
827 if (attributes_mask & GDK_WA_NOREDIR)
829 xattributes.override_redirect =
830 (attributes->override_redirect == FALSE)?False:True;
831 xattributes_mask |= CWOverrideRedirect;
834 xattributes.override_redirect = False;
836 impl->override_redirect = xattributes.override_redirect;
838 if (window->parent && window->parent->guffaw_gravity)
840 xattributes.win_gravity = StaticGravity;
841 xattributes_mask |= CWWinGravity;
845 switch (window->window_type)
847 case GDK_WINDOW_TOPLEVEL:
848 case GDK_WINDOW_TEMP:
849 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
851 /* The common code warns for this case */
852 xparent = GDK_SCREEN_XROOTWIN (screen);
856 if (!window->input_only)
860 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
862 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
863 xattributes_mask |= CWBorderPixel | CWBackPixel;
865 if (window->guffaw_gravity)
866 xattributes.bit_gravity = StaticGravity;
868 xattributes.bit_gravity = NorthWestGravity;
870 xattributes_mask |= CWBitGravity;
872 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
873 xattributes_mask |= CWColormap;
875 if (window->window_type == GDK_WINDOW_TEMP)
877 xattributes.save_under = True;
878 xattributes.override_redirect = True;
879 xattributes.cursor = None;
880 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
882 impl->override_redirect = TRUE;
890 if (window->width > 65535 ||
891 window->height > 65535)
893 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
895 if (window->width > 65535)
896 window->width = 65535;
897 if (window->height > 65535)
898 window->height = 65535;
901 impl->xid = XCreateWindow (xdisplay, xparent,
902 window->x + window->parent->abs_x,
903 window->y + window->parent->abs_y,
904 window->width, window->height,
905 0, window->depth, class, xvisual,
906 xattributes_mask, &xattributes);
908 g_object_ref (window);
909 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
911 switch (GDK_WINDOW_TYPE (window))
913 case GDK_WINDOW_TOPLEVEL:
914 case GDK_WINDOW_TEMP:
915 if (attributes_mask & GDK_WA_TITLE)
916 title = attributes->title;
918 title = get_default_title ();
920 gdk_window_set_title (window, title);
922 if (attributes_mask & GDK_WA_WMCLASS)
924 class_hint = XAllocClassHint ();
925 class_hint->res_name = attributes->wmclass_name;
926 class_hint->res_class = attributes->wmclass_class;
927 XSetClassHint (xdisplay, impl->xid, class_hint);
931 setup_toplevel_window (window, window->parent);
934 case GDK_WINDOW_CHILD:
939 if (attributes_mask & GDK_WA_TYPE_HINT)
940 gdk_window_set_type_hint (window, attributes->type_hint);
942 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
943 GDK_WINDOW_XID (window), event_mask,
944 StructureNotifyMask | PropertyChangeMask);
946 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
947 gdk_window_set_frame_clock (window, clock);
948 g_signal_connect (clock, "before-paint",
949 G_CALLBACK (on_frame_clock_before_paint), window);
950 g_signal_connect (clock, "after-paint",
951 G_CALLBACK (on_frame_clock_after_paint), window);
953 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
954 gdk_window_freeze_toplevel_updates_libgtk_only (window);
958 x_event_mask_to_gdk_event_mask (long mask)
960 GdkEventMask event_mask = 0;
963 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
965 if (mask & _gdk_x11_event_mask_table[i])
966 event_mask |= 1 << (i + 1);
973 * gdk_x11_window_foreign_new_for_display:
974 * @display: the #GdkDisplay where the window handle comes from.
975 * @window: an XLib <type>Window</type>
977 * Wraps a native window in a #GdkWindow. The function will try to
978 * look up the window using gdk_x11_window_lookup_for_display() first.
979 * If it does not find it there, it will create a new window.
981 * This may fail if the window has been destroyed. If the window
982 * was already known to GDK, a new reference to the existing
983 * #GdkWindow is returned.
985 * Return value: (transfer full): a #GdkWindow wrapper for the native
986 * window, or %NULL if the window has been destroyed. The wrapper
987 * will be newly created, if one doesn't exist already.
992 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
997 GdkWindowImplX11 *impl;
998 GdkX11Display *display_x11;
999 XWindowAttributes attrs;
1000 Window root, parent;
1001 Window *children = NULL;
1005 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1007 display_x11 = GDK_X11_DISPLAY (display);
1009 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1010 return g_object_ref (win);
1012 gdk_x11_display_error_trap_push (display);
1013 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1014 if (gdk_x11_display_error_trap_pop (display) || !result)
1017 /* FIXME: This is pretty expensive.
1018 * Maybe the caller should supply the parent
1020 gdk_x11_display_error_trap_push (display);
1021 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1022 if (gdk_x11_display_error_trap_pop (display) || !result)
1028 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1030 win = _gdk_display_create_window (display);
1031 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1032 win->impl_window = win;
1033 win->visual = gdk_x11_screen_lookup_visual (screen,
1034 XVisualIDFromVisual (attrs.visual));
1036 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1037 impl->wrapper = win;
1039 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1041 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1042 win->parent = gdk_screen_get_root_window (screen);
1044 win->parent->children = g_list_prepend (win->parent->children, win);
1050 win->width = attrs.width;
1051 win->height = attrs.height;
1052 win->window_type = GDK_WINDOW_FOREIGN;
1053 win->destroyed = FALSE;
1055 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1057 if (attrs.map_state == IsUnmapped)
1058 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1061 win->viewable = TRUE;
1063 win->depth = attrs.depth;
1066 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1068 /* Update the clip region, etc */
1069 _gdk_window_update_size (win);
1075 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1076 GdkToplevelX11 *toplevel)
1078 if (toplevel->icon_pixmap)
1080 cairo_surface_destroy (toplevel->icon_pixmap);
1081 toplevel->icon_pixmap = NULL;
1083 if (toplevel->icon_mask)
1085 cairo_surface_destroy (toplevel->icon_mask);
1086 toplevel->icon_mask = NULL;
1088 if (toplevel->group_leader)
1090 g_object_unref (toplevel->group_leader);
1091 toplevel->group_leader = NULL;
1094 if (toplevel->update_counter != None)
1096 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1097 toplevel->update_counter);
1098 toplevel->update_counter = None;
1100 toplevel->current_counter_value = 0;
1106 gdk_x11_window_destroy (GdkWindow *window,
1108 gboolean foreign_destroy)
1110 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1111 GdkToplevelX11 *toplevel;
1113 g_return_if_fail (GDK_IS_WINDOW (window));
1115 _gdk_x11_selection_window_destroyed (window);
1117 toplevel = _gdk_x11_window_get_toplevel (window);
1119 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1121 if (impl->cairo_surface)
1123 cairo_surface_finish (impl->cairo_surface);
1124 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1128 if (!recursing && !foreign_destroy)
1129 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1132 static cairo_surface_t *
1133 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1134 cairo_surface_t *surface,
1138 cairo_xlib_surface_set_size (surface, width, height);
1144 gdk_x11_window_destroy_foreign (GdkWindow *window)
1146 /* It's somebody else's window, but in our hierarchy,
1147 * so reparent it to the root window, and then send
1148 * it a delete event, as if we were a WM
1150 XClientMessageEvent xclient;
1151 GdkDisplay *display;
1153 display = GDK_WINDOW_DISPLAY (window);
1154 gdk_x11_display_error_trap_push (display);
1155 gdk_window_hide (window);
1156 gdk_window_reparent (window, NULL, 0, 0);
1158 memset (&xclient, 0, sizeof (xclient));
1159 xclient.type = ClientMessage;
1160 xclient.window = GDK_WINDOW_XID (window);
1161 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1162 xclient.format = 32;
1163 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1164 xclient.data.l[1] = CurrentTime;
1165 xclient.data.l[2] = 0;
1166 xclient.data.l[3] = 0;
1167 xclient.data.l[4] = 0;
1169 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1170 GDK_WINDOW_XID (window),
1171 False, 0, (XEvent *)&xclient);
1172 gdk_x11_display_error_trap_pop_ignored (display);
1176 get_root (GdkWindow *window)
1178 GdkScreen *screen = gdk_window_get_screen (window);
1180 return gdk_screen_get_root_window (screen);
1183 /* This function is called when the XWindow is really gone.
1186 gdk_x11_window_destroy_notify (GdkWindow *window)
1188 GdkWindowImplX11 *window_impl;
1190 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1192 if (!GDK_WINDOW_DESTROYED (window))
1194 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1195 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1197 _gdk_window_destroy (window, TRUE);
1200 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1201 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1202 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1204 _gdk_x11_window_grab_check_destroy (window);
1206 g_object_unref (window);
1209 static GdkDragProtocol
1210 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1213 GdkDragProtocol protocol;
1214 GdkDisplay *display;
1218 display = gdk_window_get_display (window);
1219 xid = _gdk_x11_display_get_drag_protocol (display,
1220 GDK_WINDOW_XID (window->impl_window),
1227 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1236 update_wm_hints (GdkWindow *window,
1239 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1240 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1244 !toplevel->is_leader &&
1245 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1248 wm_hints.flags = StateHint | InputHint;
1249 wm_hints.input = window->accept_focus ? True : False;
1250 wm_hints.initial_state = NormalState;
1252 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1254 wm_hints.flags |= StateHint;
1255 wm_hints.initial_state = IconicState;
1258 if (toplevel->icon_pixmap)
1260 wm_hints.flags |= IconPixmapHint;
1261 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1264 if (toplevel->icon_mask)
1266 wm_hints.flags |= IconMaskHint;
1267 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1270 wm_hints.flags |= WindowGroupHint;
1271 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1273 wm_hints.flags |= WindowGroupHint;
1274 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1277 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1279 if (toplevel->urgency_hint)
1280 wm_hints.flags |= XUrgencyHint;
1282 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1283 GDK_WINDOW_XID (window),
1288 set_initial_hints (GdkWindow *window)
1290 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1291 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1292 Window xwindow = GDK_WINDOW_XID (window);
1293 GdkToplevelX11 *toplevel;
1297 toplevel = _gdk_x11_window_get_toplevel (window);
1302 update_wm_hints (window, TRUE);
1304 /* We set the spec hints regardless of whether the spec is supported,
1305 * since it can't hurt and it's kind of expensive to check whether
1311 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1313 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1314 "_NET_WM_STATE_MAXIMIZED_VERT");
1316 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1317 "_NET_WM_STATE_MAXIMIZED_HORZ");
1319 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1322 if (window->state & GDK_WINDOW_STATE_ABOVE)
1324 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1325 "_NET_WM_STATE_ABOVE");
1329 if (window->state & GDK_WINDOW_STATE_BELOW)
1331 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1332 "_NET_WM_STATE_BELOW");
1336 if (window->state & GDK_WINDOW_STATE_STICKY)
1338 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1339 "_NET_WM_STATE_STICKY");
1341 toplevel->have_sticky = TRUE;
1344 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1346 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1347 "_NET_WM_STATE_FULLSCREEN");
1349 toplevel->have_fullscreen = TRUE;
1352 if (window->modal_hint)
1354 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1355 "_NET_WM_STATE_MODAL");
1359 if (toplevel->skip_taskbar_hint)
1361 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1362 "_NET_WM_STATE_SKIP_TASKBAR");
1366 if (toplevel->skip_pager_hint)
1368 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1369 "_NET_WM_STATE_SKIP_PAGER");
1373 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1375 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1376 "_NET_WM_STATE_HIDDEN");
1378 toplevel->have_hidden = TRUE;
1383 XChangeProperty (xdisplay,
1385 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1386 XA_ATOM, 32, PropModeReplace,
1387 (guchar*) atoms, i);
1391 XDeleteProperty (xdisplay,
1393 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1396 if (window->state & GDK_WINDOW_STATE_STICKY)
1398 atoms[0] = 0xFFFFFFFF;
1399 XChangeProperty (xdisplay,
1401 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1402 XA_CARDINAL, 32, PropModeReplace,
1403 (guchar*) atoms, 1);
1404 toplevel->on_all_desktops = TRUE;
1408 XDeleteProperty (xdisplay,
1410 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1413 toplevel->map_serial = NextRequest (xdisplay);
1417 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1419 GdkDisplay *display;
1420 GdkX11Display *display_x11;
1421 GdkToplevelX11 *toplevel;
1422 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1423 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1424 Window xwindow = GDK_WINDOW_XID (window);
1427 if (!already_mapped)
1428 set_initial_hints (window);
1430 if (WINDOW_IS_TOPLEVEL (window))
1432 display = gdk_window_get_display (window);
1433 display_x11 = GDK_X11_DISPLAY (display);
1434 toplevel = _gdk_x11_window_get_toplevel (window);
1436 if (toplevel->user_time != 0 &&
1437 display_x11->user_time != 0 &&
1438 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1439 gdk_x11_window_set_user_time (window, display_x11->user_time);
1442 unset_bg = !window->input_only &&
1443 (window->window_type == GDK_WINDOW_CHILD ||
1444 impl->override_redirect) &&
1445 gdk_window_is_viewable (window);
1448 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1450 XMapWindow (xdisplay, xwindow);
1453 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1455 /* Fullscreen on current monitor is the default, no need to apply this mode
1456 * when mapping a window. This also ensures that the default behavior remains
1457 * consistent with pre-fullscreen mode implementation.
1459 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1460 gdk_x11_window_apply_fullscreen_mode (window);
1464 pre_unmap (GdkWindow *window)
1466 GdkWindow *start_window = NULL;
1468 if (window->input_only)
1471 if (window->window_type == GDK_WINDOW_CHILD)
1472 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1473 else if (window->window_type == GDK_WINDOW_TEMP)
1474 start_window = get_root (window);
1477 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1481 post_unmap (GdkWindow *window)
1483 GdkWindow *start_window = NULL;
1485 if (window->input_only)
1488 if (window->window_type == GDK_WINDOW_CHILD)
1489 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1490 else if (window->window_type == GDK_WINDOW_TEMP)
1491 start_window = get_root (window);
1495 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1497 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1499 GdkRectangle invalid_rect;
1501 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1502 invalid_rect.width = gdk_window_get_width (window);
1503 invalid_rect.height = gdk_window_get_height (window);
1504 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1505 &invalid_rect, TRUE);
1511 gdk_window_x11_hide (GdkWindow *window)
1513 /* We'll get the unmap notify eventually, and handle it then,
1514 * but checking here makes things more consistent if we are
1515 * just doing stuff ourself.
1517 _gdk_x11_window_grab_check_unmap (window,
1518 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1520 /* You can't simply unmap toplevel windows. */
1521 switch (window->window_type)
1523 case GDK_WINDOW_TOPLEVEL:
1524 case GDK_WINDOW_TEMP: /* ? */
1525 gdk_window_withdraw (window);
1528 case GDK_WINDOW_FOREIGN:
1529 case GDK_WINDOW_ROOT:
1530 case GDK_WINDOW_CHILD:
1534 _gdk_window_clear_update_area (window);
1537 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1538 GDK_WINDOW_XID (window));
1539 post_unmap (window);
1543 gdk_window_x11_withdraw (GdkWindow *window)
1545 if (!window->destroyed)
1547 if (GDK_WINDOW_IS_MAPPED (window))
1548 gdk_synthesize_window_state (window,
1550 GDK_WINDOW_STATE_WITHDRAWN);
1552 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1556 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1557 GDK_WINDOW_XID (window), 0);
1559 post_unmap (window);
1564 window_x11_move (GdkWindow *window,
1568 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1570 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1572 _gdk_x11_window_move_resize_child (window,
1574 window->width, window->height);
1578 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1579 GDK_WINDOW_XID (window),
1582 if (impl->override_redirect)
1591 window_x11_resize (GdkWindow *window,
1601 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1603 _gdk_x11_window_move_resize_child (window,
1604 window->x, window->y,
1609 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1611 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1612 GDK_WINDOW_XID (window),
1615 if (impl->override_redirect)
1617 window->width = width;
1618 window->height = height;
1619 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1623 if (width != window->width || height != window->height)
1624 window->resize_count += 1;
1628 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1632 window_x11_move_resize (GdkWindow *window,
1644 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1646 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1647 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1651 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1653 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1654 GDK_WINDOW_XID (window),
1655 x, y, width, height);
1657 if (impl->override_redirect)
1662 window->width = width;
1663 window->height = height;
1665 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1669 if (width != window->width || height != window->height)
1670 window->resize_count += 1;
1676 gdk_window_x11_move_resize (GdkWindow *window,
1683 if (with_move && (width < 0 && height < 0))
1684 window_x11_move (window, x, y);
1688 window_x11_move_resize (window, x, y, width, height);
1690 window_x11_resize (window, width, height);
1695 gdk_window_x11_reparent (GdkWindow *window,
1696 GdkWindow *new_parent,
1700 GdkWindowImplX11 *impl;
1702 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1704 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1705 _gdk_x11_window_tmp_unset_parent_bg (window);
1706 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1707 GDK_WINDOW_XID (window),
1708 GDK_WINDOW_XID (new_parent),
1709 new_parent->abs_x + x, new_parent->abs_y + y);
1710 _gdk_x11_window_tmp_reset_parent_bg (window);
1711 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1713 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1714 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1716 window->parent = new_parent;
1718 /* Switch the window type as appropriate */
1720 switch (GDK_WINDOW_TYPE (new_parent))
1722 case GDK_WINDOW_ROOT:
1723 case GDK_WINDOW_FOREIGN:
1724 /* Reparenting to toplevel */
1726 if (!WINDOW_IS_TOPLEVEL (window) &&
1727 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1729 /* This is also done in common code at a later stage, but we
1730 need it in setup_toplevel, so do it here too */
1731 if (window->toplevel_window_type != -1)
1732 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1733 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1734 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1736 /* Wasn't a toplevel, set up */
1737 setup_toplevel_window (window, new_parent);
1742 case GDK_WINDOW_TOPLEVEL:
1743 case GDK_WINDOW_CHILD:
1744 case GDK_WINDOW_TEMP:
1745 if (WINDOW_IS_TOPLEVEL (window) &&
1748 if (impl->toplevel->focus_window)
1750 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1751 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1754 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1756 g_free (impl->toplevel);
1757 impl->toplevel = NULL;
1765 gdk_window_x11_raise (GdkWindow *window)
1767 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1771 gdk_window_x11_restack_under (GdkWindow *window,
1772 GList *native_siblings /* in requested order, first is bottom-most */)
1778 n_windows = g_list_length (native_siblings) + 1;
1779 windows = g_new (Window, n_windows);
1781 windows[0] = GDK_WINDOW_XID (window);
1782 /* Reverse order, as input order is bottom-most first */
1784 for (l = native_siblings; l != NULL; l = l->next)
1785 windows[i--] = GDK_WINDOW_XID (l->data);
1787 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1793 gdk_window_x11_restack_toplevel (GdkWindow *window,
1797 XWindowChanges changes;
1799 changes.sibling = GDK_WINDOW_XID (sibling);
1800 changes.stack_mode = above ? Above : Below;
1801 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1802 GDK_WINDOW_XID (window),
1803 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1804 CWStackMode | CWSibling, &changes);
1808 gdk_window_x11_lower (GdkWindow *window)
1810 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1814 * gdk_x11_window_move_to_current_desktop:
1815 * @window: (type GdkX11Window): a #GdkWindow
1817 * Moves the window to the correct workspace when running under a
1818 * window manager that supports multiple workspaces, as described
1819 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
1820 * Window Manager Hints</ulink>. Will not do anything if the
1821 * window is already on all workspaces.
1826 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1828 GdkToplevelX11 *toplevel;
1830 g_return_if_fail (GDK_IS_WINDOW (window));
1831 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1833 toplevel = _gdk_x11_window_get_toplevel (window);
1835 if (toplevel->on_all_desktops)
1838 move_to_current_desktop (window);
1842 move_to_current_desktop (GdkWindow *window)
1844 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1845 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
1846 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1847 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
1854 gulong *current_desktop;
1855 GdkDisplay *display;
1857 display = gdk_window_get_display (window);
1859 /* Get current desktop, then set it; this is a race, but not
1860 * one that matters much in practice.
1862 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1863 GDK_WINDOW_XROOTWIN (window),
1864 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1866 False, XA_CARDINAL, &type, &format, &nitems,
1867 &bytes_after, &data);
1869 if (type == XA_CARDINAL)
1871 XClientMessageEvent xclient;
1872 current_desktop = (gulong *)data;
1874 memset (&xclient, 0, sizeof (xclient));
1875 xclient.type = ClientMessage;
1877 xclient.send_event = True;
1878 xclient.window = GDK_WINDOW_XID (window);
1879 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1880 xclient.format = 32;
1882 xclient.data.l[0] = *current_desktop;
1883 xclient.data.l[1] = 1; /* source indication */
1884 xclient.data.l[2] = 0;
1885 xclient.data.l[3] = 0;
1886 xclient.data.l[4] = 0;
1888 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
1889 GDK_WINDOW_XROOTWIN (window),
1891 SubstructureRedirectMask | SubstructureNotifyMask,
1892 (XEvent *)&xclient);
1894 XFree (current_desktop);
1900 gdk_x11_window_focus (GdkWindow *window,
1903 GdkDisplay *display;
1905 g_return_if_fail (GDK_IS_WINDOW (window));
1907 if (GDK_WINDOW_DESTROYED (window) ||
1908 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1911 display = GDK_WINDOW_DISPLAY (window);
1913 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1914 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1916 XClientMessageEvent xclient;
1918 memset (&xclient, 0, sizeof (xclient));
1919 xclient.type = ClientMessage;
1920 xclient.window = GDK_WINDOW_XID (window);
1921 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
1922 "_NET_ACTIVE_WINDOW");
1923 xclient.format = 32;
1924 xclient.data.l[0] = 1; /* requestor type; we're an app */
1925 xclient.data.l[1] = timestamp;
1926 xclient.data.l[2] = None; /* currently active window */
1927 xclient.data.l[3] = 0;
1928 xclient.data.l[4] = 0;
1930 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
1931 SubstructureRedirectMask | SubstructureNotifyMask,
1932 (XEvent *)&xclient);
1936 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
1938 /* There is no way of knowing reliably whether we are viewable;
1939 * so trap errors asynchronously around the XSetInputFocus call
1941 gdk_x11_display_error_trap_push (display);
1942 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
1943 GDK_WINDOW_XID (window),
1946 gdk_x11_display_error_trap_pop_ignored (display);
1951 gdk_x11_window_set_type_hint (GdkWindow *window,
1952 GdkWindowTypeHint hint)
1954 GdkDisplay *display;
1957 if (GDK_WINDOW_DESTROYED (window) ||
1958 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1961 display = gdk_window_get_display (window);
1965 case GDK_WINDOW_TYPE_HINT_DIALOG:
1966 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
1968 case GDK_WINDOW_TYPE_HINT_MENU:
1969 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
1971 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
1972 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
1974 case GDK_WINDOW_TYPE_HINT_UTILITY:
1975 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
1977 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
1978 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
1980 case GDK_WINDOW_TYPE_HINT_DOCK:
1981 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
1983 case GDK_WINDOW_TYPE_HINT_DESKTOP:
1984 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
1986 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
1987 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
1989 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
1990 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
1992 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
1993 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
1995 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
1996 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
1998 case GDK_WINDOW_TYPE_HINT_COMBO:
1999 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2001 case GDK_WINDOW_TYPE_HINT_DND:
2002 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2005 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2007 case GDK_WINDOW_TYPE_HINT_NORMAL:
2008 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2012 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2013 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2014 XA_ATOM, 32, PropModeReplace,
2015 (guchar *)&atom, 1);
2018 static GdkWindowTypeHint
2019 gdk_x11_window_get_type_hint (GdkWindow *window)
2021 GdkDisplay *display;
2022 GdkWindowTypeHint type;
2025 gulong nitems_return;
2026 gulong bytes_after_return;
2027 guchar *data = NULL;
2029 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2031 if (GDK_WINDOW_DESTROYED (window) ||
2032 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2033 return GDK_WINDOW_TYPE_HINT_NORMAL;
2035 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2037 display = gdk_window_get_display (window);
2039 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2040 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2041 0, G_MAXLONG, False, XA_ATOM, &type_return,
2042 &format_return, &nitems_return, &bytes_after_return,
2045 if ((type_return == XA_ATOM) && (format_return == 32) &&
2046 (data) && (nitems_return == 1))
2048 Atom atom = *(Atom*)data;
2050 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2051 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2052 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2053 type = GDK_WINDOW_TYPE_HINT_MENU;
2054 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2055 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2056 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2057 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2058 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2059 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2060 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2061 type = GDK_WINDOW_TYPE_HINT_DOCK;
2062 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2063 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2064 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2065 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2066 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2067 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2068 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2069 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2070 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2071 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2072 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2073 type = GDK_WINDOW_TYPE_HINT_COMBO;
2074 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2075 type = GDK_WINDOW_TYPE_HINT_DND;
2078 if (type_return != None && data != NULL)
2086 gdk_wmspec_change_state (gboolean add,
2091 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2092 XClientMessageEvent xclient;
2094 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2095 #define _NET_WM_STATE_ADD 1 /* add/set property */
2096 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2098 memset (&xclient, 0, sizeof (xclient));
2099 xclient.type = ClientMessage;
2100 xclient.window = GDK_WINDOW_XID (window);
2101 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2102 xclient.format = 32;
2103 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2104 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2105 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2106 xclient.data.l[3] = 1; /* source indication */
2107 xclient.data.l[4] = 0;
2109 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2110 SubstructureRedirectMask | SubstructureNotifyMask,
2111 (XEvent *)&xclient);
2115 gdk_x11_window_set_modal_hint (GdkWindow *window,
2118 if (GDK_WINDOW_DESTROYED (window) ||
2119 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2122 window->modal_hint = modal;
2124 if (GDK_WINDOW_IS_MAPPED (window))
2125 gdk_wmspec_change_state (modal, window,
2126 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2131 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2132 gboolean skips_taskbar)
2134 GdkToplevelX11 *toplevel;
2136 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2138 if (GDK_WINDOW_DESTROYED (window) ||
2139 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2142 toplevel = _gdk_x11_window_get_toplevel (window);
2143 toplevel->skip_taskbar_hint = skips_taskbar;
2145 if (GDK_WINDOW_IS_MAPPED (window))
2146 gdk_wmspec_change_state (skips_taskbar, window,
2147 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2152 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2153 gboolean skips_pager)
2155 GdkToplevelX11 *toplevel;
2157 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2159 if (GDK_WINDOW_DESTROYED (window) ||
2160 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2163 toplevel = _gdk_x11_window_get_toplevel (window);
2164 toplevel->skip_pager_hint = skips_pager;
2166 if (GDK_WINDOW_IS_MAPPED (window))
2167 gdk_wmspec_change_state (skips_pager, window,
2168 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2173 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2176 GdkToplevelX11 *toplevel;
2178 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2180 if (GDK_WINDOW_DESTROYED (window) ||
2181 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2184 toplevel = _gdk_x11_window_get_toplevel (window);
2185 toplevel->urgency_hint = urgent;
2187 update_wm_hints (window, FALSE);
2191 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2192 const GdkGeometry *geometry,
2193 GdkWindowHints geom_mask)
2195 XSizeHints size_hints;
2197 if (GDK_WINDOW_DESTROYED (window) ||
2198 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2201 size_hints.flags = 0;
2203 if (geom_mask & GDK_HINT_POS)
2205 size_hints.flags |= PPosition;
2206 /* We need to initialize the following obsolete fields because KWM
2207 * apparently uses these fields if they are non-zero.
2214 if (geom_mask & GDK_HINT_USER_POS)
2216 size_hints.flags |= USPosition;
2219 if (geom_mask & GDK_HINT_USER_SIZE)
2221 size_hints.flags |= USSize;
2224 if (geom_mask & GDK_HINT_MIN_SIZE)
2226 size_hints.flags |= PMinSize;
2227 size_hints.min_width = geometry->min_width;
2228 size_hints.min_height = geometry->min_height;
2231 if (geom_mask & GDK_HINT_MAX_SIZE)
2233 size_hints.flags |= PMaxSize;
2234 size_hints.max_width = MAX (geometry->max_width, 1);
2235 size_hints.max_height = MAX (geometry->max_height, 1);
2238 if (geom_mask & GDK_HINT_BASE_SIZE)
2240 size_hints.flags |= PBaseSize;
2241 size_hints.base_width = geometry->base_width;
2242 size_hints.base_height = geometry->base_height;
2245 if (geom_mask & GDK_HINT_RESIZE_INC)
2247 size_hints.flags |= PResizeInc;
2248 size_hints.width_inc = geometry->width_inc;
2249 size_hints.height_inc = geometry->height_inc;
2252 if (geom_mask & GDK_HINT_ASPECT)
2254 size_hints.flags |= PAspect;
2255 if (geometry->min_aspect <= 1)
2257 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2258 size_hints.min_aspect.y = 65536;
2262 size_hints.min_aspect.x = 65536;
2263 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2265 if (geometry->max_aspect <= 1)
2267 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2268 size_hints.max_aspect.y = 65536;
2272 size_hints.max_aspect.x = 65536;
2273 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2277 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2279 size_hints.flags |= PWinGravity;
2280 size_hints.win_gravity = geometry->win_gravity;
2283 /* FIXME: Would it be better to delete this property if
2284 * geom_mask == 0? It would save space on the server
2286 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2287 GDK_WINDOW_XID (window),
2292 gdk_window_get_geometry_hints (GdkWindow *window,
2293 GdkGeometry *geometry,
2294 GdkWindowHints *geom_mask)
2296 XSizeHints *size_hints;
2297 glong junk_supplied_mask = 0;
2299 g_return_if_fail (GDK_IS_WINDOW (window));
2300 g_return_if_fail (geometry != NULL);
2301 g_return_if_fail (geom_mask != NULL);
2305 if (GDK_WINDOW_DESTROYED (window) ||
2306 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2309 size_hints = XAllocSizeHints ();
2313 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2314 GDK_WINDOW_XID (window),
2316 &junk_supplied_mask))
2317 size_hints->flags = 0;
2319 if (size_hints->flags & PMinSize)
2321 *geom_mask |= GDK_HINT_MIN_SIZE;
2322 geometry->min_width = size_hints->min_width;
2323 geometry->min_height = size_hints->min_height;
2326 if (size_hints->flags & PMaxSize)
2328 *geom_mask |= GDK_HINT_MAX_SIZE;
2329 geometry->max_width = MAX (size_hints->max_width, 1);
2330 geometry->max_height = MAX (size_hints->max_height, 1);
2333 if (size_hints->flags & PResizeInc)
2335 *geom_mask |= GDK_HINT_RESIZE_INC;
2336 geometry->width_inc = size_hints->width_inc;
2337 geometry->height_inc = size_hints->height_inc;
2340 if (size_hints->flags & PAspect)
2342 *geom_mask |= GDK_HINT_ASPECT;
2344 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2345 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2348 if (size_hints->flags & PWinGravity)
2350 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2351 geometry->win_gravity = size_hints->win_gravity;
2358 utf8_is_latin1 (const gchar *str)
2360 const char *p = str;
2364 gunichar ch = g_utf8_get_char (p);
2369 p = g_utf8_next_char (p);
2375 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2376 * convertable to STRING, otherwise, set it as compound text
2379 set_text_property (GdkDisplay *display,
2382 const gchar *utf8_str)
2384 gchar *prop_text = NULL;
2388 gboolean is_compound_text;
2390 if (utf8_is_latin1 (utf8_str))
2392 prop_type = XA_STRING;
2393 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2394 prop_length = prop_text ? strlen (prop_text) : 0;
2396 is_compound_text = FALSE;
2402 gdk_x11_display_utf8_to_compound_text (display,
2403 utf8_str, &gdk_type, &prop_format,
2404 (guchar **)&prop_text, &prop_length);
2405 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2406 is_compound_text = TRUE;
2411 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2414 prop_type, prop_format,
2415 PropModeReplace, (guchar *)prop_text,
2418 if (is_compound_text)
2419 gdk_x11_free_compound_text ((guchar *)prop_text);
2425 /* Set WM_NAME and _NET_WM_NAME
2428 set_wm_name (GdkDisplay *display,
2432 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2433 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2434 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2435 PropModeReplace, (guchar *)name, strlen (name));
2437 set_text_property (display, xwindow,
2438 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2443 gdk_x11_window_set_title (GdkWindow *window,
2446 GdkDisplay *display;
2450 g_return_if_fail (title != NULL);
2452 if (GDK_WINDOW_DESTROYED (window) ||
2453 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2456 display = gdk_window_get_display (window);
2457 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2458 xwindow = GDK_WINDOW_XID (window);
2460 set_wm_name (display, xwindow, title);
2462 if (!gdk_window_icon_name_set (window))
2464 XChangeProperty (xdisplay, xwindow,
2465 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2466 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2467 PropModeReplace, (guchar *)title, strlen (title));
2469 set_text_property (display, xwindow,
2470 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2476 gdk_x11_window_set_role (GdkWindow *window,
2479 GdkDisplay *display;
2481 display = gdk_window_get_display (window);
2483 if (GDK_WINDOW_DESTROYED (window) ||
2484 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2488 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2489 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2490 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2492 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2493 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2497 gdk_x11_window_set_startup_id (GdkWindow *window,
2498 const gchar *startup_id)
2500 GdkDisplay *display;
2502 g_return_if_fail (GDK_IS_WINDOW (window));
2504 display = gdk_window_get_display (window);
2506 if (GDK_WINDOW_DESTROYED (window) ||
2507 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2511 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2512 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2513 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2514 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2516 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2517 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2521 gdk_x11_window_set_transient_for (GdkWindow *window,
2524 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2525 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2526 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2527 GDK_WINDOW_XID (window),
2528 GDK_WINDOW_XID (parent));
2532 gdk_window_x11_set_back_color (GdkWindow *window,
2538 GdkVisual *visual = gdk_window_get_visual (window);
2540 /* I suppose we could handle these, but that'd require fiddling with
2541 * xrender formats... */
2545 switch (visual->type)
2547 case GDK_VISUAL_DIRECT_COLOR:
2548 case GDK_VISUAL_TRUE_COLOR:
2550 /* If bits not used for color are used for something other than padding,
2551 * it's likely alpha, so we set them to 1s.
2553 guint padding, pixel;
2555 /* Shifting by >= width-of-type isn't defined in C */
2556 if (visual->depth >= 32)
2559 padding = ((~(guint32)0)) << visual->depth;
2561 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2563 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2564 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2565 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2567 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2568 GDK_WINDOW_XID (window), pixel);
2572 /* These require fiddling with the colormap, and as they're essentially unused
2573 * we're just gonna skip them for now.
2575 case GDK_VISUAL_PSEUDO_COLOR:
2576 case GDK_VISUAL_GRAYSCALE:
2577 case GDK_VISUAL_STATIC_GRAY:
2578 case GDK_VISUAL_STATIC_COLOR:
2587 matrix_is_identity (cairo_matrix_t *matrix)
2589 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2590 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2591 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2595 gdk_window_x11_set_background (GdkWindow *window,
2596 cairo_pattern_t *pattern)
2599 cairo_surface_t *surface;
2600 cairo_matrix_t matrix;
2602 if (GDK_WINDOW_DESTROYED (window))
2605 if (pattern == NULL)
2609 /* X throws BadMatch if the parent has a different visual when
2610 * using ParentRelative */
2611 parent = gdk_window_get_parent (window);
2612 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2613 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2614 GDK_WINDOW_XID (window), ParentRelative);
2616 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2617 GDK_WINDOW_XID (window), None);
2621 switch (cairo_pattern_get_type (pattern))
2623 case CAIRO_PATTERN_TYPE_SOLID:
2624 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2625 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2628 case CAIRO_PATTERN_TYPE_SURFACE:
2629 cairo_pattern_get_matrix (pattern, &matrix);
2630 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2631 matrix_is_identity (&matrix) &&
2632 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2633 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2634 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2638 cairo_surface_get_device_offset (surface, &x, &y);
2639 /* XXX: This still bombs for non-pixmaps, but there's no way to
2640 * detect we're not a pixmap in Cairo... */
2641 if (x == 0.0 && y == 0.0)
2643 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2644 GDK_WINDOW_XID (window),
2645 cairo_xlib_surface_get_drawable (surface));
2650 case CAIRO_PATTERN_TYPE_LINEAR:
2651 case CAIRO_PATTERN_TYPE_RADIAL:
2653 /* fallback: just use black */
2657 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2658 GDK_WINDOW_XID (window), None);
2662 gdk_window_x11_set_device_cursor (GdkWindow *window,
2666 GdkWindowImplX11 *impl;
2668 g_return_if_fail (GDK_IS_WINDOW (window));
2669 g_return_if_fail (GDK_IS_DEVICE (device));
2671 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2674 g_hash_table_remove (impl->device_cursor, device);
2677 _gdk_x11_cursor_update_theme (cursor);
2678 g_hash_table_replace (impl->device_cursor,
2679 device, g_object_ref (cursor));
2682 if (!GDK_WINDOW_DESTROYED (window))
2683 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2687 _gdk_x11_window_get_cursor (GdkWindow *window)
2689 GdkWindowImplX11 *impl;
2691 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2693 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2695 return impl->cursor;
2699 gdk_window_x11_get_geometry (GdkWindow *window,
2710 guint tborder_width;
2713 if (!GDK_WINDOW_DESTROYED (window))
2715 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2716 GDK_WINDOW_XID (window),
2717 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2731 gdk_window_x11_get_root_coords (GdkWindow *window,
2742 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2743 GDK_WINDOW_XID (window),
2744 GDK_WINDOW_XROOTWIN (window),
2757 gdk_x11_window_get_root_origin (GdkWindow *window,
2763 gdk_window_get_frame_extents (window, &rect);
2773 gdk_x11_window_get_frame_extents (GdkWindow *window,
2776 GdkDisplay *display;
2777 GdkWindowImplX11 *impl;
2788 gulong nitems_return;
2789 gulong bytes_after_return;
2792 guint ww, wh, wb, wd;
2794 gboolean got_frame_extents = FALSE;
2796 g_return_if_fail (rect != NULL);
2803 while (window->parent && (window->parent)->parent)
2804 window = window->parent;
2806 /* Refine our fallback answer a bit using local information */
2807 rect->x = window->x;
2808 rect->y = window->y;
2809 rect->width = window->width;
2810 rect->height = window->height;
2812 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2813 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2819 display = gdk_window_get_display (window);
2821 gdk_x11_display_error_trap_push (display);
2823 xwindow = GDK_WINDOW_XID (window);
2825 /* first try: use _NET_FRAME_EXTENTS */
2826 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2827 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
2828 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2829 gdk_x11_get_xatom_by_name_for_display (display,
2830 "_NET_FRAME_EXTENTS"),
2831 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2832 &format_return, &nitems_return, &bytes_after_return,
2836 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2837 (nitems_return == 4) && (data))
2839 gulong *ldata = (gulong *) data;
2840 got_frame_extents = TRUE;
2842 /* try to get the real client window geometry */
2843 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2844 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2845 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2846 xwindow, root, 0, 0, &wx, &wy, &child))
2854 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2855 rect->x -= ldata[0];
2856 rect->y -= ldata[2];
2857 rect->width += ldata[0] + ldata[1];
2858 rect->height += ldata[2] + ldata[3];
2865 if (got_frame_extents)
2868 /* no frame extents property available, which means we either have a WM that
2869 is not EWMH compliant or is broken - try fallback and walk up the window
2870 tree to get our window's parent which hopefully is the window frame */
2872 /* use NETWM_VIRTUAL_ROOTS if available */
2873 root = GDK_WINDOW_XROOTWIN (window);
2875 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2876 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
2877 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
2878 gdk_x11_get_xatom_by_name_for_display (display,
2879 "_NET_VIRTUAL_ROOTS"),
2880 0, G_MAXLONG, False, XA_WINDOW, &type_return,
2881 &format_return, &nitems_return, &bytes_after_return,
2885 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
2887 nvroots = nitems_return;
2888 vroots = (Window *)data;
2892 xparent = GDK_WINDOW_XID (window);
2898 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
2900 &children, &nchildren))
2906 /* check virtual roots */
2907 for (i = 0; i < nvroots; i++)
2909 if (xparent == vroots[i])
2916 while (xparent != root);
2918 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2919 &root, &wx, &wy, &ww, &wh, &wb, &wd))
2931 gdk_x11_display_error_trap_pop_ignored (display);
2935 gdk_window_x11_get_device_state (GdkWindow *window,
2939 GdkModifierType *mask)
2943 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
2945 if (GDK_WINDOW_DESTROYED (window))
2948 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
2952 return child != NULL;
2956 gdk_window_x11_get_events (GdkWindow *window)
2958 XWindowAttributes attrs;
2959 GdkEventMask event_mask;
2960 GdkEventMask filtered;
2962 if (GDK_WINDOW_DESTROYED (window))
2966 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
2967 GDK_WINDOW_XID (window),
2969 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
2970 /* if property change was filtered out before, keep it filtered out */
2971 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
2972 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
2978 gdk_window_x11_set_events (GdkWindow *window,
2979 GdkEventMask event_mask)
2981 long xevent_mask = 0;
2983 if (!GDK_WINDOW_DESTROYED (window))
2985 GdkX11Display *display_x11;
2987 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
2988 xevent_mask = StructureNotifyMask | PropertyChangeMask;
2990 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
2991 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
2992 GDK_WINDOW_XID (window), event_mask,
2998 do_shape_combine_region (GdkWindow *window,
2999 const cairo_region_t *shape_region,
3004 if (GDK_WINDOW_DESTROYED (window))
3007 if (shape_region == NULL)
3009 /* Use NULL mask to unset the shape */
3010 if (shape == ShapeBounding
3011 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3012 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3014 if (shape == ShapeBounding)
3016 _gdk_x11_window_tmp_unset_parent_bg (window);
3017 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3019 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3020 GDK_WINDOW_XID (window),
3025 if (shape == ShapeBounding)
3027 _gdk_x11_window_tmp_reset_parent_bg (window);
3028 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3034 if (shape == ShapeBounding
3035 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3036 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3039 XRectangle *xrects = NULL;
3041 _gdk_x11_region_get_xrectangles (shape_region,
3045 if (shape == ShapeBounding)
3047 _gdk_x11_window_tmp_unset_parent_bg (window);
3048 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3050 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3051 GDK_WINDOW_XID (window),
3058 if (shape == ShapeBounding)
3060 _gdk_x11_window_tmp_reset_parent_bg (window);
3061 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3069 gdk_window_x11_shape_combine_region (GdkWindow *window,
3070 const cairo_region_t *shape_region,
3074 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3078 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3079 const cairo_region_t *shape_region,
3084 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3090 gdk_x11_window_set_override_redirect (GdkWindow *window,
3091 gboolean override_redirect)
3093 XSetWindowAttributes attr;
3095 if (!GDK_WINDOW_DESTROYED (window) &&
3096 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3098 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3100 attr.override_redirect = (override_redirect? True : False);
3101 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3102 GDK_WINDOW_XID (window),
3106 impl->override_redirect = attr.override_redirect;
3111 gdk_x11_window_set_accept_focus (GdkWindow *window,
3112 gboolean accept_focus)
3114 accept_focus = accept_focus != FALSE;
3116 if (window->accept_focus != accept_focus)
3118 window->accept_focus = accept_focus;
3120 if (!GDK_WINDOW_DESTROYED (window) &&
3121 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3122 update_wm_hints (window, FALSE);
3127 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3128 gboolean focus_on_map)
3130 focus_on_map = focus_on_map != FALSE;
3132 if (window->focus_on_map != focus_on_map)
3134 window->focus_on_map = focus_on_map;
3136 if ((!GDK_WINDOW_DESTROYED (window)) &&
3137 (!window->focus_on_map) &&
3138 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3139 gdk_x11_window_set_user_time (window, 0);
3144 * gdk_x11_window_set_user_time:
3145 * @window: (type GdkX11Window): A toplevel #GdkWindow
3146 * @timestamp: An XServer timestamp to which the property should be set
3148 * The application can use this call to update the _NET_WM_USER_TIME
3149 * property on a toplevel window. This property stores an Xserver
3150 * time which represents the time of the last user input event
3151 * received for this window. This property may be used by the window
3152 * manager to alter the focus, stacking, and/or placement behavior of
3153 * windows when they are mapped depending on whether the new window
3154 * was created by a user action or is a "pop-up" window activated by a
3155 * timer or some other event.
3157 * Note that this property is automatically updated by GDK, so this
3158 * function should only be used by applications which handle input
3159 * events bypassing GDK.
3164 gdk_x11_window_set_user_time (GdkWindow *window,
3167 GdkDisplay *display;
3168 GdkX11Display *display_x11;
3169 GdkToplevelX11 *toplevel;
3170 glong timestamp_long = (glong)timestamp;
3173 if (GDK_WINDOW_DESTROYED (window) ||
3174 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3177 display = gdk_window_get_display (window);
3178 display_x11 = GDK_X11_DISPLAY (display);
3179 toplevel = _gdk_x11_window_get_toplevel (window);
3183 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3187 if (toplevel->focus_window != None &&
3188 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3189 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3190 xid = toplevel->focus_window;
3192 xid = GDK_WINDOW_XID (window);
3194 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3195 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3196 XA_CARDINAL, 32, PropModeReplace,
3197 (guchar *)×tamp_long, 1);
3199 if (timestamp_long != GDK_CURRENT_TIME &&
3200 (display_x11->user_time == GDK_CURRENT_TIME ||
3201 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3202 display_x11->user_time = timestamp_long;
3205 toplevel->user_time = timestamp_long;
3209 * gdk_x11_window_set_utf8_property:
3210 * @window: (type GdkX11Window): a #GdkWindow
3211 * @name: Property name, will be interned as an X atom
3212 * @value: (allow-none): Property value, or %NULL to delete
3214 * This function modifies or removes an arbitrary X11 window
3215 * property of type UTF8_STRING. If the given @window is
3216 * not a toplevel window, it is ignored.
3221 gdk_x11_window_set_utf8_property (GdkWindow *window,
3225 GdkDisplay *display;
3227 if (!WINDOW_IS_TOPLEVEL (window))
3230 display = gdk_window_get_display (window);
3234 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3235 GDK_WINDOW_XID (window),
3236 gdk_x11_get_xatom_by_name_for_display (display, name),
3237 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3238 PropModeReplace, (guchar *)value, strlen (value));
3242 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3243 GDK_WINDOW_XID (window),
3244 gdk_x11_get_xatom_by_name_for_display (display, name));
3249 * gdk_x11_window_set_hide_titlebar_when_maximized:
3250 * @window: (type GdkX11Window): a #GdkWindow
3251 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3254 * Set a hint for the window manager, requesting that the titlebar
3255 * should be hidden when the window is maximized.
3257 * Note that this property is automatically updated by GTK+, so this
3258 * function should only be used by applications which do not use GTK+
3259 * to create toplevel windows.
3264 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3265 gboolean hide_titlebar_when_maximized)
3267 GdkDisplay *display;
3269 if (!WINDOW_IS_TOPLEVEL (window))
3272 display = gdk_window_get_display (window);
3274 if (hide_titlebar_when_maximized)
3277 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3278 GDK_WINDOW_XID (window),
3279 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3281 PropModeReplace, (guchar *)&hide, 1);
3285 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3286 GDK_WINDOW_XID (window),
3287 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3292 * gdk_x11_window_set_theme_variant:
3293 * @window: (type GdkX11Window): a #GdkWindow
3294 * @variant: the theme variant to export
3296 * GTK+ applications can request a dark theme variant. In order to
3297 * make other applications - namely window managers using GTK+ for
3298 * themeing - aware of this choice, GTK+ uses this function to
3299 * export the requested theme variant as _GTK_THEME_VARIANT property
3300 * on toplevel windows.
3302 * Note that this property is automatically updated by GTK+, so this
3303 * function should only be used by applications which do not use GTK+
3304 * to create toplevel windows.
3309 gdk_x11_window_set_theme_variant (GdkWindow *window,
3312 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3315 #define GDK_SELECTION_MAX_SIZE(display) \
3317 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3318 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3319 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3322 gdk_window_update_icon (GdkWindow *window,
3325 GdkToplevelX11 *toplevel;
3326 GdkPixbuf *best_icon;
3330 toplevel = _gdk_x11_window_get_toplevel (window);
3332 if (toplevel->icon_pixmap != NULL)
3334 cairo_surface_destroy (toplevel->icon_pixmap);
3335 toplevel->icon_pixmap = NULL;
3338 if (toplevel->icon_mask != NULL)
3340 cairo_surface_destroy (toplevel->icon_mask);
3341 toplevel->icon_mask = NULL;
3344 #define IDEAL_SIZE 48
3346 best_size = G_MAXINT;
3348 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3350 GdkPixbuf *pixbuf = tmp_list->data;
3353 /* average width and height - if someone passes in a rectangular
3354 * icon they deserve what they get.
3356 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3359 if (best_icon == NULL)
3366 /* icon is better if it's 32 pixels or larger, and closer to
3367 * the ideal size than the current best.
3370 (ABS (best_size - IDEAL_SIZE) <
3371 ABS (this - IDEAL_SIZE)))
3381 int width = gdk_pixbuf_get_width (best_icon);
3382 int height = gdk_pixbuf_get_height (best_icon);
3385 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3389 cr = cairo_create (toplevel->icon_pixmap);
3390 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3391 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3392 if (gdk_pixbuf_get_has_alpha (best_icon))
3394 /* Saturate the image, so it has bilevel alpha */
3395 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3397 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3399 cairo_pop_group_to_source (cr);
3404 if (gdk_pixbuf_get_has_alpha (best_icon))
3406 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3410 cr = cairo_create (toplevel->icon_mask);
3411 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3412 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3418 update_wm_hints (window, FALSE);
3422 gdk_x11_window_set_icon_list (GdkWindow *window,
3431 gint width, height, stride;
3434 GdkDisplay *display;
3437 if (GDK_WINDOW_DESTROYED (window) ||
3438 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3441 display = gdk_window_get_display (window);
3449 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3451 width = gdk_pixbuf_get_width (pixbuf);
3452 height = gdk_pixbuf_get_height (pixbuf);
3454 /* silently ignore overlarge icons */
3455 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3457 g_warning ("gdk_window_set_icon_list: icons too large");
3462 size += 2 + width * height;
3464 l = g_list_next (l);
3467 data = g_malloc (size * sizeof (gulong));
3475 width = gdk_pixbuf_get_width (pixbuf);
3476 height = gdk_pixbuf_get_height (pixbuf);
3477 stride = gdk_pixbuf_get_rowstride (pixbuf);
3478 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3483 pixels = gdk_pixbuf_get_pixels (pixbuf);
3485 for (y = 0; y < height; y++)
3487 for (x = 0; x < width; x++)
3491 r = pixels[y*stride + x*n_channels + 0];
3492 g = pixels[y*stride + x*n_channels + 1];
3493 b = pixels[y*stride + x*n_channels + 2];
3494 if (n_channels >= 4)
3495 a = pixels[y*stride + x*n_channels + 3];
3499 *p++ = a << 24 | r << 16 | g << 8 | b ;
3503 l = g_list_next (l);
3509 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3510 GDK_WINDOW_XID (window),
3511 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3514 (guchar*) data, size);
3518 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3519 GDK_WINDOW_XID (window),
3520 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3525 gdk_window_update_icon (window, pixbufs);
3529 gdk_window_icon_name_set (GdkWindow *window)
3531 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3532 g_quark_from_static_string ("gdk-icon-name-set")));
3536 gdk_x11_window_set_icon_name (GdkWindow *window,
3539 GdkDisplay *display;
3541 if (GDK_WINDOW_DESTROYED (window) ||
3542 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3545 display = gdk_window_get_display (window);
3547 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3548 GUINT_TO_POINTER (name != NULL));
3552 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3553 GDK_WINDOW_XID (window),
3554 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3555 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3556 PropModeReplace, (guchar *)name, strlen (name));
3558 set_text_property (display, GDK_WINDOW_XID (window),
3559 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3564 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3565 GDK_WINDOW_XID (window),
3566 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3567 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3568 GDK_WINDOW_XID (window),
3569 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3574 gdk_x11_window_iconify (GdkWindow *window)
3576 if (GDK_WINDOW_DESTROYED (window) ||
3577 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3580 if (GDK_WINDOW_IS_MAPPED (window))
3582 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3583 GDK_WINDOW_XID (window),
3584 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3588 /* Flip our client side flag, the real work happens on map. */
3589 gdk_synthesize_window_state (window,
3591 GDK_WINDOW_STATE_ICONIFIED);
3592 gdk_wmspec_change_state (TRUE, window,
3593 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3599 gdk_x11_window_deiconify (GdkWindow *window)
3601 if (GDK_WINDOW_DESTROYED (window) ||
3602 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3605 if (GDK_WINDOW_IS_MAPPED (window))
3607 gdk_window_show (window);
3608 gdk_wmspec_change_state (FALSE, window,
3609 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3614 /* Flip our client side flag, the real work happens on map. */
3615 gdk_synthesize_window_state (window,
3616 GDK_WINDOW_STATE_ICONIFIED,
3618 gdk_wmspec_change_state (FALSE, window,
3619 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3625 gdk_x11_window_stick (GdkWindow *window)
3627 if (GDK_WINDOW_DESTROYED (window) ||
3628 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3631 if (GDK_WINDOW_IS_MAPPED (window))
3633 /* "stick" means stick to all desktops _and_ do not scroll with the
3634 * viewport. i.e. glue to the monitor glass in all cases.
3637 XClientMessageEvent xclient;
3639 /* Request stick during viewport scroll */
3640 gdk_wmspec_change_state (TRUE, window,
3641 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3644 /* Request desktop 0xFFFFFFFF */
3645 memset (&xclient, 0, sizeof (xclient));
3646 xclient.type = ClientMessage;
3647 xclient.window = GDK_WINDOW_XID (window);
3648 xclient.display = GDK_WINDOW_XDISPLAY (window);
3649 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3651 xclient.format = 32;
3653 xclient.data.l[0] = 0xFFFFFFFF;
3654 xclient.data.l[1] = 0;
3655 xclient.data.l[2] = 0;
3656 xclient.data.l[3] = 0;
3657 xclient.data.l[4] = 0;
3659 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3660 SubstructureRedirectMask | SubstructureNotifyMask,
3661 (XEvent *)&xclient);
3665 /* Flip our client side flag, the real work happens on map. */
3666 gdk_synthesize_window_state (window,
3668 GDK_WINDOW_STATE_STICKY);
3673 gdk_x11_window_unstick (GdkWindow *window)
3675 if (GDK_WINDOW_DESTROYED (window) ||
3676 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3679 if (GDK_WINDOW_IS_MAPPED (window))
3681 /* Request unstick from viewport */
3682 gdk_wmspec_change_state (FALSE, window,
3683 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3686 move_to_current_desktop (window);
3690 /* Flip our client side flag, the real work happens on map. */
3691 gdk_synthesize_window_state (window,
3692 GDK_WINDOW_STATE_STICKY,
3699 gdk_x11_window_maximize (GdkWindow *window)
3701 if (GDK_WINDOW_DESTROYED (window) ||
3702 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3705 if (GDK_WINDOW_IS_MAPPED (window))
3706 gdk_wmspec_change_state (TRUE, window,
3707 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3708 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3710 gdk_synthesize_window_state (window,
3712 GDK_WINDOW_STATE_MAXIMIZED);
3716 gdk_x11_window_unmaximize (GdkWindow *window)
3718 if (GDK_WINDOW_DESTROYED (window) ||
3719 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3722 if (GDK_WINDOW_IS_MAPPED (window))
3723 gdk_wmspec_change_state (FALSE, window,
3724 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3725 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3727 gdk_synthesize_window_state (window,
3728 GDK_WINDOW_STATE_MAXIMIZED,
3733 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3735 if (GDK_WINDOW_DESTROYED (window) ||
3736 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3739 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3740 * to which monitors so span across when the window is fullscreen, but it's
3741 * not a state in itself so this would have no effect if the window is not
3745 if (GDK_WINDOW_IS_MAPPED (window))
3747 XClientMessageEvent xclient;
3748 gint gdk_monitors[4];
3751 memset (&xclient, 0, sizeof (xclient));
3752 xclient.type = ClientMessage;
3753 xclient.window = GDK_WINDOW_XID (window);
3754 xclient.display = GDK_WINDOW_XDISPLAY (window);
3755 xclient.format = 32;
3757 switch (window->fullscreen_mode)
3759 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3761 /* FIXME: This is not part of the EWMH spec!
3763 * There is no documented mechanism to remove the property
3764 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3765 * invalid, largest possible value.
3767 * When given values larger than actual possible monitor values, most
3768 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3769 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3772 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3774 * Note, this (non documented) mechanism is unlikely to be an issue
3775 * as it's used only for transitionning back from "all monitors" to
3776 * "current monitor" mode.
3778 * Applications who don't change the default mode won't trigger this
3781 for (i = 0; i < 4; ++i)
3782 xclient.data.l[i] = G_MAXLONG;
3786 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3788 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3793 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3794 for (i = 0; i < 4; ++i)
3796 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3798 /* Sanity check, if XINERAMA is not available, we could have invalid
3799 * negative values for the XINERAMA indices.
3801 if (xclient.data.l[i] < 0)
3803 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3810 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3811 window->fullscreen_mode);
3815 /* Send fullscreen monitors client message */
3816 xclient.data.l[4] = 1; /* source indication */
3817 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3818 "_NET_WM_FULLSCREEN_MONITORS");
3819 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3820 SubstructureRedirectMask | SubstructureNotifyMask,
3821 (XEvent *)&xclient);
3826 gdk_x11_window_fullscreen (GdkWindow *window)
3828 if (GDK_WINDOW_DESTROYED (window) ||
3829 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3832 if (GDK_WINDOW_IS_MAPPED (window))
3834 gdk_wmspec_change_state (TRUE, window,
3835 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3837 /* Actual XRandR layout may have change since we computed the fullscreen
3838 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
3840 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
3841 gdk_x11_window_apply_fullscreen_mode (window);
3844 gdk_synthesize_window_state (window,
3846 GDK_WINDOW_STATE_FULLSCREEN);
3850 gdk_x11_window_unfullscreen (GdkWindow *window)
3852 if (GDK_WINDOW_DESTROYED (window) ||
3853 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3856 if (GDK_WINDOW_IS_MAPPED (window))
3857 gdk_wmspec_change_state (FALSE, window,
3858 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3862 gdk_synthesize_window_state (window,
3863 GDK_WINDOW_STATE_FULLSCREEN,
3868 gdk_x11_window_set_keep_above (GdkWindow *window,
3871 g_return_if_fail (GDK_IS_WINDOW (window));
3873 if (GDK_WINDOW_DESTROYED (window) ||
3874 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3877 if (GDK_WINDOW_IS_MAPPED (window))
3880 gdk_wmspec_change_state (FALSE, window,
3881 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3883 gdk_wmspec_change_state (setting, window,
3884 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3888 gdk_synthesize_window_state (window,
3889 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3890 setting ? GDK_WINDOW_STATE_ABOVE : 0);
3894 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
3896 g_return_if_fail (GDK_IS_WINDOW (window));
3898 if (GDK_WINDOW_DESTROYED (window) ||
3899 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3902 if (GDK_WINDOW_IS_MAPPED (window))
3905 gdk_wmspec_change_state (FALSE, window,
3906 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3908 gdk_wmspec_change_state (setting, window,
3909 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3913 gdk_synthesize_window_state (window,
3914 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3915 setting ? GDK_WINDOW_STATE_BELOW : 0);
3919 gdk_x11_window_get_group (GdkWindow *window)
3921 GdkToplevelX11 *toplevel;
3923 if (GDK_WINDOW_DESTROYED (window) ||
3924 !WINDOW_IS_TOPLEVEL (window))
3927 toplevel = _gdk_x11_window_get_toplevel (window);
3929 return toplevel->group_leader;
3933 gdk_x11_window_set_group (GdkWindow *window,
3936 GdkToplevelX11 *toplevel;
3938 g_return_if_fail (GDK_IS_WINDOW (window));
3939 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
3940 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
3942 if (GDK_WINDOW_DESTROYED (window) ||
3943 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
3944 !WINDOW_IS_TOPLEVEL (window))
3947 toplevel = _gdk_x11_window_get_toplevel (window);
3950 leader = gdk_display_get_default_group (gdk_window_get_display (window));
3952 if (toplevel->group_leader != leader)
3954 if (toplevel->group_leader)
3955 g_object_unref (toplevel->group_leader);
3956 toplevel->group_leader = g_object_ref (leader);
3957 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
3960 update_wm_hints (window, FALSE);
3963 static MotifWmHints *
3964 gdk_window_get_mwm_hints (GdkWindow *window)
3966 GdkDisplay *display;
3967 Atom hints_atom = None;
3974 if (GDK_WINDOW_DESTROYED (window))
3977 display = gdk_window_get_display (window);
3979 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
3981 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
3982 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
3983 False, AnyPropertyType, &type, &format, &nitems,
3984 &bytes_after, &data);
3989 return (MotifWmHints *)data;
3993 gdk_window_set_mwm_hints (GdkWindow *window,
3994 MotifWmHints *new_hints)
3996 GdkDisplay *display;
3997 Atom hints_atom = None;
3999 MotifWmHints *hints;
4005 if (GDK_WINDOW_DESTROYED (window))
4008 display = gdk_window_get_display (window);
4010 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4012 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4013 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4014 False, AnyPropertyType, &type, &format, &nitems,
4015 &bytes_after, &data);
4021 hints = (MotifWmHints *)data;
4023 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4025 hints->flags |= MWM_HINTS_FUNCTIONS;
4026 hints->functions = new_hints->functions;
4028 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4030 hints->flags |= MWM_HINTS_DECORATIONS;
4031 hints->decorations = new_hints->decorations;
4035 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4036 hints_atom, hints_atom, 32, PropModeReplace,
4037 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4039 if (hints != new_hints)
4044 gdk_x11_window_set_decorations (GdkWindow *window,
4045 GdkWMDecoration decorations)
4049 if (GDK_WINDOW_DESTROYED (window) ||
4050 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4053 /* initialize to zero to avoid writing uninitialized data to socket */
4054 memset(&hints, 0, sizeof(hints));
4055 hints.flags = MWM_HINTS_DECORATIONS;
4056 hints.decorations = decorations;
4058 gdk_window_set_mwm_hints (window, &hints);
4062 gdk_x11_window_get_decorations(GdkWindow *window,
4063 GdkWMDecoration *decorations)
4065 MotifWmHints *hints;
4066 gboolean result = FALSE;
4068 if (GDK_WINDOW_DESTROYED (window) ||
4069 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4072 hints = gdk_window_get_mwm_hints (window);
4076 if (hints->flags & MWM_HINTS_DECORATIONS)
4079 *decorations = hints->decorations;
4090 gdk_x11_window_set_functions (GdkWindow *window,
4091 GdkWMFunction functions)
4095 g_return_if_fail (GDK_IS_WINDOW (window));
4097 if (GDK_WINDOW_DESTROYED (window) ||
4098 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4101 /* initialize to zero to avoid writing uninitialized data to socket */
4102 memset(&hints, 0, sizeof(hints));
4103 hints.flags = MWM_HINTS_FUNCTIONS;
4104 hints.functions = functions;
4106 gdk_window_set_mwm_hints (window, &hints);
4110 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4114 cairo_region_t *shape;
4122 /* Note that XShapeGetRectangles returns NULL in two situations:
4123 * - the server doesn't support the SHAPE extension
4124 * - the shape is empty
4126 * Since we can't discriminate these here, we always return
4127 * an empty shape. It is the callers responsibility to check
4128 * whether the server supports the SHAPE extensions beforehand.
4130 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4133 return cairo_region_create (); /* Empty */
4135 if (ord != YXBanded)
4137 /* This really shouldn't happen with any xserver, as they
4138 * generally convert regions to YXBanded internally
4140 g_warning ("non YXBanded shape masks not supported");
4145 rl = g_new (GdkRectangle, rn);
4146 for (i = 0; i < rn; i++)
4150 rl[i].width = xrl[i].width;
4151 rl[i].height = xrl[i].height;
4155 shape = cairo_region_create_rectangles (rl, rn);
4162 static cairo_region_t *
4163 gdk_x11_window_get_shape (GdkWindow *window)
4165 if (!GDK_WINDOW_DESTROYED (window) &&
4166 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4167 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4168 GDK_WINDOW_XID (window),
4174 static cairo_region_t *
4175 gdk_x11_window_get_input_shape (GdkWindow *window)
4177 #if defined(ShapeInput)
4178 if (!GDK_WINDOW_DESTROYED (window) &&
4179 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4180 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4181 GDK_WINDOW_XID (window),
4189 gdk_window_set_static_bit_gravity (GdkWindow *window,
4192 XSetWindowAttributes xattributes;
4193 guint xattributes_mask = 0;
4195 g_return_if_fail (GDK_IS_WINDOW (window));
4197 if (window->input_only)
4200 xattributes.bit_gravity = StaticGravity;
4201 xattributes_mask |= CWBitGravity;
4202 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4203 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4204 GDK_WINDOW_XID (window),
4205 CWBitGravity, &xattributes);
4209 gdk_window_set_static_win_gravity (GdkWindow *window,
4212 XSetWindowAttributes xattributes;
4214 g_return_if_fail (GDK_IS_WINDOW (window));
4216 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4218 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4219 GDK_WINDOW_XID (window),
4220 CWWinGravity, &xattributes);
4224 gdk_window_x11_set_static_gravities (GdkWindow *window,
4225 gboolean use_static)
4229 if (!use_static == !window->guffaw_gravity)
4232 window->guffaw_gravity = use_static;
4234 if (!GDK_WINDOW_DESTROYED (window))
4236 gdk_window_set_static_bit_gravity (window, use_static);
4238 tmp_list = window->children;
4241 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4243 tmp_list = tmp_list->next;
4250 /* From the WM spec */
4251 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4252 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4253 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4254 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4255 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4256 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4257 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4258 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4259 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4260 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4261 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4262 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4265 wmspec_send_message (GdkDisplay *display,
4272 XClientMessageEvent xclient;
4274 memset (&xclient, 0, sizeof (xclient));
4275 xclient.type = ClientMessage;
4276 xclient.window = GDK_WINDOW_XID (window);
4277 xclient.message_type =
4278 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4279 xclient.format = 32;
4280 xclient.data.l[0] = root_x;
4281 xclient.data.l[1] = root_y;
4282 xclient.data.l[2] = action;
4283 xclient.data.l[3] = button;
4284 xclient.data.l[4] = 1; /* source indication */
4286 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4287 SubstructureRedirectMask | SubstructureNotifyMask,
4288 (XEvent *)&xclient);
4292 handle_wmspec_button_release (GdkDisplay *display,
4295 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4298 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4299 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4300 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4302 if (xevent->xany.type == GenericEvent)
4303 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4306 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4308 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4310 if ((xevent->xany.type == ButtonRelease &&
4311 xevent->xbutton.button == display_x11->wm_moveresize_button)
4312 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4314 (xevent->xany.type == GenericEvent &&
4315 xiev->evtype == XI_ButtonRelease &&
4316 xidev->detail == display_x11->wm_moveresize_button)
4320 display_x11->wm_moveresize_button = 0;
4321 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4327 wmspec_moveresize (GdkWindow *window,
4335 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4337 /* Release passive grab */
4338 gdk_device_ungrab (device, timestamp);
4339 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4341 wmspec_send_message (display, window, root_x, root_y, direction, button);
4345 wmspec_resize_drag (GdkWindow *window,
4355 /* Let the compiler turn a switch into a table, instead
4356 * of doing the table manually, this way is easier to verify.
4360 case GDK_WINDOW_EDGE_NORTH_WEST:
4361 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4364 case GDK_WINDOW_EDGE_NORTH:
4365 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4368 case GDK_WINDOW_EDGE_NORTH_EAST:
4369 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4372 case GDK_WINDOW_EDGE_WEST:
4373 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4376 case GDK_WINDOW_EDGE_EAST:
4377 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4380 case GDK_WINDOW_EDGE_SOUTH_WEST:
4381 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4384 case GDK_WINDOW_EDGE_SOUTH:
4385 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4388 case GDK_WINDOW_EDGE_SOUTH_EAST:
4389 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4393 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4398 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4401 typedef struct _MoveResizeData MoveResizeData;
4403 struct _MoveResizeData
4405 GdkDisplay *display;
4407 GdkWindow *moveresize_window;
4408 GdkWindow *moveresize_emulation_window;
4410 GdkWindowEdge resize_edge;
4412 gint moveresize_button;
4415 gint moveresize_orig_x;
4416 gint moveresize_orig_y;
4417 gint moveresize_orig_width;
4418 gint moveresize_orig_height;
4419 GdkWindowHints moveresize_geom_mask;
4420 GdkGeometry moveresize_geometry;
4421 Time moveresize_process_time;
4422 XEvent *moveresize_pending_event;
4425 static MoveResizeData *
4426 get_move_resize_data (GdkDisplay *display,
4429 MoveResizeData *mv_resize;
4430 static GQuark move_resize_quark = 0;
4432 if (!move_resize_quark)
4433 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4435 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4437 if (!mv_resize && create)
4439 mv_resize = g_new0 (MoveResizeData, 1);
4440 mv_resize->display = display;
4442 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4449 update_pos (MoveResizeData *mv_resize,
4455 dx = new_root_x - mv_resize->moveresize_x;
4456 dy = new_root_y - mv_resize->moveresize_y;
4458 if (mv_resize->is_resize)
4462 x = mv_resize->moveresize_orig_x;
4463 y = mv_resize->moveresize_orig_y;
4465 w = mv_resize->moveresize_orig_width;
4466 h = mv_resize->moveresize_orig_height;
4468 switch (mv_resize->resize_edge)
4470 case GDK_WINDOW_EDGE_NORTH_WEST:
4476 case GDK_WINDOW_EDGE_NORTH:
4480 case GDK_WINDOW_EDGE_NORTH_EAST:
4485 case GDK_WINDOW_EDGE_SOUTH_WEST:
4490 case GDK_WINDOW_EDGE_SOUTH_EAST:
4494 case GDK_WINDOW_EDGE_SOUTH:
4497 case GDK_WINDOW_EDGE_EAST:
4500 case GDK_WINDOW_EDGE_WEST:
4511 if (mv_resize->moveresize_geom_mask)
4513 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4514 mv_resize->moveresize_geom_mask,
4518 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4524 x = mv_resize->moveresize_orig_x + dx;
4525 y = mv_resize->moveresize_orig_y + dy;
4527 gdk_window_move (mv_resize->moveresize_window, x, y);
4532 finish_drag (MoveResizeData *mv_resize)
4534 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4535 mv_resize->moveresize_emulation_window = NULL;
4536 g_object_unref (mv_resize->moveresize_window);
4537 mv_resize->moveresize_window = NULL;
4539 if (mv_resize->moveresize_pending_event)
4541 g_free (mv_resize->moveresize_pending_event);
4542 mv_resize->moveresize_pending_event = NULL;
4547 lookahead_motion_predicate (Display *xdisplay,
4551 gboolean *seen_release = (gboolean *)arg;
4552 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4553 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4558 switch (event->xany.type)
4561 *seen_release = TRUE;
4564 mv_resize->moveresize_process_time = event->xmotion.time;
4574 moveresize_lookahead (MoveResizeData *mv_resize,
4578 gboolean seen_release = FALSE;
4580 if (mv_resize->moveresize_process_time)
4582 if (event->xmotion.time == mv_resize->moveresize_process_time)
4584 mv_resize->moveresize_process_time = 0;
4591 XCheckIfEvent (event->xany.display, &tmp_event,
4592 lookahead_motion_predicate, (XPointer) & seen_release);
4594 return mv_resize->moveresize_process_time == 0;
4598 _gdk_x11_moveresize_handle_event (XEvent *event)
4600 guint button_mask = 0;
4601 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4602 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4604 if (!mv_resize || !mv_resize->moveresize_window)
4606 handle_wmspec_button_release (display, event);
4610 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4612 switch (event->xany.type)
4615 if (mv_resize->moveresize_window->resize_count > 0)
4617 if (mv_resize->moveresize_pending_event)
4618 *mv_resize->moveresize_pending_event = *event;
4620 mv_resize->moveresize_pending_event =
4621 g_memdup (event, sizeof (XEvent));
4625 if (!moveresize_lookahead (mv_resize, event))
4628 update_pos (mv_resize,
4629 event->xmotion.x_root,
4630 event->xmotion.y_root);
4632 /* This should never be triggered in normal cases, but in the
4633 * case where the drag started without an implicit grab being
4634 * in effect, we could miss the release if it occurs before
4635 * we grab the pointer; this ensures that we will never
4636 * get a permanently stuck grab.
4638 if ((event->xmotion.state & button_mask) == 0)
4639 finish_drag (mv_resize);
4643 update_pos (mv_resize,
4644 event->xbutton.x_root,
4645 event->xbutton.y_root);
4647 if (event->xbutton.button == mv_resize->moveresize_button)
4648 finish_drag (mv_resize);
4651 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4654 /* we just assume this is an XI2 event */
4655 XIEvent *ev = (XIEvent *) event->xcookie.data;
4656 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4661 update_pos (mv_resize, xev->root_x, xev->root_y);
4662 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4663 if ((state & button_mask) == 0)
4664 finish_drag (mv_resize);
4667 case XI_ButtonRelease:
4668 update_pos (mv_resize, xev->root_x, xev->root_y);
4669 if (xev->detail == mv_resize->moveresize_button)
4670 finish_drag (mv_resize);
4682 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4686 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4688 if (!mv_resize || window != mv_resize->moveresize_window)
4691 if (mv_resize->moveresize_pending_event)
4693 tmp_event = mv_resize->moveresize_pending_event;
4694 mv_resize->moveresize_pending_event = NULL;
4695 _gdk_x11_moveresize_handle_event (tmp_event);
4703 create_moveresize_window (MoveResizeData *mv_resize,
4706 GdkWindowAttr attributes;
4707 gint attributes_mask;
4708 GdkGrabStatus status;
4710 g_assert (mv_resize->moveresize_emulation_window == NULL);
4712 attributes.x = -100;
4713 attributes.y = -100;
4714 attributes.width = 10;
4715 attributes.height = 10;
4716 attributes.window_type = GDK_WINDOW_TEMP;
4717 attributes.wclass = GDK_INPUT_ONLY;
4718 attributes.override_redirect = TRUE;
4719 attributes.event_mask = 0;
4721 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4723 mv_resize->moveresize_emulation_window =
4724 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4728 gdk_window_show (mv_resize->moveresize_emulation_window);
4730 status = gdk_device_grab (mv_resize->device,
4731 mv_resize->moveresize_emulation_window,
4734 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4738 if (status != GDK_GRAB_SUCCESS)
4740 /* If this fails, some other client has grabbed the window
4743 finish_drag (mv_resize);
4746 mv_resize->moveresize_process_time = 0;
4750 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4751 so that calling XMoveWindow with these coordinates will not move the
4753 Note that this depends on the WM to implement ICCCM-compliant reference
4757 calculate_unmoving_origin (MoveResizeData *mv_resize)
4762 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4763 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4765 gdk_window_get_origin (mv_resize->moveresize_window,
4766 &mv_resize->moveresize_orig_x,
4767 &mv_resize->moveresize_orig_y);
4771 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4772 gdk_window_get_geometry (mv_resize->moveresize_window,
4773 NULL, NULL, &width, &height);
4775 switch (mv_resize->moveresize_geometry.win_gravity)
4777 case GDK_GRAVITY_NORTH_WEST:
4778 mv_resize->moveresize_orig_x = rect.x;
4779 mv_resize->moveresize_orig_y = rect.y;
4781 case GDK_GRAVITY_NORTH:
4782 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4783 mv_resize->moveresize_orig_y = rect.y;
4785 case GDK_GRAVITY_NORTH_EAST:
4786 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4787 mv_resize->moveresize_orig_y = rect.y;
4789 case GDK_GRAVITY_WEST:
4790 mv_resize->moveresize_orig_x = rect.x;
4791 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4793 case GDK_GRAVITY_CENTER:
4794 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4795 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4797 case GDK_GRAVITY_EAST:
4798 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4799 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4801 case GDK_GRAVITY_SOUTH_WEST:
4802 mv_resize->moveresize_orig_x = rect.x;
4803 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4805 case GDK_GRAVITY_SOUTH:
4806 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4807 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4809 case GDK_GRAVITY_SOUTH_EAST:
4810 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4811 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4814 mv_resize->moveresize_orig_x = rect.x;
4815 mv_resize->moveresize_orig_y = rect.y;
4822 emulate_resize_drag (GdkWindow *window,
4830 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4832 mv_resize->is_resize = TRUE;
4833 mv_resize->moveresize_button = button;
4834 mv_resize->resize_edge = edge;
4835 mv_resize->device = device;
4836 mv_resize->moveresize_x = root_x;
4837 mv_resize->moveresize_y = root_y;
4838 mv_resize->moveresize_window = g_object_ref (window);
4840 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
4841 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
4843 mv_resize->moveresize_geom_mask = 0;
4844 gdk_window_get_geometry_hints (window,
4845 &mv_resize->moveresize_geometry,
4846 &mv_resize->moveresize_geom_mask);
4848 calculate_unmoving_origin (mv_resize);
4850 create_moveresize_window (mv_resize, timestamp);
4854 emulate_move_drag (GdkWindow *window,
4861 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4863 mv_resize->is_resize = FALSE;
4864 mv_resize->device = device;
4865 mv_resize->moveresize_button = button;
4866 mv_resize->moveresize_x = root_x;
4867 mv_resize->moveresize_y = root_y;
4869 mv_resize->moveresize_window = g_object_ref (window);
4871 calculate_unmoving_origin (mv_resize);
4873 create_moveresize_window (mv_resize, timestamp);
4877 gdk_x11_window_begin_resize_drag (GdkWindow *window,
4885 if (GDK_WINDOW_DESTROYED (window) ||
4886 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4889 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4890 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4891 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4893 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4897 gdk_x11_window_begin_move_drag (GdkWindow *window,
4904 if (GDK_WINDOW_DESTROYED (window) ||
4905 !WINDOW_IS_TOPLEVEL (window))
4908 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4909 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4910 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
4911 device, button, root_x, root_y, timestamp);
4913 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
4917 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
4919 GdkWindowImplX11 *impl;
4921 if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
4924 impl = GDK_WINDOW_IMPL_X11 (window->impl);
4926 if (!impl->use_synchronized_configure)
4928 /* This basically means you want to do fancy X specific stuff, so
4929 ensure we have a native window */
4930 gdk_window_ensure_native (window);
4932 impl->use_synchronized_configure = TRUE;
4933 ensure_sync_counter (window);
4938 gdk_x11_window_configure_finished (GdkWindow *window)
4940 GdkWindowImplX11 *impl;
4942 if (!WINDOW_IS_TOPLEVEL (window))
4945 impl = GDK_WINDOW_IMPL_X11 (window->impl);
4946 if (!impl->use_synchronized_configure)
4950 if (!GDK_WINDOW_DESTROYED (window))
4952 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4953 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
4955 if (toplevel && toplevel->update_counter != None &&
4956 GDK_X11_DISPLAY (display)->use_sync &&
4957 toplevel->configure_counter_value != 0)
4959 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
4960 toplevel->update_counter,
4961 toplevel->configure_counter_value);
4963 toplevel->current_counter_value = toplevel->configure_counter_value;
4964 if ((toplevel->current_counter_value % 2) == 1)
4965 toplevel->current_counter_value += 1;
4967 toplevel->configure_counter_value = 0;
4969 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
4970 toplevel->extended_update_counter,
4971 toplevel->current_counter_value);
4978 gdk_x11_window_beep (GdkWindow *window)
4980 GdkDisplay *display;
4982 display = GDK_WINDOW_DISPLAY (window);
4985 if (GDK_X11_DISPLAY (display)->use_xkb)
4987 XkbBell (GDK_DISPLAY_XDISPLAY (display),
4988 GDK_WINDOW_XID (window),
4999 gdk_x11_window_set_opacity (GdkWindow *window,
5002 GdkDisplay *display;
5005 g_return_if_fail (GDK_IS_WINDOW (window));
5007 if (GDK_WINDOW_DESTROYED (window) ||
5008 !WINDOW_IS_TOPLEVEL (window))
5011 display = gdk_window_get_display (window);
5015 else if (opacity > 1)
5018 cardinal = opacity * 0xffffffff;
5020 if (cardinal == 0xffffffff)
5021 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5022 GDK_WINDOW_XID (window),
5023 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5025 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5026 GDK_WINDOW_XID (window),
5027 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5030 (guchar *) &cardinal, 1);
5034 gdk_x11_window_set_composited (GdkWindow *window,
5035 gboolean composited)
5037 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5038 GdkWindowImplX11 *impl;
5039 GdkDisplay *display;
5043 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5045 display = gdk_window_get_display (window);
5046 dpy = GDK_DISPLAY_XDISPLAY (display);
5047 xid = GDK_WINDOW_XID (window);
5051 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5052 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5056 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5057 XDamageDestroy (dpy, impl->damage);
5058 impl->damage = None;
5064 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5065 cairo_region_t *region)
5067 _gdk_window_process_updates_recurse (window, region);
5071 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5076 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5078 /* Sync after all drawing, otherwise the client can get "ahead" of
5079 the server rendering during animations, such that we fill up
5080 the Xserver pipes with sync rendering ops not letting other
5081 clients (including the VM) do anything. */
5082 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5086 timestamp_predicate (Display *display,
5090 Window xwindow = GPOINTER_TO_UINT (arg);
5091 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5093 if (xevent->type == PropertyNotify &&
5094 xevent->xproperty.window == xwindow &&
5095 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5096 "GDK_TIMESTAMP_PROP"))
5103 * gdk_x11_get_server_time:
5104 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5105 * with the server. The window must have
5106 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5109 * Routine to get the current X server time stamp.
5111 * Return value: the time stamp.
5114 gdk_x11_get_server_time (GdkWindow *window)
5120 Atom timestamp_prop_atom;
5122 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5123 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5125 xdisplay = GDK_WINDOW_XDISPLAY (window);
5126 xwindow = GDK_WINDOW_XID (window);
5127 timestamp_prop_atom =
5128 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5129 "GDK_TIMESTAMP_PROP");
5131 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5132 timestamp_prop_atom,
5133 8, PropModeReplace, &c, 1);
5135 XIfEvent (xdisplay, &xevent,
5136 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5138 return xevent.xproperty.time;
5142 * gdk_x11_window_get_xid:
5143 * @window: (type GdkX11Window): a native #GdkWindow.
5145 * Returns the X resource (window) belonging to a #GdkWindow.
5147 * Return value: the ID of @drawable's X resource.
5150 gdk_x11_window_get_xid (GdkWindow *window)
5152 /* Try to ensure the window has a native window */
5153 if (!_gdk_window_has_impl (window))
5155 gdk_window_ensure_native (window);
5157 /* We sync here to ensure the window is created in the Xserver when
5158 * this function returns. This is required because the returned XID
5159 * for this window must be valid immediately, even with another
5160 * connection to the Xserver */
5161 gdk_display_sync (gdk_window_get_display (window));
5164 if (!GDK_WINDOW_IS_X11 (window))
5166 g_warning (G_STRLOC " drawable is not a native X11 window");
5170 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5174 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5176 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5177 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5179 object_class->finalize = gdk_window_impl_x11_finalize;
5181 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5182 impl_class->show = gdk_window_x11_show;
5183 impl_class->hide = gdk_window_x11_hide;
5184 impl_class->withdraw = gdk_window_x11_withdraw;
5185 impl_class->set_events = gdk_window_x11_set_events;
5186 impl_class->get_events = gdk_window_x11_get_events;
5187 impl_class->raise = gdk_window_x11_raise;
5188 impl_class->lower = gdk_window_x11_lower;
5189 impl_class->restack_under = gdk_window_x11_restack_under;
5190 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5191 impl_class->move_resize = gdk_window_x11_move_resize;
5192 impl_class->set_background = gdk_window_x11_set_background;
5193 impl_class->reparent = gdk_window_x11_reparent;
5194 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5195 impl_class->get_geometry = gdk_window_x11_get_geometry;
5196 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5197 impl_class->get_device_state = gdk_window_x11_get_device_state;
5198 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5199 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5200 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5201 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5202 impl_class->translate = _gdk_x11_window_translate;
5203 impl_class->destroy = gdk_x11_window_destroy;
5204 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5205 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5206 impl_class->get_shape = gdk_x11_window_get_shape;
5207 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5208 impl_class->beep = gdk_x11_window_beep;
5210 impl_class->focus = gdk_x11_window_focus;
5211 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5212 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5213 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5214 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5215 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5216 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5217 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5218 impl_class->set_title = gdk_x11_window_set_title;
5219 impl_class->set_role = gdk_x11_window_set_role;
5220 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5221 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5222 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5223 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5224 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5225 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5226 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5227 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5228 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5229 impl_class->iconify = gdk_x11_window_iconify;
5230 impl_class->deiconify = gdk_x11_window_deiconify;
5231 impl_class->stick = gdk_x11_window_stick;
5232 impl_class->unstick = gdk_x11_window_unstick;
5233 impl_class->maximize = gdk_x11_window_maximize;
5234 impl_class->unmaximize = gdk_x11_window_unmaximize;
5235 impl_class->fullscreen = gdk_x11_window_fullscreen;
5236 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5237 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5238 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5239 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5240 impl_class->get_group = gdk_x11_window_get_group;
5241 impl_class->set_group = gdk_x11_window_set_group;
5242 impl_class->set_decorations = gdk_x11_window_set_decorations;
5243 impl_class->get_decorations = gdk_x11_window_get_decorations;
5244 impl_class->set_functions = gdk_x11_window_set_functions;
5245 impl_class->set_functions = gdk_x11_window_set_functions;
5246 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5247 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5248 impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
5249 impl_class->configure_finished = gdk_x11_window_configure_finished;
5250 impl_class->set_opacity = gdk_x11_window_set_opacity;
5251 impl_class->set_composited = gdk_x11_window_set_composited;
5252 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5253 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5254 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5255 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5256 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5257 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5258 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5259 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5260 impl_class->get_property = _gdk_x11_window_get_property;
5261 impl_class->change_property = _gdk_x11_window_change_property;
5262 impl_class->delete_property = _gdk_x11_window_delete_property;