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 window_pre_damage (GdkWindow *window)
219 GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
220 GdkWindowImplX11 *impl;
222 if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
225 impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
227 if (impl->toplevel->in_frame &&
228 impl->toplevel->current_counter_value % 2 == 0)
230 impl->toplevel->current_counter_value += 1;
231 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
232 impl->toplevel->extended_update_counter,
233 impl->toplevel->current_counter_value);
238 on_surface_changed (void *data)
240 GdkWindow *window = data;
242 window_pre_damage (window);
245 /* We want to know when cairo drawing causes damage to the window,
246 * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
247 * window only when there actually is drawing. To do that we use
248 * a technique (hack) suggested by Uli Schlachter - if we set
249 * a dummy "mime data" on the cairo surface (this facility is
250 * used to attach JPEG data to an imager), then cairo wil flush
251 * and remove the mime data before making any changes to the window.
255 hook_surface_changed (GdkWindow *window)
257 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
259 if (impl->cairo_surface)
260 cairo_surface_set_mime_data (impl->cairo_surface,
261 "x-gdk/change-notify",
262 (unsigned char *)"X",
269 unhook_surface_changed (GdkWindow *window)
271 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
273 if (impl->cairo_surface)
274 cairo_surface_set_mime_data (impl->cairo_surface,
275 "x-gdk/change-notify",
281 gdk_x11_window_begin_frame (GdkWindow *window)
283 GdkWindowImplX11 *impl;
285 g_return_if_fail (GDK_IS_WINDOW (window));
287 impl = GDK_WINDOW_IMPL_X11 (window->impl);
289 if (!WINDOW_IS_TOPLEVEL (window) ||
290 impl->toplevel->extended_update_counter == None)
293 impl->toplevel->in_frame = TRUE;
295 hook_surface_changed (window);
299 gdk_x11_window_end_frame (GdkWindow *window)
301 GdkWindowImplX11 *impl;
303 g_return_if_fail (GDK_IS_WINDOW (window));
305 impl = GDK_WINDOW_IMPL_X11 (window->impl);
307 if (!WINDOW_IS_TOPLEVEL (window) ||
308 impl->toplevel->extended_update_counter == None ||
309 !impl->toplevel->in_frame)
312 impl->toplevel->in_frame = FALSE;
314 if (impl->toplevel->current_counter_value % 2 == 1)
316 impl->toplevel->current_counter_value += 1;
317 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
318 impl->toplevel->extended_update_counter,
319 impl->toplevel->current_counter_value);
321 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
322 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
324 impl->toplevel->frame_pending = TRUE;
325 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
329 unhook_surface_changed (window);
332 /*****************************************************
333 * X11 specific implementations of generic functions *
334 *****************************************************/
337 gdk_x11_cairo_surface_destroy (void *data)
339 GdkWindowImplX11 *impl = data;
341 impl->cairo_surface = NULL;
344 static cairo_surface_t *
345 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
351 visual = gdk_window_get_visual (impl->wrapper);
352 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
353 GDK_WINDOW_IMPL_X11 (impl)->xid,
354 GDK_VISUAL_XVISUAL (visual),
358 static cairo_surface_t *
359 gdk_x11_ref_cairo_surface (GdkWindow *window)
361 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
363 if (GDK_WINDOW_DESTROYED (window))
366 if (!impl->cairo_surface)
368 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
369 gdk_window_get_width (window),
370 gdk_window_get_height (window));
372 if (impl->cairo_surface)
373 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
374 impl, gdk_x11_cairo_surface_destroy);
376 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
377 hook_surface_changed (window);
380 cairo_surface_reference (impl->cairo_surface);
382 return impl->cairo_surface;
386 gdk_window_impl_x11_finalize (GObject *object)
389 GdkWindowImplX11 *impl;
391 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
393 impl = GDK_WINDOW_IMPL_X11 (object);
395 wrapper = impl->wrapper;
397 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
398 unhook_surface_changed (wrapper);
400 _gdk_x11_window_grab_check_destroy (wrapper);
402 if (!GDK_WINDOW_DESTROYED (wrapper))
404 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
406 _gdk_x11_display_remove_window (display, impl->xid);
407 if (impl->toplevel && impl->toplevel->focus_window)
408 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
411 g_free (impl->toplevel);
414 g_object_unref (impl->cursor);
416 g_hash_table_destroy (impl->device_cursor);
418 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
427 free_pixmap (gpointer datap)
429 FreePixmapData *data = datap;
431 if (!gdk_display_is_closed (data->display))
433 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
437 g_object_unref (data->display);
438 g_slice_free (FreePixmapData, data);
442 attach_free_pixmap_handler (cairo_surface_t *surface,
446 static const cairo_user_data_key_t key;
447 FreePixmapData *data;
449 data = g_slice_new (FreePixmapData);
450 data->display = g_object_ref (display);
451 data->pixmap = pixmap;
453 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
456 /* Cairo does not guarantee we get an xlib surface if we call
457 * cairo_surface_create_similar(). In some cases however, we must use a
458 * pixmap or bitmap in the X11 API.
459 * These functions ensure an Xlib surface.
462 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
466 cairo_surface_t *surface;
469 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
470 GDK_WINDOW_XID (window),
472 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
474 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
476 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
481 /* Create a surface backed with a pixmap without alpha on the same screen as window */
482 static cairo_surface_t *
483 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
487 GdkScreen *screen = gdk_window_get_screen (window);
488 GdkVisual *visual = gdk_screen_get_system_visual (screen);
489 cairo_surface_t *surface;
492 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
493 GDK_WINDOW_XID (window),
495 gdk_visual_get_depth (visual));
496 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
498 GDK_VISUAL_XVISUAL (visual),
500 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
506 tmp_unset_bg (GdkWindow *window)
508 GdkWindowImplX11 *impl;
510 impl = GDK_WINDOW_IMPL_X11 (window->impl);
514 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
515 GDK_WINDOW_XID (window), None);
519 tmp_reset_bg (GdkWindow *window)
521 GdkWindowImplX11 *impl;
523 impl = GDK_WINDOW_IMPL_X11 (window->impl);
527 gdk_window_x11_set_background (window, window->background);
530 /* Unsetting and resetting window backgrounds.
532 * In many cases it is possible to avoid flicker by unsetting the
533 * background of windows. For example if the background of the
534 * parent window is unset when a window is unmapped, a brief flicker
535 * of background painting is avoided.
538 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
541 g_return_if_fail (GDK_IS_WINDOW (window));
543 if (window->input_only || window->destroyed ||
544 (window->window_type != GDK_WINDOW_ROOT &&
545 !GDK_WINDOW_IS_MAPPED (window)))
548 if (_gdk_window_has_impl (window) &&
549 GDK_WINDOW_IS_X11 (window) &&
550 window->window_type != GDK_WINDOW_ROOT &&
551 window->window_type != GDK_WINDOW_FOREIGN)
552 tmp_unset_bg (window);
558 for (l = window->children; l != NULL; l = l->next)
559 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
564 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
566 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
569 window = _gdk_window_get_impl_window (window->parent);
570 _gdk_x11_window_tmp_unset_bg (window, FALSE);
574 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
577 g_return_if_fail (GDK_IS_WINDOW (window));
579 if (window->input_only || window->destroyed ||
580 (window->window_type != GDK_WINDOW_ROOT &&
581 !GDK_WINDOW_IS_MAPPED (window)))
585 if (_gdk_window_has_impl (window) &&
586 GDK_WINDOW_IS_X11 (window) &&
587 window->window_type != GDK_WINDOW_ROOT &&
588 window->window_type != GDK_WINDOW_FOREIGN)
589 tmp_reset_bg (window);
595 for (l = window->children; l != NULL; l = l->next)
596 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
601 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
603 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
606 window = _gdk_window_get_impl_window (window->parent);
608 _gdk_x11_window_tmp_reset_bg (window, FALSE);
612 _gdk_x11_screen_init_root_window (GdkScreen *screen)
615 GdkWindowImplX11 *impl;
616 GdkX11Screen *x11_screen;
618 x11_screen = GDK_X11_SCREEN (screen);
620 g_assert (x11_screen->root_window == NULL);
622 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
624 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
625 window->impl_window = window;
626 window->visual = gdk_screen_get_system_visual (screen);
628 impl = GDK_WINDOW_IMPL_X11 (window->impl);
630 impl->xid = x11_screen->xroot_window;
631 impl->wrapper = window;
633 window->window_type = GDK_WINDOW_ROOT;
634 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
640 window->width = WidthOfScreen (x11_screen->xscreen);
641 window->height = HeightOfScreen (x11_screen->xscreen);
642 window->viewable = TRUE;
644 /* see init_randr_support() in gdkscreen-x11.c */
645 window->event_mask = GDK_STRUCTURE_MASK;
647 _gdk_window_update_size (x11_screen->root_window);
649 _gdk_x11_display_add_window (x11_screen->display,
650 &x11_screen->xroot_window,
651 x11_screen->root_window);
655 set_wm_protocols (GdkWindow *window)
657 GdkDisplay *display = gdk_window_get_display (window);
661 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
662 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
663 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
666 if (GDK_X11_DISPLAY (display)->use_sync)
667 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
670 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
674 get_default_title (void)
678 title = g_get_application_name ();
680 title = g_get_prgname ();
688 check_leader_window_title (GdkDisplay *display)
690 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
692 if (display_x11->leader_window && !display_x11->leader_window_title_set)
694 set_wm_name (display,
695 display_x11->leader_window,
696 get_default_title ());
698 display_x11->leader_window_title_set = TRUE;
703 create_focus_window (GdkDisplay *display,
706 GdkX11Display *display_x11;
707 GdkEventMask event_mask;
711 xdisplay = GDK_DISPLAY_XDISPLAY (display);
712 display_x11 = GDK_X11_DISPLAY (display);
714 focus_window = XCreateSimpleWindow (xdisplay, parent,
718 /* FIXME: probably better to actually track the requested event mask for the toplevel
720 event_mask = (GDK_KEY_PRESS_MASK |
721 GDK_KEY_RELEASE_MASK |
722 GDK_FOCUS_CHANGE_MASK);
724 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
728 XMapWindow (xdisplay, focus_window);
734 ensure_sync_counter (GdkWindow *window)
737 if (!GDK_WINDOW_DESTROYED (window))
739 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
740 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
743 toplevel->update_counter == None &&
744 GDK_X11_DISPLAY (display)->use_sync)
746 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
751 XSyncIntToValue (&value, 0);
753 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
754 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
756 atom = gdk_x11_get_xatom_by_name_for_display (display,
757 "_NET_WM_SYNC_REQUEST_COUNTER");
759 counters[0] = toplevel->update_counter;
760 counters[1] = toplevel->extended_update_counter;
761 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
764 (guchar *)counters, 2);
766 toplevel->current_counter_value = 0;
773 setup_toplevel_window (GdkWindow *window,
776 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
777 GdkDisplay *display = gdk_window_get_display (window);
778 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
779 XID xid = GDK_WINDOW_XID (window);
780 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
781 XSizeHints size_hints;
783 Window leader_window;
785 set_wm_protocols (window);
787 if (!window->input_only)
789 /* The focus window is off the visible area, and serves to receive key
790 * press events so they don't get sent to child windows.
792 toplevel->focus_window = create_focus_window (display, xid);
793 _gdk_x11_display_add_window (x11_screen->display,
794 &toplevel->focus_window,
798 check_leader_window_title (x11_screen->display);
800 /* FIXME: Is there any point in doing this? Do any WM's pay
801 * attention to PSize, and even if they do, is this the
804 size_hints.flags = PSize;
805 size_hints.width = window->width;
806 size_hints.height = window->height;
808 XSetWMNormalHints (xdisplay, xid, &size_hints);
810 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
811 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
814 XChangeProperty (xdisplay, xid,
815 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
820 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
823 XChangeProperty (xdisplay, xid,
824 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
825 XA_WINDOW, 32, PropModeReplace,
826 (guchar *) &leader_window, 1);
828 if (toplevel->focus_window != None)
829 XChangeProperty (xdisplay, xid,
830 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
831 XA_WINDOW, 32, PropModeReplace,
832 (guchar *) &toplevel->focus_window, 1);
834 if (!window->focus_on_map)
835 gdk_x11_window_set_user_time (window, 0);
836 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
837 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
839 ensure_sync_counter (window);
841 /* Start off in a frozen state - we'll finish this when we first paint */
842 gdk_x11_window_begin_frame (window);
846 on_frame_clock_before_paint (GdkFrameClock *clock,
849 gdk_x11_window_begin_frame (window);
853 on_frame_clock_after_paint (GdkFrameClock *clock,
856 gdk_x11_window_end_frame (window);
860 _gdk_x11_display_create_window_impl (GdkDisplay *display,
862 GdkWindow *real_parent,
864 GdkEventMask event_mask,
865 GdkWindowAttr *attributes,
866 gint attributes_mask)
868 GdkWindowImplX11 *impl;
869 GdkX11Screen *x11_screen;
870 GdkX11Display *display_x11;
871 GdkFrameClock *clock;
877 XSetWindowAttributes xattributes;
878 long xattributes_mask;
879 XClassHint *class_hint;
884 display_x11 = GDK_X11_DISPLAY (display);
885 xparent = GDK_WINDOW_XID (real_parent);
886 x11_screen = GDK_X11_SCREEN (screen);
888 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
889 window->impl = GDK_WINDOW_IMPL (impl);
890 impl->wrapper = GDK_WINDOW (window);
892 xdisplay = x11_screen->xdisplay;
894 xattributes_mask = 0;
896 xvisual = gdk_x11_visual_get_xvisual (window->visual);
898 if (attributes_mask & GDK_WA_NOREDIR)
900 xattributes.override_redirect =
901 (attributes->override_redirect == FALSE)?False:True;
902 xattributes_mask |= CWOverrideRedirect;
905 xattributes.override_redirect = False;
907 impl->override_redirect = xattributes.override_redirect;
909 if (window->parent && window->parent->guffaw_gravity)
911 xattributes.win_gravity = StaticGravity;
912 xattributes_mask |= CWWinGravity;
916 switch (window->window_type)
918 case GDK_WINDOW_TOPLEVEL:
919 case GDK_WINDOW_TEMP:
920 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
922 /* The common code warns for this case */
923 xparent = GDK_SCREEN_XROOTWIN (screen);
927 if (!window->input_only)
931 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
933 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
934 xattributes_mask |= CWBorderPixel | CWBackPixel;
936 if (window->guffaw_gravity)
937 xattributes.bit_gravity = StaticGravity;
939 xattributes.bit_gravity = NorthWestGravity;
941 xattributes_mask |= CWBitGravity;
943 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
944 xattributes_mask |= CWColormap;
946 if (window->window_type == GDK_WINDOW_TEMP)
948 xattributes.save_under = True;
949 xattributes.override_redirect = True;
950 xattributes.cursor = None;
951 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
953 impl->override_redirect = TRUE;
961 if (window->width > 65535 ||
962 window->height > 65535)
964 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
966 if (window->width > 65535)
967 window->width = 65535;
968 if (window->height > 65535)
969 window->height = 65535;
972 impl->xid = XCreateWindow (xdisplay, xparent,
973 window->x + window->parent->abs_x,
974 window->y + window->parent->abs_y,
975 window->width, window->height,
976 0, window->depth, class, xvisual,
977 xattributes_mask, &xattributes);
979 g_object_ref (window);
980 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
982 switch (GDK_WINDOW_TYPE (window))
984 case GDK_WINDOW_TOPLEVEL:
985 case GDK_WINDOW_TEMP:
986 if (attributes_mask & GDK_WA_TITLE)
987 title = attributes->title;
989 title = get_default_title ();
991 gdk_window_set_title (window, title);
993 if (attributes_mask & GDK_WA_WMCLASS)
995 class_hint = XAllocClassHint ();
996 class_hint->res_name = attributes->wmclass_name;
997 class_hint->res_class = attributes->wmclass_class;
998 XSetClassHint (xdisplay, impl->xid, class_hint);
1002 setup_toplevel_window (window, window->parent);
1005 case GDK_WINDOW_CHILD:
1010 if (attributes_mask & GDK_WA_TYPE_HINT)
1011 gdk_window_set_type_hint (window, attributes->type_hint);
1013 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1014 GDK_WINDOW_XID (window), event_mask,
1015 StructureNotifyMask | PropertyChangeMask);
1017 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1018 gdk_window_set_frame_clock (window, clock);
1019 g_signal_connect (clock, "before-paint",
1020 G_CALLBACK (on_frame_clock_before_paint), window);
1021 g_signal_connect (clock, "after-paint",
1022 G_CALLBACK (on_frame_clock_after_paint), window);
1024 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1025 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1029 x_event_mask_to_gdk_event_mask (long mask)
1031 GdkEventMask event_mask = 0;
1034 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1036 if (mask & _gdk_x11_event_mask_table[i])
1037 event_mask |= 1 << (i + 1);
1044 * gdk_x11_window_foreign_new_for_display:
1045 * @display: the #GdkDisplay where the window handle comes from.
1046 * @window: an XLib <type>Window</type>
1048 * Wraps a native window in a #GdkWindow. The function will try to
1049 * look up the window using gdk_x11_window_lookup_for_display() first.
1050 * If it does not find it there, it will create a new window.
1052 * This may fail if the window has been destroyed. If the window
1053 * was already known to GDK, a new reference to the existing
1054 * #GdkWindow is returned.
1056 * Return value: (transfer full): a #GdkWindow wrapper for the native
1057 * window, or %NULL if the window has been destroyed. The wrapper
1058 * will be newly created, if one doesn't exist already.
1063 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1068 GdkWindowImplX11 *impl;
1069 GdkX11Display *display_x11;
1070 XWindowAttributes attrs;
1071 Window root, parent;
1072 Window *children = NULL;
1076 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1078 display_x11 = GDK_X11_DISPLAY (display);
1080 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1081 return g_object_ref (win);
1083 gdk_x11_display_error_trap_push (display);
1084 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1085 if (gdk_x11_display_error_trap_pop (display) || !result)
1088 /* FIXME: This is pretty expensive.
1089 * Maybe the caller should supply the parent
1091 gdk_x11_display_error_trap_push (display);
1092 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1093 if (gdk_x11_display_error_trap_pop (display) || !result)
1099 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1101 win = _gdk_display_create_window (display);
1102 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1103 win->impl_window = win;
1104 win->visual = gdk_x11_screen_lookup_visual (screen,
1105 XVisualIDFromVisual (attrs.visual));
1107 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1108 impl->wrapper = win;
1110 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1112 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1113 win->parent = gdk_screen_get_root_window (screen);
1115 win->parent->children = g_list_prepend (win->parent->children, win);
1121 win->width = attrs.width;
1122 win->height = attrs.height;
1123 win->window_type = GDK_WINDOW_FOREIGN;
1124 win->destroyed = FALSE;
1126 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1128 if (attrs.map_state == IsUnmapped)
1129 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1132 win->viewable = TRUE;
1134 win->depth = attrs.depth;
1137 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1139 /* Update the clip region, etc */
1140 _gdk_window_update_size (win);
1146 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1147 GdkToplevelX11 *toplevel)
1149 if (toplevel->icon_pixmap)
1151 cairo_surface_destroy (toplevel->icon_pixmap);
1152 toplevel->icon_pixmap = NULL;
1154 if (toplevel->icon_mask)
1156 cairo_surface_destroy (toplevel->icon_mask);
1157 toplevel->icon_mask = NULL;
1159 if (toplevel->group_leader)
1161 g_object_unref (toplevel->group_leader);
1162 toplevel->group_leader = NULL;
1165 if (toplevel->update_counter != None)
1167 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1168 toplevel->update_counter);
1169 toplevel->update_counter = None;
1171 toplevel->current_counter_value = 0;
1177 gdk_x11_window_destroy (GdkWindow *window,
1179 gboolean foreign_destroy)
1181 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1182 GdkToplevelX11 *toplevel;
1184 g_return_if_fail (GDK_IS_WINDOW (window));
1186 _gdk_x11_selection_window_destroyed (window);
1188 toplevel = _gdk_x11_window_get_toplevel (window);
1190 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1192 if (impl->cairo_surface)
1194 cairo_surface_finish (impl->cairo_surface);
1195 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1199 if (!recursing && !foreign_destroy)
1200 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1203 static cairo_surface_t *
1204 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1205 cairo_surface_t *surface,
1209 cairo_xlib_surface_set_size (surface, width, height);
1215 gdk_x11_window_destroy_foreign (GdkWindow *window)
1217 /* It's somebody else's window, but in our hierarchy,
1218 * so reparent it to the root window, and then send
1219 * it a delete event, as if we were a WM
1221 XClientMessageEvent xclient;
1222 GdkDisplay *display;
1224 display = GDK_WINDOW_DISPLAY (window);
1225 gdk_x11_display_error_trap_push (display);
1226 gdk_window_hide (window);
1227 gdk_window_reparent (window, NULL, 0, 0);
1229 memset (&xclient, 0, sizeof (xclient));
1230 xclient.type = ClientMessage;
1231 xclient.window = GDK_WINDOW_XID (window);
1232 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1233 xclient.format = 32;
1234 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1235 xclient.data.l[1] = CurrentTime;
1236 xclient.data.l[2] = 0;
1237 xclient.data.l[3] = 0;
1238 xclient.data.l[4] = 0;
1240 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1241 GDK_WINDOW_XID (window),
1242 False, 0, (XEvent *)&xclient);
1243 gdk_x11_display_error_trap_pop_ignored (display);
1247 get_root (GdkWindow *window)
1249 GdkScreen *screen = gdk_window_get_screen (window);
1251 return gdk_screen_get_root_window (screen);
1254 /* This function is called when the XWindow is really gone.
1257 gdk_x11_window_destroy_notify (GdkWindow *window)
1259 GdkWindowImplX11 *window_impl;
1261 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1263 if (!GDK_WINDOW_DESTROYED (window))
1265 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1266 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1268 _gdk_window_destroy (window, TRUE);
1271 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1272 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1273 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1275 _gdk_x11_window_grab_check_destroy (window);
1277 g_object_unref (window);
1280 static GdkDragProtocol
1281 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1284 GdkDragProtocol protocol;
1285 GdkDisplay *display;
1289 display = gdk_window_get_display (window);
1290 xid = _gdk_x11_display_get_drag_protocol (display,
1291 GDK_WINDOW_XID (window->impl_window),
1298 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1307 update_wm_hints (GdkWindow *window,
1310 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1311 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1315 !toplevel->is_leader &&
1316 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1319 wm_hints.flags = StateHint | InputHint;
1320 wm_hints.input = window->accept_focus ? True : False;
1321 wm_hints.initial_state = NormalState;
1323 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1325 wm_hints.flags |= StateHint;
1326 wm_hints.initial_state = IconicState;
1329 if (toplevel->icon_pixmap)
1331 wm_hints.flags |= IconPixmapHint;
1332 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1335 if (toplevel->icon_mask)
1337 wm_hints.flags |= IconMaskHint;
1338 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1341 wm_hints.flags |= WindowGroupHint;
1342 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1344 wm_hints.flags |= WindowGroupHint;
1345 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1348 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1350 if (toplevel->urgency_hint)
1351 wm_hints.flags |= XUrgencyHint;
1353 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1354 GDK_WINDOW_XID (window),
1359 set_initial_hints (GdkWindow *window)
1361 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1362 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1363 Window xwindow = GDK_WINDOW_XID (window);
1364 GdkToplevelX11 *toplevel;
1368 toplevel = _gdk_x11_window_get_toplevel (window);
1373 update_wm_hints (window, TRUE);
1375 /* We set the spec hints regardless of whether the spec is supported,
1376 * since it can't hurt and it's kind of expensive to check whether
1382 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1384 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1385 "_NET_WM_STATE_MAXIMIZED_VERT");
1387 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1388 "_NET_WM_STATE_MAXIMIZED_HORZ");
1390 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1393 if (window->state & GDK_WINDOW_STATE_ABOVE)
1395 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1396 "_NET_WM_STATE_ABOVE");
1400 if (window->state & GDK_WINDOW_STATE_BELOW)
1402 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1403 "_NET_WM_STATE_BELOW");
1407 if (window->state & GDK_WINDOW_STATE_STICKY)
1409 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1410 "_NET_WM_STATE_STICKY");
1412 toplevel->have_sticky = TRUE;
1415 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1417 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1418 "_NET_WM_STATE_FULLSCREEN");
1420 toplevel->have_fullscreen = TRUE;
1423 if (window->modal_hint)
1425 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1426 "_NET_WM_STATE_MODAL");
1430 if (toplevel->skip_taskbar_hint)
1432 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1433 "_NET_WM_STATE_SKIP_TASKBAR");
1437 if (toplevel->skip_pager_hint)
1439 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1440 "_NET_WM_STATE_SKIP_PAGER");
1444 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1446 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1447 "_NET_WM_STATE_HIDDEN");
1449 toplevel->have_hidden = TRUE;
1454 XChangeProperty (xdisplay,
1456 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1457 XA_ATOM, 32, PropModeReplace,
1458 (guchar*) atoms, i);
1462 XDeleteProperty (xdisplay,
1464 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1467 if (window->state & GDK_WINDOW_STATE_STICKY)
1469 atoms[0] = 0xFFFFFFFF;
1470 XChangeProperty (xdisplay,
1472 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1473 XA_CARDINAL, 32, PropModeReplace,
1474 (guchar*) atoms, 1);
1475 toplevel->on_all_desktops = TRUE;
1479 XDeleteProperty (xdisplay,
1481 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1484 toplevel->map_serial = NextRequest (xdisplay);
1488 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1490 GdkDisplay *display;
1491 GdkX11Display *display_x11;
1492 GdkToplevelX11 *toplevel;
1493 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1494 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1495 Window xwindow = GDK_WINDOW_XID (window);
1498 if (!already_mapped)
1499 set_initial_hints (window);
1501 if (WINDOW_IS_TOPLEVEL (window))
1503 display = gdk_window_get_display (window);
1504 display_x11 = GDK_X11_DISPLAY (display);
1505 toplevel = _gdk_x11_window_get_toplevel (window);
1507 if (toplevel->user_time != 0 &&
1508 display_x11->user_time != 0 &&
1509 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1510 gdk_x11_window_set_user_time (window, display_x11->user_time);
1513 unset_bg = !window->input_only &&
1514 (window->window_type == GDK_WINDOW_CHILD ||
1515 impl->override_redirect) &&
1516 gdk_window_is_viewable (window);
1519 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1521 XMapWindow (xdisplay, xwindow);
1524 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1526 /* Fullscreen on current monitor is the default, no need to apply this mode
1527 * when mapping a window. This also ensures that the default behavior remains
1528 * consistent with pre-fullscreen mode implementation.
1530 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1531 gdk_x11_window_apply_fullscreen_mode (window);
1535 pre_unmap (GdkWindow *window)
1537 GdkWindow *start_window = NULL;
1539 if (window->input_only)
1542 if (window->window_type == GDK_WINDOW_CHILD)
1543 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1544 else if (window->window_type == GDK_WINDOW_TEMP)
1545 start_window = get_root (window);
1548 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1552 post_unmap (GdkWindow *window)
1554 GdkWindow *start_window = NULL;
1556 if (window->input_only)
1559 if (window->window_type == GDK_WINDOW_CHILD)
1560 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1561 else if (window->window_type == GDK_WINDOW_TEMP)
1562 start_window = get_root (window);
1566 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1568 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1570 GdkRectangle invalid_rect;
1572 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1573 invalid_rect.width = gdk_window_get_width (window);
1574 invalid_rect.height = gdk_window_get_height (window);
1575 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1576 &invalid_rect, TRUE);
1582 gdk_window_x11_hide (GdkWindow *window)
1584 /* We'll get the unmap notify eventually, and handle it then,
1585 * but checking here makes things more consistent if we are
1586 * just doing stuff ourself.
1588 _gdk_x11_window_grab_check_unmap (window,
1589 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1591 /* You can't simply unmap toplevel windows. */
1592 switch (window->window_type)
1594 case GDK_WINDOW_TOPLEVEL:
1595 case GDK_WINDOW_TEMP: /* ? */
1596 gdk_window_withdraw (window);
1599 case GDK_WINDOW_FOREIGN:
1600 case GDK_WINDOW_ROOT:
1601 case GDK_WINDOW_CHILD:
1605 _gdk_window_clear_update_area (window);
1608 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1609 GDK_WINDOW_XID (window));
1610 post_unmap (window);
1614 gdk_window_x11_withdraw (GdkWindow *window)
1616 if (!window->destroyed)
1618 if (GDK_WINDOW_IS_MAPPED (window))
1619 gdk_synthesize_window_state (window,
1621 GDK_WINDOW_STATE_WITHDRAWN);
1623 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1627 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1628 GDK_WINDOW_XID (window), 0);
1630 post_unmap (window);
1635 window_x11_move (GdkWindow *window,
1639 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1641 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1643 /* The window isn't actually damaged, but it's parent is */
1644 window_pre_damage (window);
1645 _gdk_x11_window_move_resize_child (window,
1647 window->width, window->height);
1651 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1652 GDK_WINDOW_XID (window),
1655 if (impl->override_redirect)
1664 window_x11_resize (GdkWindow *window,
1674 window_pre_damage (window);
1676 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1678 _gdk_x11_window_move_resize_child (window,
1679 window->x, window->y,
1684 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1686 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1687 GDK_WINDOW_XID (window),
1690 if (impl->override_redirect)
1692 window->width = width;
1693 window->height = height;
1694 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1698 if (width != window->width || height != window->height)
1699 window->resize_count += 1;
1703 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1707 window_x11_move_resize (GdkWindow *window,
1719 window_pre_damage (window);
1721 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1723 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1724 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1728 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1730 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1731 GDK_WINDOW_XID (window),
1732 x, y, width, height);
1734 if (impl->override_redirect)
1739 window->width = width;
1740 window->height = height;
1742 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1746 if (width != window->width || height != window->height)
1747 window->resize_count += 1;
1753 gdk_window_x11_move_resize (GdkWindow *window,
1760 if (with_move && (width < 0 && height < 0))
1761 window_x11_move (window, x, y);
1765 window_x11_move_resize (window, x, y, width, height);
1767 window_x11_resize (window, width, height);
1772 gdk_window_x11_reparent (GdkWindow *window,
1773 GdkWindow *new_parent,
1777 GdkWindowImplX11 *impl;
1779 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1781 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1782 _gdk_x11_window_tmp_unset_parent_bg (window);
1783 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1784 GDK_WINDOW_XID (window),
1785 GDK_WINDOW_XID (new_parent),
1786 new_parent->abs_x + x, new_parent->abs_y + y);
1787 _gdk_x11_window_tmp_reset_parent_bg (window);
1788 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1790 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1791 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1793 window->parent = new_parent;
1795 /* Switch the window type as appropriate */
1797 switch (GDK_WINDOW_TYPE (new_parent))
1799 case GDK_WINDOW_ROOT:
1800 case GDK_WINDOW_FOREIGN:
1801 /* Reparenting to toplevel */
1803 if (!WINDOW_IS_TOPLEVEL (window) &&
1804 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1806 /* This is also done in common code at a later stage, but we
1807 need it in setup_toplevel, so do it here too */
1808 if (window->toplevel_window_type != -1)
1809 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1810 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1811 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1813 /* Wasn't a toplevel, set up */
1814 setup_toplevel_window (window, new_parent);
1819 case GDK_WINDOW_TOPLEVEL:
1820 case GDK_WINDOW_CHILD:
1821 case GDK_WINDOW_TEMP:
1822 if (WINDOW_IS_TOPLEVEL (window) &&
1825 if (impl->toplevel->focus_window)
1827 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1828 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1831 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1833 g_free (impl->toplevel);
1834 impl->toplevel = NULL;
1842 gdk_window_x11_raise (GdkWindow *window)
1844 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1848 gdk_window_x11_restack_under (GdkWindow *window,
1849 GList *native_siblings /* in requested order, first is bottom-most */)
1855 n_windows = g_list_length (native_siblings) + 1;
1856 windows = g_new (Window, n_windows);
1858 windows[0] = GDK_WINDOW_XID (window);
1859 /* Reverse order, as input order is bottom-most first */
1861 for (l = native_siblings; l != NULL; l = l->next)
1862 windows[i--] = GDK_WINDOW_XID (l->data);
1864 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1870 gdk_window_x11_restack_toplevel (GdkWindow *window,
1874 XWindowChanges changes;
1876 changes.sibling = GDK_WINDOW_XID (sibling);
1877 changes.stack_mode = above ? Above : Below;
1878 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1879 GDK_WINDOW_XID (window),
1880 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1881 CWStackMode | CWSibling, &changes);
1885 gdk_window_x11_lower (GdkWindow *window)
1887 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1891 * gdk_x11_window_move_to_current_desktop:
1892 * @window: (type GdkX11Window): a #GdkWindow
1894 * Moves the window to the correct workspace when running under a
1895 * window manager that supports multiple workspaces, as described
1896 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
1897 * Window Manager Hints</ulink>. Will not do anything if the
1898 * window is already on all workspaces.
1903 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1905 GdkToplevelX11 *toplevel;
1907 g_return_if_fail (GDK_IS_WINDOW (window));
1908 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1910 toplevel = _gdk_x11_window_get_toplevel (window);
1912 if (toplevel->on_all_desktops)
1915 move_to_current_desktop (window);
1919 move_to_current_desktop (GdkWindow *window)
1921 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1922 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
1923 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1924 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
1931 gulong *current_desktop;
1932 GdkDisplay *display;
1934 display = gdk_window_get_display (window);
1936 /* Get current desktop, then set it; this is a race, but not
1937 * one that matters much in practice.
1939 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1940 GDK_WINDOW_XROOTWIN (window),
1941 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1943 False, XA_CARDINAL, &type, &format, &nitems,
1944 &bytes_after, &data);
1946 if (type == XA_CARDINAL)
1948 XClientMessageEvent xclient;
1949 current_desktop = (gulong *)data;
1951 memset (&xclient, 0, sizeof (xclient));
1952 xclient.type = ClientMessage;
1954 xclient.send_event = True;
1955 xclient.window = GDK_WINDOW_XID (window);
1956 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1957 xclient.format = 32;
1959 xclient.data.l[0] = *current_desktop;
1960 xclient.data.l[1] = 1; /* source indication */
1961 xclient.data.l[2] = 0;
1962 xclient.data.l[3] = 0;
1963 xclient.data.l[4] = 0;
1965 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
1966 GDK_WINDOW_XROOTWIN (window),
1968 SubstructureRedirectMask | SubstructureNotifyMask,
1969 (XEvent *)&xclient);
1971 XFree (current_desktop);
1977 gdk_x11_window_focus (GdkWindow *window,
1980 GdkDisplay *display;
1982 g_return_if_fail (GDK_IS_WINDOW (window));
1984 if (GDK_WINDOW_DESTROYED (window) ||
1985 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
1988 display = GDK_WINDOW_DISPLAY (window);
1990 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1991 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
1993 XClientMessageEvent xclient;
1995 memset (&xclient, 0, sizeof (xclient));
1996 xclient.type = ClientMessage;
1997 xclient.window = GDK_WINDOW_XID (window);
1998 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
1999 "_NET_ACTIVE_WINDOW");
2000 xclient.format = 32;
2001 xclient.data.l[0] = 1; /* requestor type; we're an app */
2002 xclient.data.l[1] = timestamp;
2003 xclient.data.l[2] = None; /* currently active window */
2004 xclient.data.l[3] = 0;
2005 xclient.data.l[4] = 0;
2007 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2008 SubstructureRedirectMask | SubstructureNotifyMask,
2009 (XEvent *)&xclient);
2013 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2015 /* There is no way of knowing reliably whether we are viewable;
2016 * so trap errors asynchronously around the XSetInputFocus call
2018 gdk_x11_display_error_trap_push (display);
2019 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2020 GDK_WINDOW_XID (window),
2023 gdk_x11_display_error_trap_pop_ignored (display);
2028 gdk_x11_window_set_type_hint (GdkWindow *window,
2029 GdkWindowTypeHint hint)
2031 GdkDisplay *display;
2034 if (GDK_WINDOW_DESTROYED (window) ||
2035 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2038 display = gdk_window_get_display (window);
2042 case GDK_WINDOW_TYPE_HINT_DIALOG:
2043 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2045 case GDK_WINDOW_TYPE_HINT_MENU:
2046 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2048 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2049 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2051 case GDK_WINDOW_TYPE_HINT_UTILITY:
2052 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2054 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2055 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2057 case GDK_WINDOW_TYPE_HINT_DOCK:
2058 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2060 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2061 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2063 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2064 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2066 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2067 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2069 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2070 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2072 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2073 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2075 case GDK_WINDOW_TYPE_HINT_COMBO:
2076 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2078 case GDK_WINDOW_TYPE_HINT_DND:
2079 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2082 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2084 case GDK_WINDOW_TYPE_HINT_NORMAL:
2085 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2089 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2090 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2091 XA_ATOM, 32, PropModeReplace,
2092 (guchar *)&atom, 1);
2095 static GdkWindowTypeHint
2096 gdk_x11_window_get_type_hint (GdkWindow *window)
2098 GdkDisplay *display;
2099 GdkWindowTypeHint type;
2102 gulong nitems_return;
2103 gulong bytes_after_return;
2104 guchar *data = NULL;
2106 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2108 if (GDK_WINDOW_DESTROYED (window) ||
2109 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2110 return GDK_WINDOW_TYPE_HINT_NORMAL;
2112 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2114 display = gdk_window_get_display (window);
2116 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2117 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2118 0, G_MAXLONG, False, XA_ATOM, &type_return,
2119 &format_return, &nitems_return, &bytes_after_return,
2122 if ((type_return == XA_ATOM) && (format_return == 32) &&
2123 (data) && (nitems_return == 1))
2125 Atom atom = *(Atom*)data;
2127 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2128 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2129 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2130 type = GDK_WINDOW_TYPE_HINT_MENU;
2131 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2132 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2133 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2134 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2135 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2136 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2137 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2138 type = GDK_WINDOW_TYPE_HINT_DOCK;
2139 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2140 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2141 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2142 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2143 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2144 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2145 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2146 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2147 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2148 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2149 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2150 type = GDK_WINDOW_TYPE_HINT_COMBO;
2151 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2152 type = GDK_WINDOW_TYPE_HINT_DND;
2155 if (type_return != None && data != NULL)
2163 gdk_wmspec_change_state (gboolean add,
2168 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2169 XClientMessageEvent xclient;
2171 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2172 #define _NET_WM_STATE_ADD 1 /* add/set property */
2173 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2175 memset (&xclient, 0, sizeof (xclient));
2176 xclient.type = ClientMessage;
2177 xclient.window = GDK_WINDOW_XID (window);
2178 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2179 xclient.format = 32;
2180 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2181 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2182 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2183 xclient.data.l[3] = 1; /* source indication */
2184 xclient.data.l[4] = 0;
2186 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2187 SubstructureRedirectMask | SubstructureNotifyMask,
2188 (XEvent *)&xclient);
2192 gdk_x11_window_set_modal_hint (GdkWindow *window,
2195 if (GDK_WINDOW_DESTROYED (window) ||
2196 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2199 window->modal_hint = modal;
2201 if (GDK_WINDOW_IS_MAPPED (window))
2202 gdk_wmspec_change_state (modal, window,
2203 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2208 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2209 gboolean skips_taskbar)
2211 GdkToplevelX11 *toplevel;
2213 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2215 if (GDK_WINDOW_DESTROYED (window) ||
2216 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2219 toplevel = _gdk_x11_window_get_toplevel (window);
2220 toplevel->skip_taskbar_hint = skips_taskbar;
2222 if (GDK_WINDOW_IS_MAPPED (window))
2223 gdk_wmspec_change_state (skips_taskbar, window,
2224 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2229 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2230 gboolean skips_pager)
2232 GdkToplevelX11 *toplevel;
2234 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2236 if (GDK_WINDOW_DESTROYED (window) ||
2237 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2240 toplevel = _gdk_x11_window_get_toplevel (window);
2241 toplevel->skip_pager_hint = skips_pager;
2243 if (GDK_WINDOW_IS_MAPPED (window))
2244 gdk_wmspec_change_state (skips_pager, window,
2245 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2250 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2253 GdkToplevelX11 *toplevel;
2255 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2257 if (GDK_WINDOW_DESTROYED (window) ||
2258 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2261 toplevel = _gdk_x11_window_get_toplevel (window);
2262 toplevel->urgency_hint = urgent;
2264 update_wm_hints (window, FALSE);
2268 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2269 const GdkGeometry *geometry,
2270 GdkWindowHints geom_mask)
2272 XSizeHints size_hints;
2274 if (GDK_WINDOW_DESTROYED (window) ||
2275 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2278 size_hints.flags = 0;
2280 if (geom_mask & GDK_HINT_POS)
2282 size_hints.flags |= PPosition;
2283 /* We need to initialize the following obsolete fields because KWM
2284 * apparently uses these fields if they are non-zero.
2291 if (geom_mask & GDK_HINT_USER_POS)
2293 size_hints.flags |= USPosition;
2296 if (geom_mask & GDK_HINT_USER_SIZE)
2298 size_hints.flags |= USSize;
2301 if (geom_mask & GDK_HINT_MIN_SIZE)
2303 size_hints.flags |= PMinSize;
2304 size_hints.min_width = geometry->min_width;
2305 size_hints.min_height = geometry->min_height;
2308 if (geom_mask & GDK_HINT_MAX_SIZE)
2310 size_hints.flags |= PMaxSize;
2311 size_hints.max_width = MAX (geometry->max_width, 1);
2312 size_hints.max_height = MAX (geometry->max_height, 1);
2315 if (geom_mask & GDK_HINT_BASE_SIZE)
2317 size_hints.flags |= PBaseSize;
2318 size_hints.base_width = geometry->base_width;
2319 size_hints.base_height = geometry->base_height;
2322 if (geom_mask & GDK_HINT_RESIZE_INC)
2324 size_hints.flags |= PResizeInc;
2325 size_hints.width_inc = geometry->width_inc;
2326 size_hints.height_inc = geometry->height_inc;
2329 if (geom_mask & GDK_HINT_ASPECT)
2331 size_hints.flags |= PAspect;
2332 if (geometry->min_aspect <= 1)
2334 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2335 size_hints.min_aspect.y = 65536;
2339 size_hints.min_aspect.x = 65536;
2340 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2342 if (geometry->max_aspect <= 1)
2344 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2345 size_hints.max_aspect.y = 65536;
2349 size_hints.max_aspect.x = 65536;
2350 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2354 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2356 size_hints.flags |= PWinGravity;
2357 size_hints.win_gravity = geometry->win_gravity;
2360 /* FIXME: Would it be better to delete this property if
2361 * geom_mask == 0? It would save space on the server
2363 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2364 GDK_WINDOW_XID (window),
2369 gdk_window_get_geometry_hints (GdkWindow *window,
2370 GdkGeometry *geometry,
2371 GdkWindowHints *geom_mask)
2373 XSizeHints *size_hints;
2374 glong junk_supplied_mask = 0;
2376 g_return_if_fail (GDK_IS_WINDOW (window));
2377 g_return_if_fail (geometry != NULL);
2378 g_return_if_fail (geom_mask != NULL);
2382 if (GDK_WINDOW_DESTROYED (window) ||
2383 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2386 size_hints = XAllocSizeHints ();
2390 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2391 GDK_WINDOW_XID (window),
2393 &junk_supplied_mask))
2394 size_hints->flags = 0;
2396 if (size_hints->flags & PMinSize)
2398 *geom_mask |= GDK_HINT_MIN_SIZE;
2399 geometry->min_width = size_hints->min_width;
2400 geometry->min_height = size_hints->min_height;
2403 if (size_hints->flags & PMaxSize)
2405 *geom_mask |= GDK_HINT_MAX_SIZE;
2406 geometry->max_width = MAX (size_hints->max_width, 1);
2407 geometry->max_height = MAX (size_hints->max_height, 1);
2410 if (size_hints->flags & PResizeInc)
2412 *geom_mask |= GDK_HINT_RESIZE_INC;
2413 geometry->width_inc = size_hints->width_inc;
2414 geometry->height_inc = size_hints->height_inc;
2417 if (size_hints->flags & PAspect)
2419 *geom_mask |= GDK_HINT_ASPECT;
2421 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2422 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2425 if (size_hints->flags & PWinGravity)
2427 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2428 geometry->win_gravity = size_hints->win_gravity;
2435 utf8_is_latin1 (const gchar *str)
2437 const char *p = str;
2441 gunichar ch = g_utf8_get_char (p);
2446 p = g_utf8_next_char (p);
2452 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2453 * convertable to STRING, otherwise, set it as compound text
2456 set_text_property (GdkDisplay *display,
2459 const gchar *utf8_str)
2461 gchar *prop_text = NULL;
2465 gboolean is_compound_text;
2467 if (utf8_is_latin1 (utf8_str))
2469 prop_type = XA_STRING;
2470 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2471 prop_length = prop_text ? strlen (prop_text) : 0;
2473 is_compound_text = FALSE;
2479 gdk_x11_display_utf8_to_compound_text (display,
2480 utf8_str, &gdk_type, &prop_format,
2481 (guchar **)&prop_text, &prop_length);
2482 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2483 is_compound_text = TRUE;
2488 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2491 prop_type, prop_format,
2492 PropModeReplace, (guchar *)prop_text,
2495 if (is_compound_text)
2496 gdk_x11_free_compound_text ((guchar *)prop_text);
2502 /* Set WM_NAME and _NET_WM_NAME
2505 set_wm_name (GdkDisplay *display,
2509 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2510 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2511 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2512 PropModeReplace, (guchar *)name, strlen (name));
2514 set_text_property (display, xwindow,
2515 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2520 gdk_x11_window_set_title (GdkWindow *window,
2523 GdkDisplay *display;
2527 g_return_if_fail (title != NULL);
2529 if (GDK_WINDOW_DESTROYED (window) ||
2530 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2533 display = gdk_window_get_display (window);
2534 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2535 xwindow = GDK_WINDOW_XID (window);
2537 set_wm_name (display, xwindow, title);
2539 if (!gdk_window_icon_name_set (window))
2541 XChangeProperty (xdisplay, xwindow,
2542 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2543 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2544 PropModeReplace, (guchar *)title, strlen (title));
2546 set_text_property (display, xwindow,
2547 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2553 gdk_x11_window_set_role (GdkWindow *window,
2556 GdkDisplay *display;
2558 display = gdk_window_get_display (window);
2560 if (GDK_WINDOW_DESTROYED (window) ||
2561 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2565 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2566 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2567 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2569 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2570 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2574 gdk_x11_window_set_startup_id (GdkWindow *window,
2575 const gchar *startup_id)
2577 GdkDisplay *display;
2579 g_return_if_fail (GDK_IS_WINDOW (window));
2581 display = gdk_window_get_display (window);
2583 if (GDK_WINDOW_DESTROYED (window) ||
2584 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2588 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2589 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2590 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2591 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2593 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2594 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2598 gdk_x11_window_set_transient_for (GdkWindow *window,
2601 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2602 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2603 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2604 GDK_WINDOW_XID (window),
2605 GDK_WINDOW_XID (parent));
2609 gdk_window_x11_set_back_color (GdkWindow *window,
2615 GdkVisual *visual = gdk_window_get_visual (window);
2617 /* I suppose we could handle these, but that'd require fiddling with
2618 * xrender formats... */
2622 switch (visual->type)
2624 case GDK_VISUAL_DIRECT_COLOR:
2625 case GDK_VISUAL_TRUE_COLOR:
2627 /* If bits not used for color are used for something other than padding,
2628 * it's likely alpha, so we set them to 1s.
2630 guint padding, pixel;
2632 /* Shifting by >= width-of-type isn't defined in C */
2633 if (visual->depth >= 32)
2636 padding = ((~(guint32)0)) << visual->depth;
2638 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2640 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2641 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2642 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2644 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2645 GDK_WINDOW_XID (window), pixel);
2649 /* These require fiddling with the colormap, and as they're essentially unused
2650 * we're just gonna skip them for now.
2652 case GDK_VISUAL_PSEUDO_COLOR:
2653 case GDK_VISUAL_GRAYSCALE:
2654 case GDK_VISUAL_STATIC_GRAY:
2655 case GDK_VISUAL_STATIC_COLOR:
2664 matrix_is_identity (cairo_matrix_t *matrix)
2666 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2667 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2668 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2672 gdk_window_x11_set_background (GdkWindow *window,
2673 cairo_pattern_t *pattern)
2676 cairo_surface_t *surface;
2677 cairo_matrix_t matrix;
2679 if (GDK_WINDOW_DESTROYED (window))
2682 if (pattern == NULL)
2686 /* X throws BadMatch if the parent has a different visual when
2687 * using ParentRelative */
2688 parent = gdk_window_get_parent (window);
2689 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2690 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2691 GDK_WINDOW_XID (window), ParentRelative);
2693 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2694 GDK_WINDOW_XID (window), None);
2698 switch (cairo_pattern_get_type (pattern))
2700 case CAIRO_PATTERN_TYPE_SOLID:
2701 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2702 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2705 case CAIRO_PATTERN_TYPE_SURFACE:
2706 cairo_pattern_get_matrix (pattern, &matrix);
2707 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2708 matrix_is_identity (&matrix) &&
2709 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2710 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2711 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2715 cairo_surface_get_device_offset (surface, &x, &y);
2716 /* XXX: This still bombs for non-pixmaps, but there's no way to
2717 * detect we're not a pixmap in Cairo... */
2718 if (x == 0.0 && y == 0.0)
2720 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2721 GDK_WINDOW_XID (window),
2722 cairo_xlib_surface_get_drawable (surface));
2727 case CAIRO_PATTERN_TYPE_LINEAR:
2728 case CAIRO_PATTERN_TYPE_RADIAL:
2730 /* fallback: just use black */
2734 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2735 GDK_WINDOW_XID (window), None);
2739 gdk_window_x11_set_device_cursor (GdkWindow *window,
2743 GdkWindowImplX11 *impl;
2745 g_return_if_fail (GDK_IS_WINDOW (window));
2746 g_return_if_fail (GDK_IS_DEVICE (device));
2748 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2751 g_hash_table_remove (impl->device_cursor, device);
2754 _gdk_x11_cursor_update_theme (cursor);
2755 g_hash_table_replace (impl->device_cursor,
2756 device, g_object_ref (cursor));
2759 if (!GDK_WINDOW_DESTROYED (window))
2760 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2764 _gdk_x11_window_get_cursor (GdkWindow *window)
2766 GdkWindowImplX11 *impl;
2768 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2770 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2772 return impl->cursor;
2776 gdk_window_x11_get_geometry (GdkWindow *window,
2787 guint tborder_width;
2790 if (!GDK_WINDOW_DESTROYED (window))
2792 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2793 GDK_WINDOW_XID (window),
2794 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2808 gdk_window_x11_get_root_coords (GdkWindow *window,
2819 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2820 GDK_WINDOW_XID (window),
2821 GDK_WINDOW_XROOTWIN (window),
2834 gdk_x11_window_get_root_origin (GdkWindow *window,
2840 gdk_window_get_frame_extents (window, &rect);
2850 gdk_x11_window_get_frame_extents (GdkWindow *window,
2853 GdkDisplay *display;
2854 GdkWindowImplX11 *impl;
2865 gulong nitems_return;
2866 gulong bytes_after_return;
2869 guint ww, wh, wb, wd;
2871 gboolean got_frame_extents = FALSE;
2873 g_return_if_fail (rect != NULL);
2880 while (window->parent && (window->parent)->parent)
2881 window = window->parent;
2883 /* Refine our fallback answer a bit using local information */
2884 rect->x = window->x;
2885 rect->y = window->y;
2886 rect->width = window->width;
2887 rect->height = window->height;
2889 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2890 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2896 display = gdk_window_get_display (window);
2898 gdk_x11_display_error_trap_push (display);
2900 xwindow = GDK_WINDOW_XID (window);
2902 /* first try: use _NET_FRAME_EXTENTS */
2903 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2904 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
2905 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2906 gdk_x11_get_xatom_by_name_for_display (display,
2907 "_NET_FRAME_EXTENTS"),
2908 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2909 &format_return, &nitems_return, &bytes_after_return,
2913 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2914 (nitems_return == 4) && (data))
2916 gulong *ldata = (gulong *) data;
2917 got_frame_extents = TRUE;
2919 /* try to get the real client window geometry */
2920 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2921 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2922 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2923 xwindow, root, 0, 0, &wx, &wy, &child))
2931 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2932 rect->x -= ldata[0];
2933 rect->y -= ldata[2];
2934 rect->width += ldata[0] + ldata[1];
2935 rect->height += ldata[2] + ldata[3];
2942 if (got_frame_extents)
2945 /* no frame extents property available, which means we either have a WM that
2946 is not EWMH compliant or is broken - try fallback and walk up the window
2947 tree to get our window's parent which hopefully is the window frame */
2949 /* use NETWM_VIRTUAL_ROOTS if available */
2950 root = GDK_WINDOW_XROOTWIN (window);
2952 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2953 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
2954 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
2955 gdk_x11_get_xatom_by_name_for_display (display,
2956 "_NET_VIRTUAL_ROOTS"),
2957 0, G_MAXLONG, False, XA_WINDOW, &type_return,
2958 &format_return, &nitems_return, &bytes_after_return,
2962 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
2964 nvroots = nitems_return;
2965 vroots = (Window *)data;
2969 xparent = GDK_WINDOW_XID (window);
2975 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
2977 &children, &nchildren))
2983 /* check virtual roots */
2984 for (i = 0; i < nvroots; i++)
2986 if (xparent == vroots[i])
2993 while (xparent != root);
2995 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2996 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3008 gdk_x11_display_error_trap_pop_ignored (display);
3012 gdk_window_x11_get_device_state (GdkWindow *window,
3016 GdkModifierType *mask)
3020 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3022 if (GDK_WINDOW_DESTROYED (window))
3025 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3029 return child != NULL;
3033 gdk_window_x11_get_events (GdkWindow *window)
3035 XWindowAttributes attrs;
3036 GdkEventMask event_mask;
3037 GdkEventMask filtered;
3039 if (GDK_WINDOW_DESTROYED (window))
3043 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3044 GDK_WINDOW_XID (window),
3046 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3047 /* if property change was filtered out before, keep it filtered out */
3048 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3049 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3055 gdk_window_x11_set_events (GdkWindow *window,
3056 GdkEventMask event_mask)
3058 long xevent_mask = 0;
3060 if (!GDK_WINDOW_DESTROYED (window))
3062 GdkX11Display *display_x11;
3064 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3065 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3067 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3068 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3069 GDK_WINDOW_XID (window), event_mask,
3075 do_shape_combine_region (GdkWindow *window,
3076 const cairo_region_t *shape_region,
3081 if (GDK_WINDOW_DESTROYED (window))
3084 if (shape_region == NULL)
3086 /* Use NULL mask to unset the shape */
3087 if (shape == ShapeBounding
3088 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3089 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3091 if (shape == ShapeBounding)
3093 _gdk_x11_window_tmp_unset_parent_bg (window);
3094 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3096 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3097 GDK_WINDOW_XID (window),
3102 if (shape == ShapeBounding)
3104 _gdk_x11_window_tmp_reset_parent_bg (window);
3105 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3111 if (shape == ShapeBounding
3112 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3113 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3116 XRectangle *xrects = NULL;
3118 _gdk_x11_region_get_xrectangles (shape_region,
3122 if (shape == ShapeBounding)
3124 _gdk_x11_window_tmp_unset_parent_bg (window);
3125 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3127 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3128 GDK_WINDOW_XID (window),
3135 if (shape == ShapeBounding)
3137 _gdk_x11_window_tmp_reset_parent_bg (window);
3138 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3146 gdk_window_x11_shape_combine_region (GdkWindow *window,
3147 const cairo_region_t *shape_region,
3151 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3155 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3156 const cairo_region_t *shape_region,
3161 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3167 gdk_x11_window_set_override_redirect (GdkWindow *window,
3168 gboolean override_redirect)
3170 XSetWindowAttributes attr;
3172 if (!GDK_WINDOW_DESTROYED (window) &&
3173 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3175 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3177 attr.override_redirect = (override_redirect? True : False);
3178 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3179 GDK_WINDOW_XID (window),
3183 impl->override_redirect = attr.override_redirect;
3188 gdk_x11_window_set_accept_focus (GdkWindow *window,
3189 gboolean accept_focus)
3191 accept_focus = accept_focus != FALSE;
3193 if (window->accept_focus != accept_focus)
3195 window->accept_focus = accept_focus;
3197 if (!GDK_WINDOW_DESTROYED (window) &&
3198 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3199 update_wm_hints (window, FALSE);
3204 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3205 gboolean focus_on_map)
3207 focus_on_map = focus_on_map != FALSE;
3209 if (window->focus_on_map != focus_on_map)
3211 window->focus_on_map = focus_on_map;
3213 if ((!GDK_WINDOW_DESTROYED (window)) &&
3214 (!window->focus_on_map) &&
3215 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3216 gdk_x11_window_set_user_time (window, 0);
3221 * gdk_x11_window_set_user_time:
3222 * @window: (type GdkX11Window): A toplevel #GdkWindow
3223 * @timestamp: An XServer timestamp to which the property should be set
3225 * The application can use this call to update the _NET_WM_USER_TIME
3226 * property on a toplevel window. This property stores an Xserver
3227 * time which represents the time of the last user input event
3228 * received for this window. This property may be used by the window
3229 * manager to alter the focus, stacking, and/or placement behavior of
3230 * windows when they are mapped depending on whether the new window
3231 * was created by a user action or is a "pop-up" window activated by a
3232 * timer or some other event.
3234 * Note that this property is automatically updated by GDK, so this
3235 * function should only be used by applications which handle input
3236 * events bypassing GDK.
3241 gdk_x11_window_set_user_time (GdkWindow *window,
3244 GdkDisplay *display;
3245 GdkX11Display *display_x11;
3246 GdkToplevelX11 *toplevel;
3247 glong timestamp_long = (glong)timestamp;
3250 if (GDK_WINDOW_DESTROYED (window) ||
3251 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3254 display = gdk_window_get_display (window);
3255 display_x11 = GDK_X11_DISPLAY (display);
3256 toplevel = _gdk_x11_window_get_toplevel (window);
3260 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3264 if (toplevel->focus_window != None &&
3265 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3266 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3267 xid = toplevel->focus_window;
3269 xid = GDK_WINDOW_XID (window);
3271 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3272 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3273 XA_CARDINAL, 32, PropModeReplace,
3274 (guchar *)×tamp_long, 1);
3276 if (timestamp_long != GDK_CURRENT_TIME &&
3277 (display_x11->user_time == GDK_CURRENT_TIME ||
3278 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3279 display_x11->user_time = timestamp_long;
3282 toplevel->user_time = timestamp_long;
3286 * gdk_x11_window_set_utf8_property:
3287 * @window: (type GdkX11Window): a #GdkWindow
3288 * @name: Property name, will be interned as an X atom
3289 * @value: (allow-none): Property value, or %NULL to delete
3291 * This function modifies or removes an arbitrary X11 window
3292 * property of type UTF8_STRING. If the given @window is
3293 * not a toplevel window, it is ignored.
3298 gdk_x11_window_set_utf8_property (GdkWindow *window,
3302 GdkDisplay *display;
3304 if (!WINDOW_IS_TOPLEVEL (window))
3307 display = gdk_window_get_display (window);
3311 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3312 GDK_WINDOW_XID (window),
3313 gdk_x11_get_xatom_by_name_for_display (display, name),
3314 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3315 PropModeReplace, (guchar *)value, strlen (value));
3319 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3320 GDK_WINDOW_XID (window),
3321 gdk_x11_get_xatom_by_name_for_display (display, name));
3326 * gdk_x11_window_set_hide_titlebar_when_maximized:
3327 * @window: (type GdkX11Window): a #GdkWindow
3328 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3331 * Set a hint for the window manager, requesting that the titlebar
3332 * should be hidden when the window is maximized.
3334 * Note that this property is automatically updated by GTK+, so this
3335 * function should only be used by applications which do not use GTK+
3336 * to create toplevel windows.
3341 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3342 gboolean hide_titlebar_when_maximized)
3344 GdkDisplay *display;
3346 if (!WINDOW_IS_TOPLEVEL (window))
3349 display = gdk_window_get_display (window);
3351 if (hide_titlebar_when_maximized)
3354 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3355 GDK_WINDOW_XID (window),
3356 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3358 PropModeReplace, (guchar *)&hide, 1);
3362 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3363 GDK_WINDOW_XID (window),
3364 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3369 * gdk_x11_window_set_theme_variant:
3370 * @window: (type GdkX11Window): a #GdkWindow
3371 * @variant: the theme variant to export
3373 * GTK+ applications can request a dark theme variant. In order to
3374 * make other applications - namely window managers using GTK+ for
3375 * themeing - aware of this choice, GTK+ uses this function to
3376 * export the requested theme variant as _GTK_THEME_VARIANT property
3377 * on toplevel windows.
3379 * Note that this property is automatically updated by GTK+, so this
3380 * function should only be used by applications which do not use GTK+
3381 * to create toplevel windows.
3386 gdk_x11_window_set_theme_variant (GdkWindow *window,
3389 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3392 #define GDK_SELECTION_MAX_SIZE(display) \
3394 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3395 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3396 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3399 gdk_window_update_icon (GdkWindow *window,
3402 GdkToplevelX11 *toplevel;
3403 GdkPixbuf *best_icon;
3407 toplevel = _gdk_x11_window_get_toplevel (window);
3409 if (toplevel->icon_pixmap != NULL)
3411 cairo_surface_destroy (toplevel->icon_pixmap);
3412 toplevel->icon_pixmap = NULL;
3415 if (toplevel->icon_mask != NULL)
3417 cairo_surface_destroy (toplevel->icon_mask);
3418 toplevel->icon_mask = NULL;
3421 #define IDEAL_SIZE 48
3423 best_size = G_MAXINT;
3425 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3427 GdkPixbuf *pixbuf = tmp_list->data;
3430 /* average width and height - if someone passes in a rectangular
3431 * icon they deserve what they get.
3433 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3436 if (best_icon == NULL)
3443 /* icon is better if it's 32 pixels or larger, and closer to
3444 * the ideal size than the current best.
3447 (ABS (best_size - IDEAL_SIZE) <
3448 ABS (this - IDEAL_SIZE)))
3458 int width = gdk_pixbuf_get_width (best_icon);
3459 int height = gdk_pixbuf_get_height (best_icon);
3462 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3466 cr = cairo_create (toplevel->icon_pixmap);
3467 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3468 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3469 if (gdk_pixbuf_get_has_alpha (best_icon))
3471 /* Saturate the image, so it has bilevel alpha */
3472 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3474 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3476 cairo_pop_group_to_source (cr);
3481 if (gdk_pixbuf_get_has_alpha (best_icon))
3483 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3487 cr = cairo_create (toplevel->icon_mask);
3488 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3489 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3495 update_wm_hints (window, FALSE);
3499 gdk_x11_window_set_icon_list (GdkWindow *window,
3508 gint width, height, stride;
3511 GdkDisplay *display;
3514 if (GDK_WINDOW_DESTROYED (window) ||
3515 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3518 display = gdk_window_get_display (window);
3526 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3528 width = gdk_pixbuf_get_width (pixbuf);
3529 height = gdk_pixbuf_get_height (pixbuf);
3531 /* silently ignore overlarge icons */
3532 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3534 g_warning ("gdk_window_set_icon_list: icons too large");
3539 size += 2 + width * height;
3541 l = g_list_next (l);
3544 data = g_malloc (size * sizeof (gulong));
3552 width = gdk_pixbuf_get_width (pixbuf);
3553 height = gdk_pixbuf_get_height (pixbuf);
3554 stride = gdk_pixbuf_get_rowstride (pixbuf);
3555 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3560 pixels = gdk_pixbuf_get_pixels (pixbuf);
3562 for (y = 0; y < height; y++)
3564 for (x = 0; x < width; x++)
3568 r = pixels[y*stride + x*n_channels + 0];
3569 g = pixels[y*stride + x*n_channels + 1];
3570 b = pixels[y*stride + x*n_channels + 2];
3571 if (n_channels >= 4)
3572 a = pixels[y*stride + x*n_channels + 3];
3576 *p++ = a << 24 | r << 16 | g << 8 | b ;
3580 l = g_list_next (l);
3586 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3587 GDK_WINDOW_XID (window),
3588 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3591 (guchar*) data, size);
3595 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3596 GDK_WINDOW_XID (window),
3597 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3602 gdk_window_update_icon (window, pixbufs);
3606 gdk_window_icon_name_set (GdkWindow *window)
3608 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3609 g_quark_from_static_string ("gdk-icon-name-set")));
3613 gdk_x11_window_set_icon_name (GdkWindow *window,
3616 GdkDisplay *display;
3618 if (GDK_WINDOW_DESTROYED (window) ||
3619 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3622 display = gdk_window_get_display (window);
3624 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3625 GUINT_TO_POINTER (name != NULL));
3629 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3630 GDK_WINDOW_XID (window),
3631 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3632 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3633 PropModeReplace, (guchar *)name, strlen (name));
3635 set_text_property (display, GDK_WINDOW_XID (window),
3636 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3641 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3642 GDK_WINDOW_XID (window),
3643 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3644 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3645 GDK_WINDOW_XID (window),
3646 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3651 gdk_x11_window_iconify (GdkWindow *window)
3653 if (GDK_WINDOW_DESTROYED (window) ||
3654 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3657 if (GDK_WINDOW_IS_MAPPED (window))
3659 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3660 GDK_WINDOW_XID (window),
3661 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3665 /* Flip our client side flag, the real work happens on map. */
3666 gdk_synthesize_window_state (window,
3668 GDK_WINDOW_STATE_ICONIFIED);
3669 gdk_wmspec_change_state (TRUE, window,
3670 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3676 gdk_x11_window_deiconify (GdkWindow *window)
3678 if (GDK_WINDOW_DESTROYED (window) ||
3679 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3682 if (GDK_WINDOW_IS_MAPPED (window))
3684 gdk_window_show (window);
3685 gdk_wmspec_change_state (FALSE, window,
3686 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3691 /* Flip our client side flag, the real work happens on map. */
3692 gdk_synthesize_window_state (window,
3693 GDK_WINDOW_STATE_ICONIFIED,
3695 gdk_wmspec_change_state (FALSE, window,
3696 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3702 gdk_x11_window_stick (GdkWindow *window)
3704 if (GDK_WINDOW_DESTROYED (window) ||
3705 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3708 if (GDK_WINDOW_IS_MAPPED (window))
3710 /* "stick" means stick to all desktops _and_ do not scroll with the
3711 * viewport. i.e. glue to the monitor glass in all cases.
3714 XClientMessageEvent xclient;
3716 /* Request stick during viewport scroll */
3717 gdk_wmspec_change_state (TRUE, window,
3718 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3721 /* Request desktop 0xFFFFFFFF */
3722 memset (&xclient, 0, sizeof (xclient));
3723 xclient.type = ClientMessage;
3724 xclient.window = GDK_WINDOW_XID (window);
3725 xclient.display = GDK_WINDOW_XDISPLAY (window);
3726 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3728 xclient.format = 32;
3730 xclient.data.l[0] = 0xFFFFFFFF;
3731 xclient.data.l[1] = 0;
3732 xclient.data.l[2] = 0;
3733 xclient.data.l[3] = 0;
3734 xclient.data.l[4] = 0;
3736 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3737 SubstructureRedirectMask | SubstructureNotifyMask,
3738 (XEvent *)&xclient);
3742 /* Flip our client side flag, the real work happens on map. */
3743 gdk_synthesize_window_state (window,
3745 GDK_WINDOW_STATE_STICKY);
3750 gdk_x11_window_unstick (GdkWindow *window)
3752 if (GDK_WINDOW_DESTROYED (window) ||
3753 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3756 if (GDK_WINDOW_IS_MAPPED (window))
3758 /* Request unstick from viewport */
3759 gdk_wmspec_change_state (FALSE, window,
3760 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3763 move_to_current_desktop (window);
3767 /* Flip our client side flag, the real work happens on map. */
3768 gdk_synthesize_window_state (window,
3769 GDK_WINDOW_STATE_STICKY,
3776 gdk_x11_window_maximize (GdkWindow *window)
3778 if (GDK_WINDOW_DESTROYED (window) ||
3779 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3782 if (GDK_WINDOW_IS_MAPPED (window))
3783 gdk_wmspec_change_state (TRUE, window,
3784 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3785 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3787 gdk_synthesize_window_state (window,
3789 GDK_WINDOW_STATE_MAXIMIZED);
3793 gdk_x11_window_unmaximize (GdkWindow *window)
3795 if (GDK_WINDOW_DESTROYED (window) ||
3796 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3799 if (GDK_WINDOW_IS_MAPPED (window))
3800 gdk_wmspec_change_state (FALSE, window,
3801 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3802 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3804 gdk_synthesize_window_state (window,
3805 GDK_WINDOW_STATE_MAXIMIZED,
3810 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3812 if (GDK_WINDOW_DESTROYED (window) ||
3813 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3816 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3817 * to which monitors so span across when the window is fullscreen, but it's
3818 * not a state in itself so this would have no effect if the window is not
3822 if (GDK_WINDOW_IS_MAPPED (window))
3824 XClientMessageEvent xclient;
3825 gint gdk_monitors[4];
3828 memset (&xclient, 0, sizeof (xclient));
3829 xclient.type = ClientMessage;
3830 xclient.window = GDK_WINDOW_XID (window);
3831 xclient.display = GDK_WINDOW_XDISPLAY (window);
3832 xclient.format = 32;
3834 switch (window->fullscreen_mode)
3836 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3838 /* FIXME: This is not part of the EWMH spec!
3840 * There is no documented mechanism to remove the property
3841 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3842 * invalid, largest possible value.
3844 * When given values larger than actual possible monitor values, most
3845 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3846 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3849 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3851 * Note, this (non documented) mechanism is unlikely to be an issue
3852 * as it's used only for transitionning back from "all monitors" to
3853 * "current monitor" mode.
3855 * Applications who don't change the default mode won't trigger this
3858 for (i = 0; i < 4; ++i)
3859 xclient.data.l[i] = G_MAXLONG;
3863 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3865 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3870 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3871 for (i = 0; i < 4; ++i)
3873 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3875 /* Sanity check, if XINERAMA is not available, we could have invalid
3876 * negative values for the XINERAMA indices.
3878 if (xclient.data.l[i] < 0)
3880 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3887 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3888 window->fullscreen_mode);
3892 /* Send fullscreen monitors client message */
3893 xclient.data.l[4] = 1; /* source indication */
3894 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3895 "_NET_WM_FULLSCREEN_MONITORS");
3896 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3897 SubstructureRedirectMask | SubstructureNotifyMask,
3898 (XEvent *)&xclient);
3903 gdk_x11_window_fullscreen (GdkWindow *window)
3905 if (GDK_WINDOW_DESTROYED (window) ||
3906 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3909 if (GDK_WINDOW_IS_MAPPED (window))
3911 gdk_wmspec_change_state (TRUE, window,
3912 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3914 /* Actual XRandR layout may have change since we computed the fullscreen
3915 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
3917 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
3918 gdk_x11_window_apply_fullscreen_mode (window);
3921 gdk_synthesize_window_state (window,
3923 GDK_WINDOW_STATE_FULLSCREEN);
3927 gdk_x11_window_unfullscreen (GdkWindow *window)
3929 if (GDK_WINDOW_DESTROYED (window) ||
3930 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3933 if (GDK_WINDOW_IS_MAPPED (window))
3934 gdk_wmspec_change_state (FALSE, window,
3935 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3939 gdk_synthesize_window_state (window,
3940 GDK_WINDOW_STATE_FULLSCREEN,
3945 gdk_x11_window_set_keep_above (GdkWindow *window,
3948 g_return_if_fail (GDK_IS_WINDOW (window));
3950 if (GDK_WINDOW_DESTROYED (window) ||
3951 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3954 if (GDK_WINDOW_IS_MAPPED (window))
3957 gdk_wmspec_change_state (FALSE, window,
3958 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3960 gdk_wmspec_change_state (setting, window,
3961 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3965 gdk_synthesize_window_state (window,
3966 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3967 setting ? GDK_WINDOW_STATE_ABOVE : 0);
3971 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
3973 g_return_if_fail (GDK_IS_WINDOW (window));
3975 if (GDK_WINDOW_DESTROYED (window) ||
3976 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3979 if (GDK_WINDOW_IS_MAPPED (window))
3982 gdk_wmspec_change_state (FALSE, window,
3983 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3985 gdk_wmspec_change_state (setting, window,
3986 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3990 gdk_synthesize_window_state (window,
3991 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
3992 setting ? GDK_WINDOW_STATE_BELOW : 0);
3996 gdk_x11_window_get_group (GdkWindow *window)
3998 GdkToplevelX11 *toplevel;
4000 if (GDK_WINDOW_DESTROYED (window) ||
4001 !WINDOW_IS_TOPLEVEL (window))
4004 toplevel = _gdk_x11_window_get_toplevel (window);
4006 return toplevel->group_leader;
4010 gdk_x11_window_set_group (GdkWindow *window,
4013 GdkToplevelX11 *toplevel;
4015 g_return_if_fail (GDK_IS_WINDOW (window));
4016 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4017 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4019 if (GDK_WINDOW_DESTROYED (window) ||
4020 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4021 !WINDOW_IS_TOPLEVEL (window))
4024 toplevel = _gdk_x11_window_get_toplevel (window);
4027 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4029 if (toplevel->group_leader != leader)
4031 if (toplevel->group_leader)
4032 g_object_unref (toplevel->group_leader);
4033 toplevel->group_leader = g_object_ref (leader);
4034 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4037 update_wm_hints (window, FALSE);
4040 static MotifWmHints *
4041 gdk_window_get_mwm_hints (GdkWindow *window)
4043 GdkDisplay *display;
4044 Atom hints_atom = None;
4051 if (GDK_WINDOW_DESTROYED (window))
4054 display = gdk_window_get_display (window);
4056 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4058 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4059 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4060 False, AnyPropertyType, &type, &format, &nitems,
4061 &bytes_after, &data);
4066 return (MotifWmHints *)data;
4070 gdk_window_set_mwm_hints (GdkWindow *window,
4071 MotifWmHints *new_hints)
4073 GdkDisplay *display;
4074 Atom hints_atom = None;
4076 MotifWmHints *hints;
4082 if (GDK_WINDOW_DESTROYED (window))
4085 display = gdk_window_get_display (window);
4087 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4089 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4090 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4091 False, AnyPropertyType, &type, &format, &nitems,
4092 &bytes_after, &data);
4098 hints = (MotifWmHints *)data;
4100 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4102 hints->flags |= MWM_HINTS_FUNCTIONS;
4103 hints->functions = new_hints->functions;
4105 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4107 hints->flags |= MWM_HINTS_DECORATIONS;
4108 hints->decorations = new_hints->decorations;
4112 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4113 hints_atom, hints_atom, 32, PropModeReplace,
4114 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4116 if (hints != new_hints)
4121 gdk_x11_window_set_decorations (GdkWindow *window,
4122 GdkWMDecoration decorations)
4126 if (GDK_WINDOW_DESTROYED (window) ||
4127 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4130 /* initialize to zero to avoid writing uninitialized data to socket */
4131 memset(&hints, 0, sizeof(hints));
4132 hints.flags = MWM_HINTS_DECORATIONS;
4133 hints.decorations = decorations;
4135 gdk_window_set_mwm_hints (window, &hints);
4139 gdk_x11_window_get_decorations(GdkWindow *window,
4140 GdkWMDecoration *decorations)
4142 MotifWmHints *hints;
4143 gboolean result = FALSE;
4145 if (GDK_WINDOW_DESTROYED (window) ||
4146 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4149 hints = gdk_window_get_mwm_hints (window);
4153 if (hints->flags & MWM_HINTS_DECORATIONS)
4156 *decorations = hints->decorations;
4167 gdk_x11_window_set_functions (GdkWindow *window,
4168 GdkWMFunction functions)
4172 g_return_if_fail (GDK_IS_WINDOW (window));
4174 if (GDK_WINDOW_DESTROYED (window) ||
4175 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4178 /* initialize to zero to avoid writing uninitialized data to socket */
4179 memset(&hints, 0, sizeof(hints));
4180 hints.flags = MWM_HINTS_FUNCTIONS;
4181 hints.functions = functions;
4183 gdk_window_set_mwm_hints (window, &hints);
4187 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4191 cairo_region_t *shape;
4199 /* Note that XShapeGetRectangles returns NULL in two situations:
4200 * - the server doesn't support the SHAPE extension
4201 * - the shape is empty
4203 * Since we can't discriminate these here, we always return
4204 * an empty shape. It is the callers responsibility to check
4205 * whether the server supports the SHAPE extensions beforehand.
4207 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4210 return cairo_region_create (); /* Empty */
4212 if (ord != YXBanded)
4214 /* This really shouldn't happen with any xserver, as they
4215 * generally convert regions to YXBanded internally
4217 g_warning ("non YXBanded shape masks not supported");
4222 rl = g_new (GdkRectangle, rn);
4223 for (i = 0; i < rn; i++)
4227 rl[i].width = xrl[i].width;
4228 rl[i].height = xrl[i].height;
4232 shape = cairo_region_create_rectangles (rl, rn);
4239 static cairo_region_t *
4240 gdk_x11_window_get_shape (GdkWindow *window)
4242 if (!GDK_WINDOW_DESTROYED (window) &&
4243 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4244 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4245 GDK_WINDOW_XID (window),
4251 static cairo_region_t *
4252 gdk_x11_window_get_input_shape (GdkWindow *window)
4254 #if defined(ShapeInput)
4255 if (!GDK_WINDOW_DESTROYED (window) &&
4256 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4257 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4258 GDK_WINDOW_XID (window),
4266 gdk_window_set_static_bit_gravity (GdkWindow *window,
4269 XSetWindowAttributes xattributes;
4270 guint xattributes_mask = 0;
4272 g_return_if_fail (GDK_IS_WINDOW (window));
4274 if (window->input_only)
4277 xattributes.bit_gravity = StaticGravity;
4278 xattributes_mask |= CWBitGravity;
4279 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4280 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4281 GDK_WINDOW_XID (window),
4282 CWBitGravity, &xattributes);
4286 gdk_window_set_static_win_gravity (GdkWindow *window,
4289 XSetWindowAttributes xattributes;
4291 g_return_if_fail (GDK_IS_WINDOW (window));
4293 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4295 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4296 GDK_WINDOW_XID (window),
4297 CWWinGravity, &xattributes);
4301 gdk_window_x11_set_static_gravities (GdkWindow *window,
4302 gboolean use_static)
4306 if (!use_static == !window->guffaw_gravity)
4309 window->guffaw_gravity = use_static;
4311 if (!GDK_WINDOW_DESTROYED (window))
4313 gdk_window_set_static_bit_gravity (window, use_static);
4315 tmp_list = window->children;
4318 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4320 tmp_list = tmp_list->next;
4327 /* From the WM spec */
4328 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4329 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4330 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4331 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4332 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4333 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4334 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4335 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4336 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4337 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4338 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4339 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4342 wmspec_send_message (GdkDisplay *display,
4349 XClientMessageEvent xclient;
4351 memset (&xclient, 0, sizeof (xclient));
4352 xclient.type = ClientMessage;
4353 xclient.window = GDK_WINDOW_XID (window);
4354 xclient.message_type =
4355 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4356 xclient.format = 32;
4357 xclient.data.l[0] = root_x;
4358 xclient.data.l[1] = root_y;
4359 xclient.data.l[2] = action;
4360 xclient.data.l[3] = button;
4361 xclient.data.l[4] = 1; /* source indication */
4363 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4364 SubstructureRedirectMask | SubstructureNotifyMask,
4365 (XEvent *)&xclient);
4369 handle_wmspec_button_release (GdkDisplay *display,
4372 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4375 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4376 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4377 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4379 if (xevent->xany.type == GenericEvent)
4380 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4383 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4385 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4387 if ((xevent->xany.type == ButtonRelease &&
4388 xevent->xbutton.button == display_x11->wm_moveresize_button)
4389 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4391 (xevent->xany.type == GenericEvent &&
4392 xiev->evtype == XI_ButtonRelease &&
4393 xidev->detail == display_x11->wm_moveresize_button)
4397 display_x11->wm_moveresize_button = 0;
4398 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4404 wmspec_moveresize (GdkWindow *window,
4412 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4414 /* Release passive grab */
4415 gdk_device_ungrab (device, timestamp);
4416 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4418 wmspec_send_message (display, window, root_x, root_y, direction, button);
4422 wmspec_resize_drag (GdkWindow *window,
4432 /* Let the compiler turn a switch into a table, instead
4433 * of doing the table manually, this way is easier to verify.
4437 case GDK_WINDOW_EDGE_NORTH_WEST:
4438 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4441 case GDK_WINDOW_EDGE_NORTH:
4442 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4445 case GDK_WINDOW_EDGE_NORTH_EAST:
4446 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4449 case GDK_WINDOW_EDGE_WEST:
4450 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4453 case GDK_WINDOW_EDGE_EAST:
4454 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4457 case GDK_WINDOW_EDGE_SOUTH_WEST:
4458 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4461 case GDK_WINDOW_EDGE_SOUTH:
4462 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4465 case GDK_WINDOW_EDGE_SOUTH_EAST:
4466 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4470 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4475 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4478 typedef struct _MoveResizeData MoveResizeData;
4480 struct _MoveResizeData
4482 GdkDisplay *display;
4484 GdkWindow *moveresize_window;
4485 GdkWindow *moveresize_emulation_window;
4487 GdkWindowEdge resize_edge;
4489 gint moveresize_button;
4492 gint moveresize_orig_x;
4493 gint moveresize_orig_y;
4494 gint moveresize_orig_width;
4495 gint moveresize_orig_height;
4496 GdkWindowHints moveresize_geom_mask;
4497 GdkGeometry moveresize_geometry;
4498 Time moveresize_process_time;
4499 XEvent *moveresize_pending_event;
4502 static MoveResizeData *
4503 get_move_resize_data (GdkDisplay *display,
4506 MoveResizeData *mv_resize;
4507 static GQuark move_resize_quark = 0;
4509 if (!move_resize_quark)
4510 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4512 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4514 if (!mv_resize && create)
4516 mv_resize = g_new0 (MoveResizeData, 1);
4517 mv_resize->display = display;
4519 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4526 update_pos (MoveResizeData *mv_resize,
4532 dx = new_root_x - mv_resize->moveresize_x;
4533 dy = new_root_y - mv_resize->moveresize_y;
4535 if (mv_resize->is_resize)
4539 x = mv_resize->moveresize_orig_x;
4540 y = mv_resize->moveresize_orig_y;
4542 w = mv_resize->moveresize_orig_width;
4543 h = mv_resize->moveresize_orig_height;
4545 switch (mv_resize->resize_edge)
4547 case GDK_WINDOW_EDGE_NORTH_WEST:
4553 case GDK_WINDOW_EDGE_NORTH:
4557 case GDK_WINDOW_EDGE_NORTH_EAST:
4562 case GDK_WINDOW_EDGE_SOUTH_WEST:
4567 case GDK_WINDOW_EDGE_SOUTH_EAST:
4571 case GDK_WINDOW_EDGE_SOUTH:
4574 case GDK_WINDOW_EDGE_EAST:
4577 case GDK_WINDOW_EDGE_WEST:
4588 if (mv_resize->moveresize_geom_mask)
4590 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4591 mv_resize->moveresize_geom_mask,
4595 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4601 x = mv_resize->moveresize_orig_x + dx;
4602 y = mv_resize->moveresize_orig_y + dy;
4604 gdk_window_move (mv_resize->moveresize_window, x, y);
4609 finish_drag (MoveResizeData *mv_resize)
4611 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4612 mv_resize->moveresize_emulation_window = NULL;
4613 g_object_unref (mv_resize->moveresize_window);
4614 mv_resize->moveresize_window = NULL;
4616 if (mv_resize->moveresize_pending_event)
4618 g_free (mv_resize->moveresize_pending_event);
4619 mv_resize->moveresize_pending_event = NULL;
4624 lookahead_motion_predicate (Display *xdisplay,
4628 gboolean *seen_release = (gboolean *)arg;
4629 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4630 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4635 switch (event->xany.type)
4638 *seen_release = TRUE;
4641 mv_resize->moveresize_process_time = event->xmotion.time;
4651 moveresize_lookahead (MoveResizeData *mv_resize,
4655 gboolean seen_release = FALSE;
4657 if (mv_resize->moveresize_process_time)
4659 if (event->xmotion.time == mv_resize->moveresize_process_time)
4661 mv_resize->moveresize_process_time = 0;
4668 XCheckIfEvent (event->xany.display, &tmp_event,
4669 lookahead_motion_predicate, (XPointer) & seen_release);
4671 return mv_resize->moveresize_process_time == 0;
4675 _gdk_x11_moveresize_handle_event (XEvent *event)
4677 guint button_mask = 0;
4678 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4679 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4681 if (!mv_resize || !mv_resize->moveresize_window)
4683 handle_wmspec_button_release (display, event);
4687 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4689 switch (event->xany.type)
4692 if (mv_resize->moveresize_window->resize_count > 0)
4694 if (mv_resize->moveresize_pending_event)
4695 *mv_resize->moveresize_pending_event = *event;
4697 mv_resize->moveresize_pending_event =
4698 g_memdup (event, sizeof (XEvent));
4702 if (!moveresize_lookahead (mv_resize, event))
4705 update_pos (mv_resize,
4706 event->xmotion.x_root,
4707 event->xmotion.y_root);
4709 /* This should never be triggered in normal cases, but in the
4710 * case where the drag started without an implicit grab being
4711 * in effect, we could miss the release if it occurs before
4712 * we grab the pointer; this ensures that we will never
4713 * get a permanently stuck grab.
4715 if ((event->xmotion.state & button_mask) == 0)
4716 finish_drag (mv_resize);
4720 update_pos (mv_resize,
4721 event->xbutton.x_root,
4722 event->xbutton.y_root);
4724 if (event->xbutton.button == mv_resize->moveresize_button)
4725 finish_drag (mv_resize);
4728 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4731 /* we just assume this is an XI2 event */
4732 XIEvent *ev = (XIEvent *) event->xcookie.data;
4733 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4738 update_pos (mv_resize, xev->root_x, xev->root_y);
4739 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4740 if ((state & button_mask) == 0)
4741 finish_drag (mv_resize);
4744 case XI_ButtonRelease:
4745 update_pos (mv_resize, xev->root_x, xev->root_y);
4746 if (xev->detail == mv_resize->moveresize_button)
4747 finish_drag (mv_resize);
4759 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4763 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4765 if (!mv_resize || window != mv_resize->moveresize_window)
4768 if (mv_resize->moveresize_pending_event)
4770 tmp_event = mv_resize->moveresize_pending_event;
4771 mv_resize->moveresize_pending_event = NULL;
4772 _gdk_x11_moveresize_handle_event (tmp_event);
4780 create_moveresize_window (MoveResizeData *mv_resize,
4783 GdkWindowAttr attributes;
4784 gint attributes_mask;
4785 GdkGrabStatus status;
4787 g_assert (mv_resize->moveresize_emulation_window == NULL);
4789 attributes.x = -100;
4790 attributes.y = -100;
4791 attributes.width = 10;
4792 attributes.height = 10;
4793 attributes.window_type = GDK_WINDOW_TEMP;
4794 attributes.wclass = GDK_INPUT_ONLY;
4795 attributes.override_redirect = TRUE;
4796 attributes.event_mask = 0;
4798 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4800 mv_resize->moveresize_emulation_window =
4801 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4805 gdk_window_show (mv_resize->moveresize_emulation_window);
4807 status = gdk_device_grab (mv_resize->device,
4808 mv_resize->moveresize_emulation_window,
4811 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4815 if (status != GDK_GRAB_SUCCESS)
4817 /* If this fails, some other client has grabbed the window
4820 finish_drag (mv_resize);
4823 mv_resize->moveresize_process_time = 0;
4827 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4828 so that calling XMoveWindow with these coordinates will not move the
4830 Note that this depends on the WM to implement ICCCM-compliant reference
4834 calculate_unmoving_origin (MoveResizeData *mv_resize)
4839 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4840 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4842 gdk_window_get_origin (mv_resize->moveresize_window,
4843 &mv_resize->moveresize_orig_x,
4844 &mv_resize->moveresize_orig_y);
4848 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4849 gdk_window_get_geometry (mv_resize->moveresize_window,
4850 NULL, NULL, &width, &height);
4852 switch (mv_resize->moveresize_geometry.win_gravity)
4854 case GDK_GRAVITY_NORTH_WEST:
4855 mv_resize->moveresize_orig_x = rect.x;
4856 mv_resize->moveresize_orig_y = rect.y;
4858 case GDK_GRAVITY_NORTH:
4859 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4860 mv_resize->moveresize_orig_y = rect.y;
4862 case GDK_GRAVITY_NORTH_EAST:
4863 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4864 mv_resize->moveresize_orig_y = rect.y;
4866 case GDK_GRAVITY_WEST:
4867 mv_resize->moveresize_orig_x = rect.x;
4868 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4870 case GDK_GRAVITY_CENTER:
4871 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4872 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4874 case GDK_GRAVITY_EAST:
4875 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4876 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4878 case GDK_GRAVITY_SOUTH_WEST:
4879 mv_resize->moveresize_orig_x = rect.x;
4880 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4882 case GDK_GRAVITY_SOUTH:
4883 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4884 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4886 case GDK_GRAVITY_SOUTH_EAST:
4887 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4888 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4891 mv_resize->moveresize_orig_x = rect.x;
4892 mv_resize->moveresize_orig_y = rect.y;
4899 emulate_resize_drag (GdkWindow *window,
4907 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4909 mv_resize->is_resize = TRUE;
4910 mv_resize->moveresize_button = button;
4911 mv_resize->resize_edge = edge;
4912 mv_resize->device = device;
4913 mv_resize->moveresize_x = root_x;
4914 mv_resize->moveresize_y = root_y;
4915 mv_resize->moveresize_window = g_object_ref (window);
4917 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
4918 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
4920 mv_resize->moveresize_geom_mask = 0;
4921 gdk_window_get_geometry_hints (window,
4922 &mv_resize->moveresize_geometry,
4923 &mv_resize->moveresize_geom_mask);
4925 calculate_unmoving_origin (mv_resize);
4927 create_moveresize_window (mv_resize, timestamp);
4931 emulate_move_drag (GdkWindow *window,
4938 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4940 mv_resize->is_resize = FALSE;
4941 mv_resize->device = device;
4942 mv_resize->moveresize_button = button;
4943 mv_resize->moveresize_x = root_x;
4944 mv_resize->moveresize_y = root_y;
4946 mv_resize->moveresize_window = g_object_ref (window);
4948 calculate_unmoving_origin (mv_resize);
4950 create_moveresize_window (mv_resize, timestamp);
4954 gdk_x11_window_begin_resize_drag (GdkWindow *window,
4962 if (GDK_WINDOW_DESTROYED (window) ||
4963 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4966 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4967 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4968 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4970 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4974 gdk_x11_window_begin_move_drag (GdkWindow *window,
4981 if (GDK_WINDOW_DESTROYED (window) ||
4982 !WINDOW_IS_TOPLEVEL (window))
4985 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4986 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4987 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
4988 device, button, root_x, root_y, timestamp);
4990 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
4994 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
4996 GdkWindowImplX11 *impl;
4998 if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
5001 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5003 if (!impl->use_synchronized_configure)
5005 /* This basically means you want to do fancy X specific stuff, so
5006 ensure we have a native window */
5007 gdk_window_ensure_native (window);
5009 impl->use_synchronized_configure = TRUE;
5010 ensure_sync_counter (window);
5015 gdk_x11_window_configure_finished (GdkWindow *window)
5017 GdkWindowImplX11 *impl;
5019 if (!WINDOW_IS_TOPLEVEL (window))
5022 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5023 if (!impl->use_synchronized_configure)
5027 if (!GDK_WINDOW_DESTROYED (window))
5029 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5030 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5032 if (toplevel && toplevel->update_counter != None &&
5033 GDK_X11_DISPLAY (display)->use_sync &&
5034 toplevel->configure_counter_value != 0)
5036 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5037 toplevel->update_counter,
5038 toplevel->configure_counter_value);
5040 toplevel->current_counter_value = toplevel->configure_counter_value;
5041 if ((toplevel->current_counter_value % 2) == 1)
5042 toplevel->current_counter_value += 1;
5044 toplevel->configure_counter_value = 0;
5046 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5047 toplevel->extended_update_counter,
5048 toplevel->current_counter_value);
5055 gdk_x11_window_beep (GdkWindow *window)
5057 GdkDisplay *display;
5059 display = GDK_WINDOW_DISPLAY (window);
5062 if (GDK_X11_DISPLAY (display)->use_xkb)
5064 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5065 GDK_WINDOW_XID (window),
5076 gdk_x11_window_set_opacity (GdkWindow *window,
5079 GdkDisplay *display;
5082 g_return_if_fail (GDK_IS_WINDOW (window));
5084 if (GDK_WINDOW_DESTROYED (window) ||
5085 !WINDOW_IS_TOPLEVEL (window))
5088 display = gdk_window_get_display (window);
5092 else if (opacity > 1)
5095 cardinal = opacity * 0xffffffff;
5097 if (cardinal == 0xffffffff)
5098 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5099 GDK_WINDOW_XID (window),
5100 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5102 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5103 GDK_WINDOW_XID (window),
5104 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5107 (guchar *) &cardinal, 1);
5111 gdk_x11_window_set_composited (GdkWindow *window,
5112 gboolean composited)
5114 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5115 GdkWindowImplX11 *impl;
5116 GdkDisplay *display;
5120 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5122 display = gdk_window_get_display (window);
5123 dpy = GDK_DISPLAY_XDISPLAY (display);
5124 xid = GDK_WINDOW_XID (window);
5128 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5129 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5133 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5134 XDamageDestroy (dpy, impl->damage);
5135 impl->damage = None;
5141 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5142 cairo_region_t *region)
5144 _gdk_window_process_updates_recurse (window, region);
5148 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5153 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5155 /* Sync after all drawing, otherwise the client can get "ahead" of
5156 the server rendering during animations, such that we fill up
5157 the Xserver pipes with sync rendering ops not letting other
5158 clients (including the VM) do anything. */
5159 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5163 timestamp_predicate (Display *display,
5167 Window xwindow = GPOINTER_TO_UINT (arg);
5168 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5170 if (xevent->type == PropertyNotify &&
5171 xevent->xproperty.window == xwindow &&
5172 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5173 "GDK_TIMESTAMP_PROP"))
5180 * gdk_x11_get_server_time:
5181 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5182 * with the server. The window must have
5183 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5186 * Routine to get the current X server time stamp.
5188 * Return value: the time stamp.
5191 gdk_x11_get_server_time (GdkWindow *window)
5197 Atom timestamp_prop_atom;
5199 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5200 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5202 xdisplay = GDK_WINDOW_XDISPLAY (window);
5203 xwindow = GDK_WINDOW_XID (window);
5204 timestamp_prop_atom =
5205 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5206 "GDK_TIMESTAMP_PROP");
5208 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5209 timestamp_prop_atom,
5210 8, PropModeReplace, &c, 1);
5212 XIfEvent (xdisplay, &xevent,
5213 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5215 return xevent.xproperty.time;
5219 * gdk_x11_window_get_xid:
5220 * @window: (type GdkX11Window): a native #GdkWindow.
5222 * Returns the X resource (window) belonging to a #GdkWindow.
5224 * Return value: the ID of @drawable's X resource.
5227 gdk_x11_window_get_xid (GdkWindow *window)
5229 /* Try to ensure the window has a native window */
5230 if (!_gdk_window_has_impl (window))
5232 gdk_window_ensure_native (window);
5234 /* We sync here to ensure the window is created in the Xserver when
5235 * this function returns. This is required because the returned XID
5236 * for this window must be valid immediately, even with another
5237 * connection to the Xserver */
5238 gdk_display_sync (gdk_window_get_display (window));
5241 if (!GDK_WINDOW_IS_X11 (window))
5243 g_warning (G_STRLOC " drawable is not a native X11 window");
5247 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5251 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5253 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5254 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5256 object_class->finalize = gdk_window_impl_x11_finalize;
5258 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5259 impl_class->show = gdk_window_x11_show;
5260 impl_class->hide = gdk_window_x11_hide;
5261 impl_class->withdraw = gdk_window_x11_withdraw;
5262 impl_class->set_events = gdk_window_x11_set_events;
5263 impl_class->get_events = gdk_window_x11_get_events;
5264 impl_class->raise = gdk_window_x11_raise;
5265 impl_class->lower = gdk_window_x11_lower;
5266 impl_class->restack_under = gdk_window_x11_restack_under;
5267 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5268 impl_class->move_resize = gdk_window_x11_move_resize;
5269 impl_class->set_background = gdk_window_x11_set_background;
5270 impl_class->reparent = gdk_window_x11_reparent;
5271 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5272 impl_class->get_geometry = gdk_window_x11_get_geometry;
5273 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5274 impl_class->get_device_state = gdk_window_x11_get_device_state;
5275 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5276 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5277 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5278 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5279 impl_class->translate = _gdk_x11_window_translate;
5280 impl_class->destroy = gdk_x11_window_destroy;
5281 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5282 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5283 impl_class->get_shape = gdk_x11_window_get_shape;
5284 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5285 impl_class->beep = gdk_x11_window_beep;
5287 impl_class->focus = gdk_x11_window_focus;
5288 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5289 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5290 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5291 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5292 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5293 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5294 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5295 impl_class->set_title = gdk_x11_window_set_title;
5296 impl_class->set_role = gdk_x11_window_set_role;
5297 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5298 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5299 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5300 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5301 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5302 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5303 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5304 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5305 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5306 impl_class->iconify = gdk_x11_window_iconify;
5307 impl_class->deiconify = gdk_x11_window_deiconify;
5308 impl_class->stick = gdk_x11_window_stick;
5309 impl_class->unstick = gdk_x11_window_unstick;
5310 impl_class->maximize = gdk_x11_window_maximize;
5311 impl_class->unmaximize = gdk_x11_window_unmaximize;
5312 impl_class->fullscreen = gdk_x11_window_fullscreen;
5313 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5314 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5315 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5316 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5317 impl_class->get_group = gdk_x11_window_get_group;
5318 impl_class->set_group = gdk_x11_window_set_group;
5319 impl_class->set_decorations = gdk_x11_window_set_decorations;
5320 impl_class->get_decorations = gdk_x11_window_get_decorations;
5321 impl_class->set_functions = gdk_x11_window_set_functions;
5322 impl_class->set_functions = gdk_x11_window_set_functions;
5323 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5324 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5325 impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
5326 impl_class->configure_finished = gdk_x11_window_configure_finished;
5327 impl_class->set_opacity = gdk_x11_window_set_opacity;
5328 impl_class->set_composited = gdk_x11_window_set_composited;
5329 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5330 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5331 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5332 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5333 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5334 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5335 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5336 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5337 impl_class->get_property = _gdk_x11_window_get_property;
5338 impl_class->change_property = _gdk_x11_window_change_property;
5339 impl_class->delete_property = _gdk_x11_window_delete_property;