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_predict_presentation_time (GdkWindow *window)
283 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
284 GdkFrameClock *clock;
285 GdkFrameTimings *timings;
287 gint64 presentation_time;
288 gint64 refresh_interval;
289 gboolean slept_before;
291 if (!WINDOW_IS_TOPLEVEL (window))
294 clock = gdk_window_get_frame_clock (window);
296 timings = gdk_frame_clock_get_current_frame_timings (clock);
297 frame_time = gdk_frame_timings_get_frame_time (timings);
298 slept_before = gdk_frame_timings_get_slept_before (timings);
300 gdk_frame_clock_get_refresh_info (clock,
302 &refresh_interval, &presentation_time);
304 if (presentation_time != 0)
308 presentation_time += refresh_interval;
312 if (presentation_time < frame_time + refresh_interval / 2)
313 presentation_time += refresh_interval;
319 presentation_time = frame_time + refresh_interval + refresh_interval / 2;
321 presentation_time = frame_time + refresh_interval;
324 if (presentation_time < impl->toplevel->throttled_presentation_time)
325 presentation_time = impl->toplevel->throttled_presentation_time;
327 gdk_frame_timings_set_predicted_presentation_time (timings,
333 gdk_x11_window_begin_frame (GdkWindow *window)
335 GdkWindowImplX11 *impl;
337 g_return_if_fail (GDK_IS_WINDOW (window));
339 impl = GDK_WINDOW_IMPL_X11 (window->impl);
341 if (!WINDOW_IS_TOPLEVEL (window) ||
342 impl->toplevel->extended_update_counter == None)
345 impl->toplevel->in_frame = TRUE;
347 hook_surface_changed (window);
351 gdk_x11_window_end_frame (GdkWindow *window)
353 GdkFrameClock *clock;
354 GdkFrameTimings *timings;
355 GdkWindowImplX11 *impl;
357 g_return_if_fail (GDK_IS_WINDOW (window));
359 impl = GDK_WINDOW_IMPL_X11 (window->impl);
361 if (!WINDOW_IS_TOPLEVEL (window) ||
362 impl->toplevel->extended_update_counter == None ||
363 !impl->toplevel->in_frame)
366 clock = gdk_window_get_frame_clock (window);
367 timings = gdk_frame_clock_get_current_frame_timings (clock);
369 impl->toplevel->in_frame = FALSE;
371 if (impl->toplevel->current_counter_value % 2 == 1)
373 #ifdef G_ENABLE_DEBUG
374 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
376 XImage *image = XGetImage (GDK_WINDOW_XDISPLAY (window),
377 GDK_WINDOW_XID (window),
381 XDestroyImage (image);
383 #endif /* G_ENABLE_DEBUG */
385 /* An increment of 3 means that the frame was not drawn as fast as possible,
386 * but rather at a particular time. This can trigger different handling from
389 if (gdk_frame_timings_get_slept_before (timings))
390 impl->toplevel->current_counter_value += 3;
392 impl->toplevel->current_counter_value += 1;
394 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
395 impl->toplevel->extended_update_counter,
396 impl->toplevel->current_counter_value);
398 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
399 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
401 impl->toplevel->frame_pending = TRUE;
402 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
403 gdk_frame_timings_set_cookie (timings,
404 impl->toplevel->current_counter_value);
408 unhook_surface_changed (window);
410 if (!impl->toplevel->frame_pending)
411 gdk_frame_timings_set_complete (timings, TRUE);
414 /*****************************************************
415 * X11 specific implementations of generic functions *
416 *****************************************************/
419 gdk_x11_cairo_surface_destroy (void *data)
421 GdkWindowImplX11 *impl = data;
423 impl->cairo_surface = NULL;
426 static cairo_surface_t *
427 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
433 visual = gdk_window_get_visual (impl->wrapper);
434 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
435 GDK_WINDOW_IMPL_X11 (impl)->xid,
436 GDK_VISUAL_XVISUAL (visual),
440 static cairo_surface_t *
441 gdk_x11_ref_cairo_surface (GdkWindow *window)
443 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
445 if (GDK_WINDOW_DESTROYED (window))
448 if (!impl->cairo_surface)
450 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
451 gdk_window_get_width (window),
452 gdk_window_get_height (window));
454 if (impl->cairo_surface)
455 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
456 impl, gdk_x11_cairo_surface_destroy);
458 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
459 hook_surface_changed (window);
462 cairo_surface_reference (impl->cairo_surface);
464 return impl->cairo_surface;
468 gdk_window_impl_x11_finalize (GObject *object)
471 GdkWindowImplX11 *impl;
473 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
475 impl = GDK_WINDOW_IMPL_X11 (object);
477 wrapper = impl->wrapper;
479 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
480 unhook_surface_changed (wrapper);
482 _gdk_x11_window_grab_check_destroy (wrapper);
484 if (!GDK_WINDOW_DESTROYED (wrapper))
486 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
488 _gdk_x11_display_remove_window (display, impl->xid);
489 if (impl->toplevel && impl->toplevel->focus_window)
490 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
493 g_free (impl->toplevel);
496 g_object_unref (impl->cursor);
498 g_hash_table_destroy (impl->device_cursor);
500 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
509 free_pixmap (gpointer datap)
511 FreePixmapData *data = datap;
513 if (!gdk_display_is_closed (data->display))
515 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
519 g_object_unref (data->display);
520 g_slice_free (FreePixmapData, data);
524 attach_free_pixmap_handler (cairo_surface_t *surface,
528 static const cairo_user_data_key_t key;
529 FreePixmapData *data;
531 data = g_slice_new (FreePixmapData);
532 data->display = g_object_ref (display);
533 data->pixmap = pixmap;
535 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
538 /* Cairo does not guarantee we get an xlib surface if we call
539 * cairo_surface_create_similar(). In some cases however, we must use a
540 * pixmap or bitmap in the X11 API.
541 * These functions ensure an Xlib surface.
544 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
548 cairo_surface_t *surface;
551 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
552 GDK_WINDOW_XID (window),
554 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
556 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
558 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
563 /* Create a surface backed with a pixmap without alpha on the same screen as window */
564 static cairo_surface_t *
565 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
569 GdkScreen *screen = gdk_window_get_screen (window);
570 GdkVisual *visual = gdk_screen_get_system_visual (screen);
571 cairo_surface_t *surface;
574 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
575 GDK_WINDOW_XID (window),
577 gdk_visual_get_depth (visual));
578 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
580 GDK_VISUAL_XVISUAL (visual),
582 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
588 tmp_unset_bg (GdkWindow *window)
590 GdkWindowImplX11 *impl;
592 impl = GDK_WINDOW_IMPL_X11 (window->impl);
596 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
597 GDK_WINDOW_XID (window), None);
601 tmp_reset_bg (GdkWindow *window)
603 GdkWindowImplX11 *impl;
605 impl = GDK_WINDOW_IMPL_X11 (window->impl);
609 gdk_window_x11_set_background (window, window->background);
612 /* Unsetting and resetting window backgrounds.
614 * In many cases it is possible to avoid flicker by unsetting the
615 * background of windows. For example if the background of the
616 * parent window is unset when a window is unmapped, a brief flicker
617 * of background painting is avoided.
620 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
623 g_return_if_fail (GDK_IS_WINDOW (window));
625 if (window->input_only || window->destroyed ||
626 (window->window_type != GDK_WINDOW_ROOT &&
627 !GDK_WINDOW_IS_MAPPED (window)))
630 if (_gdk_window_has_impl (window) &&
631 GDK_WINDOW_IS_X11 (window) &&
632 window->window_type != GDK_WINDOW_ROOT &&
633 window->window_type != GDK_WINDOW_FOREIGN)
634 tmp_unset_bg (window);
640 for (l = window->children; l != NULL; l = l->next)
641 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
646 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
648 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
651 window = _gdk_window_get_impl_window (window->parent);
652 _gdk_x11_window_tmp_unset_bg (window, FALSE);
656 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
659 g_return_if_fail (GDK_IS_WINDOW (window));
661 if (window->input_only || window->destroyed ||
662 (window->window_type != GDK_WINDOW_ROOT &&
663 !GDK_WINDOW_IS_MAPPED (window)))
667 if (_gdk_window_has_impl (window) &&
668 GDK_WINDOW_IS_X11 (window) &&
669 window->window_type != GDK_WINDOW_ROOT &&
670 window->window_type != GDK_WINDOW_FOREIGN)
671 tmp_reset_bg (window);
677 for (l = window->children; l != NULL; l = l->next)
678 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
683 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
685 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
688 window = _gdk_window_get_impl_window (window->parent);
690 _gdk_x11_window_tmp_reset_bg (window, FALSE);
694 _gdk_x11_screen_init_root_window (GdkScreen *screen)
697 GdkWindowImplX11 *impl;
698 GdkX11Screen *x11_screen;
700 x11_screen = GDK_X11_SCREEN (screen);
702 g_assert (x11_screen->root_window == NULL);
704 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
706 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
707 window->impl_window = window;
708 window->visual = gdk_screen_get_system_visual (screen);
710 impl = GDK_WINDOW_IMPL_X11 (window->impl);
712 impl->xid = x11_screen->xroot_window;
713 impl->wrapper = window;
715 window->window_type = GDK_WINDOW_ROOT;
716 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
722 window->width = WidthOfScreen (x11_screen->xscreen);
723 window->height = HeightOfScreen (x11_screen->xscreen);
724 window->viewable = TRUE;
726 /* see init_randr_support() in gdkscreen-x11.c */
727 window->event_mask = GDK_STRUCTURE_MASK;
729 _gdk_window_update_size (x11_screen->root_window);
731 _gdk_x11_display_add_window (x11_screen->display,
732 &x11_screen->xroot_window,
733 x11_screen->root_window);
737 set_wm_protocols (GdkWindow *window)
739 GdkDisplay *display = gdk_window_get_display (window);
743 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
744 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
745 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
748 if (GDK_X11_DISPLAY (display)->use_sync)
749 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
752 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
756 get_default_title (void)
760 title = g_get_application_name ();
762 title = g_get_prgname ();
770 check_leader_window_title (GdkDisplay *display)
772 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
774 if (display_x11->leader_window && !display_x11->leader_window_title_set)
776 set_wm_name (display,
777 display_x11->leader_window,
778 get_default_title ());
780 display_x11->leader_window_title_set = TRUE;
785 create_focus_window (GdkDisplay *display,
788 GdkX11Display *display_x11;
789 GdkEventMask event_mask;
793 xdisplay = GDK_DISPLAY_XDISPLAY (display);
794 display_x11 = GDK_X11_DISPLAY (display);
796 focus_window = XCreateSimpleWindow (xdisplay, parent,
800 /* FIXME: probably better to actually track the requested event mask for the toplevel
802 event_mask = (GDK_KEY_PRESS_MASK |
803 GDK_KEY_RELEASE_MASK |
804 GDK_FOCUS_CHANGE_MASK);
806 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
810 XMapWindow (xdisplay, focus_window);
816 ensure_sync_counter (GdkWindow *window)
819 if (!GDK_WINDOW_DESTROYED (window))
821 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
822 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
825 toplevel->update_counter == None &&
826 GDK_X11_DISPLAY (display)->use_sync)
828 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
833 XSyncIntToValue (&value, 0);
835 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
836 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
838 atom = gdk_x11_get_xatom_by_name_for_display (display,
839 "_NET_WM_SYNC_REQUEST_COUNTER");
841 counters[0] = toplevel->update_counter;
842 counters[1] = toplevel->extended_update_counter;
843 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
846 (guchar *)counters, 2);
848 toplevel->current_counter_value = 0;
855 setup_toplevel_window (GdkWindow *window,
858 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
859 GdkDisplay *display = gdk_window_get_display (window);
860 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
861 XID xid = GDK_WINDOW_XID (window);
862 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
863 XSizeHints size_hints;
865 Window leader_window;
867 set_wm_protocols (window);
869 if (!window->input_only)
871 /* The focus window is off the visible area, and serves to receive key
872 * press events so they don't get sent to child windows.
874 toplevel->focus_window = create_focus_window (display, xid);
875 _gdk_x11_display_add_window (x11_screen->display,
876 &toplevel->focus_window,
880 check_leader_window_title (x11_screen->display);
882 /* FIXME: Is there any point in doing this? Do any WM's pay
883 * attention to PSize, and even if they do, is this the
886 size_hints.flags = PSize;
887 size_hints.width = window->width;
888 size_hints.height = window->height;
890 XSetWMNormalHints (xdisplay, xid, &size_hints);
892 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
893 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
896 XChangeProperty (xdisplay, xid,
897 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
902 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
905 XChangeProperty (xdisplay, xid,
906 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
907 XA_WINDOW, 32, PropModeReplace,
908 (guchar *) &leader_window, 1);
910 if (toplevel->focus_window != None)
911 XChangeProperty (xdisplay, xid,
912 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
913 XA_WINDOW, 32, PropModeReplace,
914 (guchar *) &toplevel->focus_window, 1);
916 if (!window->focus_on_map)
917 gdk_x11_window_set_user_time (window, 0);
918 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
919 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
921 ensure_sync_counter (window);
923 /* Start off in a frozen state - we'll finish this when we first paint */
924 gdk_x11_window_begin_frame (window);
928 on_frame_clock_before_paint (GdkFrameClock *clock,
931 gdk_x11_window_predict_presentation_time (window);
932 gdk_x11_window_begin_frame (window);
936 on_frame_clock_after_paint (GdkFrameClock *clock,
939 gdk_x11_window_end_frame (window);
944 _gdk_x11_display_create_window_impl (GdkDisplay *display,
946 GdkWindow *real_parent,
948 GdkEventMask event_mask,
949 GdkWindowAttr *attributes,
950 gint attributes_mask)
952 GdkWindowImplX11 *impl;
953 GdkX11Screen *x11_screen;
954 GdkX11Display *display_x11;
955 GdkFrameClock *clock;
961 XSetWindowAttributes xattributes;
962 long xattributes_mask;
963 XClassHint *class_hint;
968 display_x11 = GDK_X11_DISPLAY (display);
969 xparent = GDK_WINDOW_XID (real_parent);
970 x11_screen = GDK_X11_SCREEN (screen);
972 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
973 window->impl = GDK_WINDOW_IMPL (impl);
974 impl->wrapper = GDK_WINDOW (window);
976 xdisplay = x11_screen->xdisplay;
978 xattributes_mask = 0;
980 xvisual = gdk_x11_visual_get_xvisual (window->visual);
982 if (attributes_mask & GDK_WA_NOREDIR)
984 xattributes.override_redirect =
985 (attributes->override_redirect == FALSE)?False:True;
986 xattributes_mask |= CWOverrideRedirect;
989 xattributes.override_redirect = False;
991 impl->override_redirect = xattributes.override_redirect;
993 if (window->parent && window->parent->guffaw_gravity)
995 xattributes.win_gravity = StaticGravity;
996 xattributes_mask |= CWWinGravity;
1000 switch (window->window_type)
1002 case GDK_WINDOW_TOPLEVEL:
1003 case GDK_WINDOW_TEMP:
1004 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
1006 /* The common code warns for this case */
1007 xparent = GDK_SCREEN_XROOTWIN (screen);
1011 if (!window->input_only)
1013 class = InputOutput;
1015 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1017 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1018 xattributes_mask |= CWBorderPixel | CWBackPixel;
1020 if (window->guffaw_gravity)
1021 xattributes.bit_gravity = StaticGravity;
1023 xattributes.bit_gravity = NorthWestGravity;
1025 xattributes_mask |= CWBitGravity;
1027 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
1028 xattributes_mask |= CWColormap;
1030 if (window->window_type == GDK_WINDOW_TEMP)
1032 xattributes.save_under = True;
1033 xattributes.override_redirect = True;
1034 xattributes.cursor = None;
1035 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
1037 impl->override_redirect = TRUE;
1045 if (window->width > 65535 ||
1046 window->height > 65535)
1048 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
1050 if (window->width > 65535)
1051 window->width = 65535;
1052 if (window->height > 65535)
1053 window->height = 65535;
1056 impl->xid = XCreateWindow (xdisplay, xparent,
1057 window->x + window->parent->abs_x,
1058 window->y + window->parent->abs_y,
1059 window->width, window->height,
1060 0, window->depth, class, xvisual,
1061 xattributes_mask, &xattributes);
1063 g_object_ref (window);
1064 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1066 switch (GDK_WINDOW_TYPE (window))
1068 case GDK_WINDOW_TOPLEVEL:
1069 case GDK_WINDOW_TEMP:
1070 if (attributes_mask & GDK_WA_TITLE)
1071 title = attributes->title;
1073 title = get_default_title ();
1075 gdk_window_set_title (window, title);
1077 if (attributes_mask & GDK_WA_WMCLASS)
1079 class_hint = XAllocClassHint ();
1080 class_hint->res_name = attributes->wmclass_name;
1081 class_hint->res_class = attributes->wmclass_class;
1082 XSetClassHint (xdisplay, impl->xid, class_hint);
1086 setup_toplevel_window (window, window->parent);
1089 case GDK_WINDOW_CHILD:
1094 if (attributes_mask & GDK_WA_TYPE_HINT)
1095 gdk_window_set_type_hint (window, attributes->type_hint);
1097 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1098 GDK_WINDOW_XID (window), event_mask,
1099 StructureNotifyMask | PropertyChangeMask);
1101 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1102 gdk_window_set_frame_clock (window, clock);
1103 g_signal_connect (clock, "before-paint",
1104 G_CALLBACK (on_frame_clock_before_paint), window);
1105 g_signal_connect (clock, "after-paint",
1106 G_CALLBACK (on_frame_clock_after_paint), window);
1108 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1109 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1113 x_event_mask_to_gdk_event_mask (long mask)
1115 GdkEventMask event_mask = 0;
1118 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1120 if (mask & _gdk_x11_event_mask_table[i])
1121 event_mask |= 1 << (i + 1);
1128 * gdk_x11_window_foreign_new_for_display:
1129 * @display: the #GdkDisplay where the window handle comes from.
1130 * @window: an XLib <type>Window</type>
1132 * Wraps a native window in a #GdkWindow. The function will try to
1133 * look up the window using gdk_x11_window_lookup_for_display() first.
1134 * If it does not find it there, it will create a new window.
1136 * This may fail if the window has been destroyed. If the window
1137 * was already known to GDK, a new reference to the existing
1138 * #GdkWindow is returned.
1140 * Return value: (transfer full): a #GdkWindow wrapper for the native
1141 * window, or %NULL if the window has been destroyed. The wrapper
1142 * will be newly created, if one doesn't exist already.
1147 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1152 GdkWindowImplX11 *impl;
1153 GdkX11Display *display_x11;
1154 XWindowAttributes attrs;
1155 Window root, parent;
1156 Window *children = NULL;
1160 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1162 display_x11 = GDK_X11_DISPLAY (display);
1164 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1165 return g_object_ref (win);
1167 gdk_x11_display_error_trap_push (display);
1168 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1169 if (gdk_x11_display_error_trap_pop (display) || !result)
1172 /* FIXME: This is pretty expensive.
1173 * Maybe the caller should supply the parent
1175 gdk_x11_display_error_trap_push (display);
1176 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1177 if (gdk_x11_display_error_trap_pop (display) || !result)
1183 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1185 win = _gdk_display_create_window (display);
1186 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1187 win->impl_window = win;
1188 win->visual = gdk_x11_screen_lookup_visual (screen,
1189 XVisualIDFromVisual (attrs.visual));
1191 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1192 impl->wrapper = win;
1194 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1196 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1197 win->parent = gdk_screen_get_root_window (screen);
1199 win->parent->children = g_list_prepend (win->parent->children, win);
1205 win->width = attrs.width;
1206 win->height = attrs.height;
1207 win->window_type = GDK_WINDOW_FOREIGN;
1208 win->destroyed = FALSE;
1210 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1212 if (attrs.map_state == IsUnmapped)
1213 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1216 win->viewable = TRUE;
1218 win->depth = attrs.depth;
1221 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1223 /* Update the clip region, etc */
1224 _gdk_window_update_size (win);
1230 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1231 GdkToplevelX11 *toplevel)
1233 if (toplevel->icon_pixmap)
1235 cairo_surface_destroy (toplevel->icon_pixmap);
1236 toplevel->icon_pixmap = NULL;
1238 if (toplevel->icon_mask)
1240 cairo_surface_destroy (toplevel->icon_mask);
1241 toplevel->icon_mask = NULL;
1243 if (toplevel->group_leader)
1245 g_object_unref (toplevel->group_leader);
1246 toplevel->group_leader = NULL;
1249 if (toplevel->update_counter != None)
1251 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1252 toplevel->update_counter);
1253 toplevel->update_counter = None;
1255 toplevel->current_counter_value = 0;
1261 gdk_x11_window_destroy (GdkWindow *window,
1263 gboolean foreign_destroy)
1265 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1266 GdkToplevelX11 *toplevel;
1268 g_return_if_fail (GDK_IS_WINDOW (window));
1270 _gdk_x11_selection_window_destroyed (window);
1272 toplevel = _gdk_x11_window_get_toplevel (window);
1274 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1276 if (impl->cairo_surface)
1278 cairo_surface_finish (impl->cairo_surface);
1279 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1283 if (!recursing && !foreign_destroy)
1284 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1287 static cairo_surface_t *
1288 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1289 cairo_surface_t *surface,
1293 cairo_xlib_surface_set_size (surface, width, height);
1299 gdk_x11_window_destroy_foreign (GdkWindow *window)
1301 /* It's somebody else's window, but in our hierarchy,
1302 * so reparent it to the root window, and then send
1303 * it a delete event, as if we were a WM
1305 XClientMessageEvent xclient;
1306 GdkDisplay *display;
1308 display = GDK_WINDOW_DISPLAY (window);
1309 gdk_x11_display_error_trap_push (display);
1310 gdk_window_hide (window);
1311 gdk_window_reparent (window, NULL, 0, 0);
1313 memset (&xclient, 0, sizeof (xclient));
1314 xclient.type = ClientMessage;
1315 xclient.window = GDK_WINDOW_XID (window);
1316 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1317 xclient.format = 32;
1318 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1319 xclient.data.l[1] = CurrentTime;
1320 xclient.data.l[2] = 0;
1321 xclient.data.l[3] = 0;
1322 xclient.data.l[4] = 0;
1324 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1325 GDK_WINDOW_XID (window),
1326 False, 0, (XEvent *)&xclient);
1327 gdk_x11_display_error_trap_pop_ignored (display);
1331 get_root (GdkWindow *window)
1333 GdkScreen *screen = gdk_window_get_screen (window);
1335 return gdk_screen_get_root_window (screen);
1338 /* This function is called when the XWindow is really gone.
1341 gdk_x11_window_destroy_notify (GdkWindow *window)
1343 GdkWindowImplX11 *window_impl;
1345 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1347 if (!GDK_WINDOW_DESTROYED (window))
1349 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1350 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1352 _gdk_window_destroy (window, TRUE);
1355 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1356 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1357 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1359 _gdk_x11_window_grab_check_destroy (window);
1361 g_object_unref (window);
1364 static GdkDragProtocol
1365 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1368 GdkDragProtocol protocol;
1369 GdkDisplay *display;
1373 display = gdk_window_get_display (window);
1374 xid = _gdk_x11_display_get_drag_protocol (display,
1375 GDK_WINDOW_XID (window->impl_window),
1382 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1391 update_wm_hints (GdkWindow *window,
1394 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1395 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1399 !toplevel->is_leader &&
1400 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1403 wm_hints.flags = StateHint | InputHint;
1404 wm_hints.input = window->accept_focus ? True : False;
1405 wm_hints.initial_state = NormalState;
1407 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1409 wm_hints.flags |= StateHint;
1410 wm_hints.initial_state = IconicState;
1413 if (toplevel->icon_pixmap)
1415 wm_hints.flags |= IconPixmapHint;
1416 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1419 if (toplevel->icon_mask)
1421 wm_hints.flags |= IconMaskHint;
1422 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1425 wm_hints.flags |= WindowGroupHint;
1426 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1428 wm_hints.flags |= WindowGroupHint;
1429 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1432 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1434 if (toplevel->urgency_hint)
1435 wm_hints.flags |= XUrgencyHint;
1437 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1438 GDK_WINDOW_XID (window),
1443 set_initial_hints (GdkWindow *window)
1445 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1446 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1447 Window xwindow = GDK_WINDOW_XID (window);
1448 GdkToplevelX11 *toplevel;
1452 toplevel = _gdk_x11_window_get_toplevel (window);
1457 update_wm_hints (window, TRUE);
1459 /* We set the spec hints regardless of whether the spec is supported,
1460 * since it can't hurt and it's kind of expensive to check whether
1466 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1468 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1469 "_NET_WM_STATE_MAXIMIZED_VERT");
1471 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1472 "_NET_WM_STATE_MAXIMIZED_HORZ");
1474 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1477 if (window->state & GDK_WINDOW_STATE_ABOVE)
1479 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1480 "_NET_WM_STATE_ABOVE");
1484 if (window->state & GDK_WINDOW_STATE_BELOW)
1486 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1487 "_NET_WM_STATE_BELOW");
1491 if (window->state & GDK_WINDOW_STATE_STICKY)
1493 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1494 "_NET_WM_STATE_STICKY");
1496 toplevel->have_sticky = TRUE;
1499 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1501 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1502 "_NET_WM_STATE_FULLSCREEN");
1504 toplevel->have_fullscreen = TRUE;
1507 if (window->modal_hint)
1509 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1510 "_NET_WM_STATE_MODAL");
1514 if (toplevel->skip_taskbar_hint)
1516 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1517 "_NET_WM_STATE_SKIP_TASKBAR");
1521 if (toplevel->skip_pager_hint)
1523 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1524 "_NET_WM_STATE_SKIP_PAGER");
1528 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1530 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1531 "_NET_WM_STATE_HIDDEN");
1533 toplevel->have_hidden = TRUE;
1538 XChangeProperty (xdisplay,
1540 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1541 XA_ATOM, 32, PropModeReplace,
1542 (guchar*) atoms, i);
1546 XDeleteProperty (xdisplay,
1548 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1551 if (window->state & GDK_WINDOW_STATE_STICKY)
1553 atoms[0] = 0xFFFFFFFF;
1554 XChangeProperty (xdisplay,
1556 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1557 XA_CARDINAL, 32, PropModeReplace,
1558 (guchar*) atoms, 1);
1559 toplevel->on_all_desktops = TRUE;
1563 XDeleteProperty (xdisplay,
1565 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1568 toplevel->map_serial = NextRequest (xdisplay);
1572 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1574 GdkDisplay *display;
1575 GdkX11Display *display_x11;
1576 GdkToplevelX11 *toplevel;
1577 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1578 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1579 Window xwindow = GDK_WINDOW_XID (window);
1582 if (!already_mapped)
1583 set_initial_hints (window);
1585 if (WINDOW_IS_TOPLEVEL (window))
1587 display = gdk_window_get_display (window);
1588 display_x11 = GDK_X11_DISPLAY (display);
1589 toplevel = _gdk_x11_window_get_toplevel (window);
1591 if (toplevel->user_time != 0 &&
1592 display_x11->user_time != 0 &&
1593 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1594 gdk_x11_window_set_user_time (window, display_x11->user_time);
1597 unset_bg = !window->input_only &&
1598 (window->window_type == GDK_WINDOW_CHILD ||
1599 impl->override_redirect) &&
1600 gdk_window_is_viewable (window);
1603 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1605 XMapWindow (xdisplay, xwindow);
1608 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1610 /* Fullscreen on current monitor is the default, no need to apply this mode
1611 * when mapping a window. This also ensures that the default behavior remains
1612 * consistent with pre-fullscreen mode implementation.
1614 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1615 gdk_x11_window_apply_fullscreen_mode (window);
1619 pre_unmap (GdkWindow *window)
1621 GdkWindow *start_window = NULL;
1623 if (window->input_only)
1626 if (window->window_type == GDK_WINDOW_CHILD)
1627 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1628 else if (window->window_type == GDK_WINDOW_TEMP)
1629 start_window = get_root (window);
1632 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1636 post_unmap (GdkWindow *window)
1638 GdkWindow *start_window = NULL;
1640 if (window->input_only)
1643 if (window->window_type == GDK_WINDOW_CHILD)
1644 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1645 else if (window->window_type == GDK_WINDOW_TEMP)
1646 start_window = get_root (window);
1650 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1652 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1654 GdkRectangle invalid_rect;
1656 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1657 invalid_rect.width = gdk_window_get_width (window);
1658 invalid_rect.height = gdk_window_get_height (window);
1659 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1660 &invalid_rect, TRUE);
1666 gdk_window_x11_hide (GdkWindow *window)
1668 /* We'll get the unmap notify eventually, and handle it then,
1669 * but checking here makes things more consistent if we are
1670 * just doing stuff ourself.
1672 _gdk_x11_window_grab_check_unmap (window,
1673 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1675 /* You can't simply unmap toplevel windows. */
1676 switch (window->window_type)
1678 case GDK_WINDOW_TOPLEVEL:
1679 case GDK_WINDOW_TEMP: /* ? */
1680 gdk_window_withdraw (window);
1683 case GDK_WINDOW_FOREIGN:
1684 case GDK_WINDOW_ROOT:
1685 case GDK_WINDOW_CHILD:
1689 _gdk_window_clear_update_area (window);
1692 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1693 GDK_WINDOW_XID (window));
1694 post_unmap (window);
1698 gdk_window_x11_withdraw (GdkWindow *window)
1700 if (!window->destroyed)
1702 if (GDK_WINDOW_IS_MAPPED (window))
1703 gdk_synthesize_window_state (window,
1705 GDK_WINDOW_STATE_WITHDRAWN);
1707 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1711 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1712 GDK_WINDOW_XID (window), 0);
1714 post_unmap (window);
1719 window_x11_move (GdkWindow *window,
1723 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1725 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1727 /* The window isn't actually damaged, but it's parent is */
1728 window_pre_damage (window);
1729 _gdk_x11_window_move_resize_child (window,
1731 window->width, window->height);
1735 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1736 GDK_WINDOW_XID (window),
1739 if (impl->override_redirect)
1748 window_x11_resize (GdkWindow *window,
1758 window_pre_damage (window);
1760 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1762 _gdk_x11_window_move_resize_child (window,
1763 window->x, window->y,
1768 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1770 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1771 GDK_WINDOW_XID (window),
1774 if (impl->override_redirect)
1776 window->width = width;
1777 window->height = height;
1778 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1782 if (width != window->width || height != window->height)
1783 window->resize_count += 1;
1787 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1791 window_x11_move_resize (GdkWindow *window,
1803 window_pre_damage (window);
1805 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1807 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1808 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1812 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1814 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1815 GDK_WINDOW_XID (window),
1816 x, y, width, height);
1818 if (impl->override_redirect)
1823 window->width = width;
1824 window->height = height;
1826 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1830 if (width != window->width || height != window->height)
1831 window->resize_count += 1;
1837 gdk_window_x11_move_resize (GdkWindow *window,
1844 if (with_move && (width < 0 && height < 0))
1845 window_x11_move (window, x, y);
1849 window_x11_move_resize (window, x, y, width, height);
1851 window_x11_resize (window, width, height);
1856 gdk_window_x11_reparent (GdkWindow *window,
1857 GdkWindow *new_parent,
1861 GdkWindowImplX11 *impl;
1863 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1865 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1866 _gdk_x11_window_tmp_unset_parent_bg (window);
1867 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1868 GDK_WINDOW_XID (window),
1869 GDK_WINDOW_XID (new_parent),
1870 new_parent->abs_x + x, new_parent->abs_y + y);
1871 _gdk_x11_window_tmp_reset_parent_bg (window);
1872 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1874 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1875 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1877 window->parent = new_parent;
1879 /* Switch the window type as appropriate */
1881 switch (GDK_WINDOW_TYPE (new_parent))
1883 case GDK_WINDOW_ROOT:
1884 case GDK_WINDOW_FOREIGN:
1885 /* Reparenting to toplevel */
1887 if (!WINDOW_IS_TOPLEVEL (window) &&
1888 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1890 /* This is also done in common code at a later stage, but we
1891 need it in setup_toplevel, so do it here too */
1892 if (window->toplevel_window_type != -1)
1893 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1894 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1895 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1897 /* Wasn't a toplevel, set up */
1898 setup_toplevel_window (window, new_parent);
1903 case GDK_WINDOW_TOPLEVEL:
1904 case GDK_WINDOW_CHILD:
1905 case GDK_WINDOW_TEMP:
1906 if (WINDOW_IS_TOPLEVEL (window) &&
1909 if (impl->toplevel->focus_window)
1911 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1912 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1915 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1917 g_free (impl->toplevel);
1918 impl->toplevel = NULL;
1926 gdk_window_x11_raise (GdkWindow *window)
1928 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1932 gdk_window_x11_restack_under (GdkWindow *window,
1933 GList *native_siblings /* in requested order, first is bottom-most */)
1939 n_windows = g_list_length (native_siblings) + 1;
1940 windows = g_new (Window, n_windows);
1942 windows[0] = GDK_WINDOW_XID (window);
1943 /* Reverse order, as input order is bottom-most first */
1945 for (l = native_siblings; l != NULL; l = l->next)
1946 windows[i--] = GDK_WINDOW_XID (l->data);
1948 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1954 gdk_window_x11_restack_toplevel (GdkWindow *window,
1958 XWindowChanges changes;
1960 changes.sibling = GDK_WINDOW_XID (sibling);
1961 changes.stack_mode = above ? Above : Below;
1962 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1963 GDK_WINDOW_XID (window),
1964 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1965 CWStackMode | CWSibling, &changes);
1969 gdk_window_x11_lower (GdkWindow *window)
1971 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1975 * gdk_x11_window_move_to_current_desktop:
1976 * @window: (type GdkX11Window): a #GdkWindow
1978 * Moves the window to the correct workspace when running under a
1979 * window manager that supports multiple workspaces, as described
1980 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
1981 * Window Manager Hints</ulink>. Will not do anything if the
1982 * window is already on all workspaces.
1987 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1989 GdkToplevelX11 *toplevel;
1991 g_return_if_fail (GDK_IS_WINDOW (window));
1992 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1994 toplevel = _gdk_x11_window_get_toplevel (window);
1996 if (toplevel->on_all_desktops)
1999 move_to_current_desktop (window);
2003 move_to_current_desktop (GdkWindow *window)
2005 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2006 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
2007 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2008 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
2015 gulong *current_desktop;
2016 GdkDisplay *display;
2018 display = gdk_window_get_display (window);
2020 /* Get current desktop, then set it; this is a race, but not
2021 * one that matters much in practice.
2023 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
2024 GDK_WINDOW_XROOTWIN (window),
2025 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
2027 False, XA_CARDINAL, &type, &format, &nitems,
2028 &bytes_after, &data);
2030 if (type == XA_CARDINAL)
2032 XClientMessageEvent xclient;
2033 current_desktop = (gulong *)data;
2035 memset (&xclient, 0, sizeof (xclient));
2036 xclient.type = ClientMessage;
2038 xclient.send_event = True;
2039 xclient.window = GDK_WINDOW_XID (window);
2040 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
2041 xclient.format = 32;
2043 xclient.data.l[0] = *current_desktop;
2044 xclient.data.l[1] = 1; /* source indication */
2045 xclient.data.l[2] = 0;
2046 xclient.data.l[3] = 0;
2047 xclient.data.l[4] = 0;
2049 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
2050 GDK_WINDOW_XROOTWIN (window),
2052 SubstructureRedirectMask | SubstructureNotifyMask,
2053 (XEvent *)&xclient);
2055 XFree (current_desktop);
2061 gdk_x11_window_focus (GdkWindow *window,
2064 GdkDisplay *display;
2066 g_return_if_fail (GDK_IS_WINDOW (window));
2068 if (GDK_WINDOW_DESTROYED (window) ||
2069 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2072 display = GDK_WINDOW_DISPLAY (window);
2074 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2075 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2077 XClientMessageEvent xclient;
2079 memset (&xclient, 0, sizeof (xclient));
2080 xclient.type = ClientMessage;
2081 xclient.window = GDK_WINDOW_XID (window);
2082 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2083 "_NET_ACTIVE_WINDOW");
2084 xclient.format = 32;
2085 xclient.data.l[0] = 1; /* requestor type; we're an app */
2086 xclient.data.l[1] = timestamp;
2087 xclient.data.l[2] = None; /* currently active window */
2088 xclient.data.l[3] = 0;
2089 xclient.data.l[4] = 0;
2091 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2092 SubstructureRedirectMask | SubstructureNotifyMask,
2093 (XEvent *)&xclient);
2097 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2099 /* There is no way of knowing reliably whether we are viewable;
2100 * so trap errors asynchronously around the XSetInputFocus call
2102 gdk_x11_display_error_trap_push (display);
2103 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2104 GDK_WINDOW_XID (window),
2107 gdk_x11_display_error_trap_pop_ignored (display);
2112 gdk_x11_window_set_type_hint (GdkWindow *window,
2113 GdkWindowTypeHint hint)
2115 GdkDisplay *display;
2118 if (GDK_WINDOW_DESTROYED (window) ||
2119 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2122 display = gdk_window_get_display (window);
2126 case GDK_WINDOW_TYPE_HINT_DIALOG:
2127 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2129 case GDK_WINDOW_TYPE_HINT_MENU:
2130 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2132 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2133 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2135 case GDK_WINDOW_TYPE_HINT_UTILITY:
2136 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2138 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2139 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2141 case GDK_WINDOW_TYPE_HINT_DOCK:
2142 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2144 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2145 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2147 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2148 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2150 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2151 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2153 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2154 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2156 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2157 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2159 case GDK_WINDOW_TYPE_HINT_COMBO:
2160 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2162 case GDK_WINDOW_TYPE_HINT_DND:
2163 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2166 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2168 case GDK_WINDOW_TYPE_HINT_NORMAL:
2169 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2173 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2174 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2175 XA_ATOM, 32, PropModeReplace,
2176 (guchar *)&atom, 1);
2179 static GdkWindowTypeHint
2180 gdk_x11_window_get_type_hint (GdkWindow *window)
2182 GdkDisplay *display;
2183 GdkWindowTypeHint type;
2186 gulong nitems_return;
2187 gulong bytes_after_return;
2188 guchar *data = NULL;
2190 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2192 if (GDK_WINDOW_DESTROYED (window) ||
2193 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2194 return GDK_WINDOW_TYPE_HINT_NORMAL;
2196 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2198 display = gdk_window_get_display (window);
2200 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2201 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2202 0, G_MAXLONG, False, XA_ATOM, &type_return,
2203 &format_return, &nitems_return, &bytes_after_return,
2206 if ((type_return == XA_ATOM) && (format_return == 32) &&
2207 (data) && (nitems_return == 1))
2209 Atom atom = *(Atom*)data;
2211 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2212 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2213 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2214 type = GDK_WINDOW_TYPE_HINT_MENU;
2215 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2216 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2217 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2218 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2219 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2220 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2221 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2222 type = GDK_WINDOW_TYPE_HINT_DOCK;
2223 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2224 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2225 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2226 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2227 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2228 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2229 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2230 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2231 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2232 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2233 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2234 type = GDK_WINDOW_TYPE_HINT_COMBO;
2235 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2236 type = GDK_WINDOW_TYPE_HINT_DND;
2239 if (type_return != None && data != NULL)
2247 gdk_wmspec_change_state (gboolean add,
2252 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2253 XClientMessageEvent xclient;
2255 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2256 #define _NET_WM_STATE_ADD 1 /* add/set property */
2257 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2259 memset (&xclient, 0, sizeof (xclient));
2260 xclient.type = ClientMessage;
2261 xclient.window = GDK_WINDOW_XID (window);
2262 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2263 xclient.format = 32;
2264 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2265 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2266 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2267 xclient.data.l[3] = 1; /* source indication */
2268 xclient.data.l[4] = 0;
2270 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2271 SubstructureRedirectMask | SubstructureNotifyMask,
2272 (XEvent *)&xclient);
2276 gdk_x11_window_set_modal_hint (GdkWindow *window,
2279 if (GDK_WINDOW_DESTROYED (window) ||
2280 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2283 window->modal_hint = modal;
2285 if (GDK_WINDOW_IS_MAPPED (window))
2286 gdk_wmspec_change_state (modal, window,
2287 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2292 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2293 gboolean skips_taskbar)
2295 GdkToplevelX11 *toplevel;
2297 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2299 if (GDK_WINDOW_DESTROYED (window) ||
2300 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2303 toplevel = _gdk_x11_window_get_toplevel (window);
2304 toplevel->skip_taskbar_hint = skips_taskbar;
2306 if (GDK_WINDOW_IS_MAPPED (window))
2307 gdk_wmspec_change_state (skips_taskbar, window,
2308 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2313 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2314 gboolean skips_pager)
2316 GdkToplevelX11 *toplevel;
2318 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2320 if (GDK_WINDOW_DESTROYED (window) ||
2321 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2324 toplevel = _gdk_x11_window_get_toplevel (window);
2325 toplevel->skip_pager_hint = skips_pager;
2327 if (GDK_WINDOW_IS_MAPPED (window))
2328 gdk_wmspec_change_state (skips_pager, window,
2329 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2334 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2337 GdkToplevelX11 *toplevel;
2339 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2341 if (GDK_WINDOW_DESTROYED (window) ||
2342 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2345 toplevel = _gdk_x11_window_get_toplevel (window);
2346 toplevel->urgency_hint = urgent;
2348 update_wm_hints (window, FALSE);
2352 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2353 const GdkGeometry *geometry,
2354 GdkWindowHints geom_mask)
2356 XSizeHints size_hints;
2358 if (GDK_WINDOW_DESTROYED (window) ||
2359 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2362 size_hints.flags = 0;
2364 if (geom_mask & GDK_HINT_POS)
2366 size_hints.flags |= PPosition;
2367 /* We need to initialize the following obsolete fields because KWM
2368 * apparently uses these fields if they are non-zero.
2375 if (geom_mask & GDK_HINT_USER_POS)
2377 size_hints.flags |= USPosition;
2380 if (geom_mask & GDK_HINT_USER_SIZE)
2382 size_hints.flags |= USSize;
2385 if (geom_mask & GDK_HINT_MIN_SIZE)
2387 size_hints.flags |= PMinSize;
2388 size_hints.min_width = geometry->min_width;
2389 size_hints.min_height = geometry->min_height;
2392 if (geom_mask & GDK_HINT_MAX_SIZE)
2394 size_hints.flags |= PMaxSize;
2395 size_hints.max_width = MAX (geometry->max_width, 1);
2396 size_hints.max_height = MAX (geometry->max_height, 1);
2399 if (geom_mask & GDK_HINT_BASE_SIZE)
2401 size_hints.flags |= PBaseSize;
2402 size_hints.base_width = geometry->base_width;
2403 size_hints.base_height = geometry->base_height;
2406 if (geom_mask & GDK_HINT_RESIZE_INC)
2408 size_hints.flags |= PResizeInc;
2409 size_hints.width_inc = geometry->width_inc;
2410 size_hints.height_inc = geometry->height_inc;
2413 if (geom_mask & GDK_HINT_ASPECT)
2415 size_hints.flags |= PAspect;
2416 if (geometry->min_aspect <= 1)
2418 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2419 size_hints.min_aspect.y = 65536;
2423 size_hints.min_aspect.x = 65536;
2424 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2426 if (geometry->max_aspect <= 1)
2428 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2429 size_hints.max_aspect.y = 65536;
2433 size_hints.max_aspect.x = 65536;
2434 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2438 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2440 size_hints.flags |= PWinGravity;
2441 size_hints.win_gravity = geometry->win_gravity;
2444 /* FIXME: Would it be better to delete this property if
2445 * geom_mask == 0? It would save space on the server
2447 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2448 GDK_WINDOW_XID (window),
2453 gdk_window_get_geometry_hints (GdkWindow *window,
2454 GdkGeometry *geometry,
2455 GdkWindowHints *geom_mask)
2457 XSizeHints *size_hints;
2458 glong junk_supplied_mask = 0;
2460 g_return_if_fail (GDK_IS_WINDOW (window));
2461 g_return_if_fail (geometry != NULL);
2462 g_return_if_fail (geom_mask != NULL);
2466 if (GDK_WINDOW_DESTROYED (window) ||
2467 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2470 size_hints = XAllocSizeHints ();
2474 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2475 GDK_WINDOW_XID (window),
2477 &junk_supplied_mask))
2478 size_hints->flags = 0;
2480 if (size_hints->flags & PMinSize)
2482 *geom_mask |= GDK_HINT_MIN_SIZE;
2483 geometry->min_width = size_hints->min_width;
2484 geometry->min_height = size_hints->min_height;
2487 if (size_hints->flags & PMaxSize)
2489 *geom_mask |= GDK_HINT_MAX_SIZE;
2490 geometry->max_width = MAX (size_hints->max_width, 1);
2491 geometry->max_height = MAX (size_hints->max_height, 1);
2494 if (size_hints->flags & PResizeInc)
2496 *geom_mask |= GDK_HINT_RESIZE_INC;
2497 geometry->width_inc = size_hints->width_inc;
2498 geometry->height_inc = size_hints->height_inc;
2501 if (size_hints->flags & PAspect)
2503 *geom_mask |= GDK_HINT_ASPECT;
2505 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2506 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2509 if (size_hints->flags & PWinGravity)
2511 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2512 geometry->win_gravity = size_hints->win_gravity;
2519 utf8_is_latin1 (const gchar *str)
2521 const char *p = str;
2525 gunichar ch = g_utf8_get_char (p);
2530 p = g_utf8_next_char (p);
2536 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2537 * convertable to STRING, otherwise, set it as compound text
2540 set_text_property (GdkDisplay *display,
2543 const gchar *utf8_str)
2545 gchar *prop_text = NULL;
2549 gboolean is_compound_text;
2551 if (utf8_is_latin1 (utf8_str))
2553 prop_type = XA_STRING;
2554 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2555 prop_length = prop_text ? strlen (prop_text) : 0;
2557 is_compound_text = FALSE;
2563 gdk_x11_display_utf8_to_compound_text (display,
2564 utf8_str, &gdk_type, &prop_format,
2565 (guchar **)&prop_text, &prop_length);
2566 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2567 is_compound_text = TRUE;
2572 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2575 prop_type, prop_format,
2576 PropModeReplace, (guchar *)prop_text,
2579 if (is_compound_text)
2580 gdk_x11_free_compound_text ((guchar *)prop_text);
2586 /* Set WM_NAME and _NET_WM_NAME
2589 set_wm_name (GdkDisplay *display,
2593 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2594 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2595 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2596 PropModeReplace, (guchar *)name, strlen (name));
2598 set_text_property (display, xwindow,
2599 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2604 gdk_x11_window_set_title (GdkWindow *window,
2607 GdkDisplay *display;
2611 g_return_if_fail (title != NULL);
2613 if (GDK_WINDOW_DESTROYED (window) ||
2614 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2617 display = gdk_window_get_display (window);
2618 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2619 xwindow = GDK_WINDOW_XID (window);
2621 set_wm_name (display, xwindow, title);
2623 if (!gdk_window_icon_name_set (window))
2625 XChangeProperty (xdisplay, xwindow,
2626 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2627 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2628 PropModeReplace, (guchar *)title, strlen (title));
2630 set_text_property (display, xwindow,
2631 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2637 gdk_x11_window_set_role (GdkWindow *window,
2640 GdkDisplay *display;
2642 display = gdk_window_get_display (window);
2644 if (GDK_WINDOW_DESTROYED (window) ||
2645 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2649 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2650 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2651 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2653 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2654 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2658 gdk_x11_window_set_startup_id (GdkWindow *window,
2659 const gchar *startup_id)
2661 GdkDisplay *display;
2663 g_return_if_fail (GDK_IS_WINDOW (window));
2665 display = gdk_window_get_display (window);
2667 if (GDK_WINDOW_DESTROYED (window) ||
2668 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2672 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2673 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2674 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2675 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2677 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2678 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2682 gdk_x11_window_set_transient_for (GdkWindow *window,
2685 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2686 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2687 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2688 GDK_WINDOW_XID (window),
2689 GDK_WINDOW_XID (parent));
2693 gdk_window_x11_set_back_color (GdkWindow *window,
2699 GdkVisual *visual = gdk_window_get_visual (window);
2701 /* I suppose we could handle these, but that'd require fiddling with
2702 * xrender formats... */
2706 switch (visual->type)
2708 case GDK_VISUAL_DIRECT_COLOR:
2709 case GDK_VISUAL_TRUE_COLOR:
2711 /* If bits not used for color are used for something other than padding,
2712 * it's likely alpha, so we set them to 1s.
2714 guint padding, pixel;
2716 /* Shifting by >= width-of-type isn't defined in C */
2717 if (visual->depth >= 32)
2720 padding = ((~(guint32)0)) << visual->depth;
2722 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2724 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2725 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2726 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2728 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2729 GDK_WINDOW_XID (window), pixel);
2733 /* These require fiddling with the colormap, and as they're essentially unused
2734 * we're just gonna skip them for now.
2736 case GDK_VISUAL_PSEUDO_COLOR:
2737 case GDK_VISUAL_GRAYSCALE:
2738 case GDK_VISUAL_STATIC_GRAY:
2739 case GDK_VISUAL_STATIC_COLOR:
2748 matrix_is_identity (cairo_matrix_t *matrix)
2750 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2751 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2752 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2756 gdk_window_x11_set_background (GdkWindow *window,
2757 cairo_pattern_t *pattern)
2760 cairo_surface_t *surface;
2761 cairo_matrix_t matrix;
2763 if (GDK_WINDOW_DESTROYED (window))
2766 if (pattern == NULL)
2770 /* X throws BadMatch if the parent has a different visual when
2771 * using ParentRelative */
2772 parent = gdk_window_get_parent (window);
2773 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2774 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2775 GDK_WINDOW_XID (window), ParentRelative);
2777 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2778 GDK_WINDOW_XID (window), None);
2782 switch (cairo_pattern_get_type (pattern))
2784 case CAIRO_PATTERN_TYPE_SOLID:
2785 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2786 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2789 case CAIRO_PATTERN_TYPE_SURFACE:
2790 cairo_pattern_get_matrix (pattern, &matrix);
2791 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2792 matrix_is_identity (&matrix) &&
2793 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2794 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2795 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2799 cairo_surface_get_device_offset (surface, &x, &y);
2800 /* XXX: This still bombs for non-pixmaps, but there's no way to
2801 * detect we're not a pixmap in Cairo... */
2802 if (x == 0.0 && y == 0.0)
2804 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2805 GDK_WINDOW_XID (window),
2806 cairo_xlib_surface_get_drawable (surface));
2811 case CAIRO_PATTERN_TYPE_LINEAR:
2812 case CAIRO_PATTERN_TYPE_RADIAL:
2814 /* fallback: just use black */
2818 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2819 GDK_WINDOW_XID (window), None);
2823 gdk_window_x11_set_device_cursor (GdkWindow *window,
2827 GdkWindowImplX11 *impl;
2829 g_return_if_fail (GDK_IS_WINDOW (window));
2830 g_return_if_fail (GDK_IS_DEVICE (device));
2832 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2835 g_hash_table_remove (impl->device_cursor, device);
2838 _gdk_x11_cursor_update_theme (cursor);
2839 g_hash_table_replace (impl->device_cursor,
2840 device, g_object_ref (cursor));
2843 if (!GDK_WINDOW_DESTROYED (window))
2844 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2848 _gdk_x11_window_get_cursor (GdkWindow *window)
2850 GdkWindowImplX11 *impl;
2852 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2854 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2856 return impl->cursor;
2860 gdk_window_x11_get_geometry (GdkWindow *window,
2871 guint tborder_width;
2874 if (!GDK_WINDOW_DESTROYED (window))
2876 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2877 GDK_WINDOW_XID (window),
2878 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2892 gdk_window_x11_get_root_coords (GdkWindow *window,
2903 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2904 GDK_WINDOW_XID (window),
2905 GDK_WINDOW_XROOTWIN (window),
2918 gdk_x11_window_get_root_origin (GdkWindow *window,
2924 gdk_window_get_frame_extents (window, &rect);
2934 gdk_x11_window_get_frame_extents (GdkWindow *window,
2937 GdkDisplay *display;
2938 GdkWindowImplX11 *impl;
2949 gulong nitems_return;
2950 gulong bytes_after_return;
2953 guint ww, wh, wb, wd;
2955 gboolean got_frame_extents = FALSE;
2957 g_return_if_fail (rect != NULL);
2964 while (window->parent && (window->parent)->parent)
2965 window = window->parent;
2967 /* Refine our fallback answer a bit using local information */
2968 rect->x = window->x;
2969 rect->y = window->y;
2970 rect->width = window->width;
2971 rect->height = window->height;
2973 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2974 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2980 display = gdk_window_get_display (window);
2982 gdk_x11_display_error_trap_push (display);
2984 xwindow = GDK_WINDOW_XID (window);
2986 /* first try: use _NET_FRAME_EXTENTS */
2987 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2988 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
2989 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2990 gdk_x11_get_xatom_by_name_for_display (display,
2991 "_NET_FRAME_EXTENTS"),
2992 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2993 &format_return, &nitems_return, &bytes_after_return,
2997 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2998 (nitems_return == 4) && (data))
3000 gulong *ldata = (gulong *) data;
3001 got_frame_extents = TRUE;
3003 /* try to get the real client window geometry */
3004 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3005 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
3006 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
3007 xwindow, root, 0, 0, &wx, &wy, &child))
3015 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
3016 rect->x -= ldata[0];
3017 rect->y -= ldata[2];
3018 rect->width += ldata[0] + ldata[1];
3019 rect->height += ldata[2] + ldata[3];
3026 if (got_frame_extents)
3029 /* no frame extents property available, which means we either have a WM that
3030 is not EWMH compliant or is broken - try fallback and walk up the window
3031 tree to get our window's parent which hopefully is the window frame */
3033 /* use NETWM_VIRTUAL_ROOTS if available */
3034 root = GDK_WINDOW_XROOTWIN (window);
3036 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3037 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
3038 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
3039 gdk_x11_get_xatom_by_name_for_display (display,
3040 "_NET_VIRTUAL_ROOTS"),
3041 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3042 &format_return, &nitems_return, &bytes_after_return,
3046 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
3048 nvroots = nitems_return;
3049 vroots = (Window *)data;
3053 xparent = GDK_WINDOW_XID (window);
3059 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3061 &children, &nchildren))
3067 /* check virtual roots */
3068 for (i = 0; i < nvroots; i++)
3070 if (xparent == vroots[i])
3077 while (xparent != root);
3079 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3080 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3092 gdk_x11_display_error_trap_pop_ignored (display);
3096 gdk_window_x11_get_device_state (GdkWindow *window,
3100 GdkModifierType *mask)
3104 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3106 if (GDK_WINDOW_DESTROYED (window))
3109 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3113 return child != NULL;
3117 gdk_window_x11_get_events (GdkWindow *window)
3119 XWindowAttributes attrs;
3120 GdkEventMask event_mask;
3121 GdkEventMask filtered;
3123 if (GDK_WINDOW_DESTROYED (window))
3127 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3128 GDK_WINDOW_XID (window),
3130 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3131 /* if property change was filtered out before, keep it filtered out */
3132 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3133 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3139 gdk_window_x11_set_events (GdkWindow *window,
3140 GdkEventMask event_mask)
3142 long xevent_mask = 0;
3144 if (!GDK_WINDOW_DESTROYED (window))
3146 GdkX11Display *display_x11;
3148 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3149 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3151 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3152 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3153 GDK_WINDOW_XID (window), event_mask,
3159 do_shape_combine_region (GdkWindow *window,
3160 const cairo_region_t *shape_region,
3165 if (GDK_WINDOW_DESTROYED (window))
3168 if (shape_region == NULL)
3170 /* Use NULL mask to unset the shape */
3171 if (shape == ShapeBounding
3172 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3173 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3175 if (shape == ShapeBounding)
3177 _gdk_x11_window_tmp_unset_parent_bg (window);
3178 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3180 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3181 GDK_WINDOW_XID (window),
3186 if (shape == ShapeBounding)
3188 _gdk_x11_window_tmp_reset_parent_bg (window);
3189 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3195 if (shape == ShapeBounding
3196 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3197 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3200 XRectangle *xrects = NULL;
3202 _gdk_x11_region_get_xrectangles (shape_region,
3206 if (shape == ShapeBounding)
3208 _gdk_x11_window_tmp_unset_parent_bg (window);
3209 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3211 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3212 GDK_WINDOW_XID (window),
3219 if (shape == ShapeBounding)
3221 _gdk_x11_window_tmp_reset_parent_bg (window);
3222 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3230 gdk_window_x11_shape_combine_region (GdkWindow *window,
3231 const cairo_region_t *shape_region,
3235 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3239 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3240 const cairo_region_t *shape_region,
3245 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3251 gdk_x11_window_set_override_redirect (GdkWindow *window,
3252 gboolean override_redirect)
3254 XSetWindowAttributes attr;
3256 if (!GDK_WINDOW_DESTROYED (window) &&
3257 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3259 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3261 attr.override_redirect = (override_redirect? True : False);
3262 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3263 GDK_WINDOW_XID (window),
3267 impl->override_redirect = attr.override_redirect;
3272 gdk_x11_window_set_accept_focus (GdkWindow *window,
3273 gboolean accept_focus)
3275 accept_focus = accept_focus != FALSE;
3277 if (window->accept_focus != accept_focus)
3279 window->accept_focus = accept_focus;
3281 if (!GDK_WINDOW_DESTROYED (window) &&
3282 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3283 update_wm_hints (window, FALSE);
3288 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3289 gboolean focus_on_map)
3291 focus_on_map = focus_on_map != FALSE;
3293 if (window->focus_on_map != focus_on_map)
3295 window->focus_on_map = focus_on_map;
3297 if ((!GDK_WINDOW_DESTROYED (window)) &&
3298 (!window->focus_on_map) &&
3299 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3300 gdk_x11_window_set_user_time (window, 0);
3305 * gdk_x11_window_set_user_time:
3306 * @window: (type GdkX11Window): A toplevel #GdkWindow
3307 * @timestamp: An XServer timestamp to which the property should be set
3309 * The application can use this call to update the _NET_WM_USER_TIME
3310 * property on a toplevel window. This property stores an Xserver
3311 * time which represents the time of the last user input event
3312 * received for this window. This property may be used by the window
3313 * manager to alter the focus, stacking, and/or placement behavior of
3314 * windows when they are mapped depending on whether the new window
3315 * was created by a user action or is a "pop-up" window activated by a
3316 * timer or some other event.
3318 * Note that this property is automatically updated by GDK, so this
3319 * function should only be used by applications which handle input
3320 * events bypassing GDK.
3325 gdk_x11_window_set_user_time (GdkWindow *window,
3328 GdkDisplay *display;
3329 GdkX11Display *display_x11;
3330 GdkToplevelX11 *toplevel;
3331 glong timestamp_long = (glong)timestamp;
3334 if (GDK_WINDOW_DESTROYED (window) ||
3335 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3338 display = gdk_window_get_display (window);
3339 display_x11 = GDK_X11_DISPLAY (display);
3340 toplevel = _gdk_x11_window_get_toplevel (window);
3344 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3348 if (toplevel->focus_window != None &&
3349 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3350 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3351 xid = toplevel->focus_window;
3353 xid = GDK_WINDOW_XID (window);
3355 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3356 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3357 XA_CARDINAL, 32, PropModeReplace,
3358 (guchar *)×tamp_long, 1);
3360 if (timestamp_long != GDK_CURRENT_TIME &&
3361 (display_x11->user_time == GDK_CURRENT_TIME ||
3362 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3363 display_x11->user_time = timestamp_long;
3366 toplevel->user_time = timestamp_long;
3370 * gdk_x11_window_set_utf8_property:
3371 * @window: (type GdkX11Window): a #GdkWindow
3372 * @name: Property name, will be interned as an X atom
3373 * @value: (allow-none): Property value, or %NULL to delete
3375 * This function modifies or removes an arbitrary X11 window
3376 * property of type UTF8_STRING. If the given @window is
3377 * not a toplevel window, it is ignored.
3382 gdk_x11_window_set_utf8_property (GdkWindow *window,
3386 GdkDisplay *display;
3388 if (!WINDOW_IS_TOPLEVEL (window))
3391 display = gdk_window_get_display (window);
3395 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3396 GDK_WINDOW_XID (window),
3397 gdk_x11_get_xatom_by_name_for_display (display, name),
3398 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3399 PropModeReplace, (guchar *)value, strlen (value));
3403 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3404 GDK_WINDOW_XID (window),
3405 gdk_x11_get_xatom_by_name_for_display (display, name));
3410 * gdk_x11_window_set_hide_titlebar_when_maximized:
3411 * @window: (type GdkX11Window): a #GdkWindow
3412 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3415 * Set a hint for the window manager, requesting that the titlebar
3416 * should be hidden when the window is maximized.
3418 * Note that this property is automatically updated by GTK+, so this
3419 * function should only be used by applications which do not use GTK+
3420 * to create toplevel windows.
3425 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3426 gboolean hide_titlebar_when_maximized)
3428 GdkDisplay *display;
3430 if (!WINDOW_IS_TOPLEVEL (window))
3433 display = gdk_window_get_display (window);
3435 if (hide_titlebar_when_maximized)
3438 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3439 GDK_WINDOW_XID (window),
3440 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3442 PropModeReplace, (guchar *)&hide, 1);
3446 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3447 GDK_WINDOW_XID (window),
3448 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3453 * gdk_x11_window_set_theme_variant:
3454 * @window: (type GdkX11Window): a #GdkWindow
3455 * @variant: the theme variant to export
3457 * GTK+ applications can request a dark theme variant. In order to
3458 * make other applications - namely window managers using GTK+ for
3459 * themeing - aware of this choice, GTK+ uses this function to
3460 * export the requested theme variant as _GTK_THEME_VARIANT property
3461 * on toplevel windows.
3463 * Note that this property is automatically updated by GTK+, so this
3464 * function should only be used by applications which do not use GTK+
3465 * to create toplevel windows.
3470 gdk_x11_window_set_theme_variant (GdkWindow *window,
3473 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3476 #define GDK_SELECTION_MAX_SIZE(display) \
3478 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3479 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3480 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3483 gdk_window_update_icon (GdkWindow *window,
3486 GdkToplevelX11 *toplevel;
3487 GdkPixbuf *best_icon;
3491 toplevel = _gdk_x11_window_get_toplevel (window);
3493 if (toplevel->icon_pixmap != NULL)
3495 cairo_surface_destroy (toplevel->icon_pixmap);
3496 toplevel->icon_pixmap = NULL;
3499 if (toplevel->icon_mask != NULL)
3501 cairo_surface_destroy (toplevel->icon_mask);
3502 toplevel->icon_mask = NULL;
3505 #define IDEAL_SIZE 48
3507 best_size = G_MAXINT;
3509 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3511 GdkPixbuf *pixbuf = tmp_list->data;
3514 /* average width and height - if someone passes in a rectangular
3515 * icon they deserve what they get.
3517 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3520 if (best_icon == NULL)
3527 /* icon is better if it's 32 pixels or larger, and closer to
3528 * the ideal size than the current best.
3531 (ABS (best_size - IDEAL_SIZE) <
3532 ABS (this - IDEAL_SIZE)))
3542 int width = gdk_pixbuf_get_width (best_icon);
3543 int height = gdk_pixbuf_get_height (best_icon);
3546 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3550 cr = cairo_create (toplevel->icon_pixmap);
3551 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3552 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3553 if (gdk_pixbuf_get_has_alpha (best_icon))
3555 /* Saturate the image, so it has bilevel alpha */
3556 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3558 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3560 cairo_pop_group_to_source (cr);
3565 if (gdk_pixbuf_get_has_alpha (best_icon))
3567 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3571 cr = cairo_create (toplevel->icon_mask);
3572 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3573 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3579 update_wm_hints (window, FALSE);
3583 gdk_x11_window_set_icon_list (GdkWindow *window,
3592 gint width, height, stride;
3595 GdkDisplay *display;
3598 if (GDK_WINDOW_DESTROYED (window) ||
3599 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3602 display = gdk_window_get_display (window);
3610 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3612 width = gdk_pixbuf_get_width (pixbuf);
3613 height = gdk_pixbuf_get_height (pixbuf);
3615 /* silently ignore overlarge icons */
3616 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3618 g_warning ("gdk_window_set_icon_list: icons too large");
3623 size += 2 + width * height;
3625 l = g_list_next (l);
3628 data = g_malloc (size * sizeof (gulong));
3636 width = gdk_pixbuf_get_width (pixbuf);
3637 height = gdk_pixbuf_get_height (pixbuf);
3638 stride = gdk_pixbuf_get_rowstride (pixbuf);
3639 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3644 pixels = gdk_pixbuf_get_pixels (pixbuf);
3646 for (y = 0; y < height; y++)
3648 for (x = 0; x < width; x++)
3652 r = pixels[y*stride + x*n_channels + 0];
3653 g = pixels[y*stride + x*n_channels + 1];
3654 b = pixels[y*stride + x*n_channels + 2];
3655 if (n_channels >= 4)
3656 a = pixels[y*stride + x*n_channels + 3];
3660 *p++ = a << 24 | r << 16 | g << 8 | b ;
3664 l = g_list_next (l);
3670 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3671 GDK_WINDOW_XID (window),
3672 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3675 (guchar*) data, size);
3679 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3680 GDK_WINDOW_XID (window),
3681 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3686 gdk_window_update_icon (window, pixbufs);
3690 gdk_window_icon_name_set (GdkWindow *window)
3692 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3693 g_quark_from_static_string ("gdk-icon-name-set")));
3697 gdk_x11_window_set_icon_name (GdkWindow *window,
3700 GdkDisplay *display;
3702 if (GDK_WINDOW_DESTROYED (window) ||
3703 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3706 display = gdk_window_get_display (window);
3708 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3709 GUINT_TO_POINTER (name != NULL));
3713 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3714 GDK_WINDOW_XID (window),
3715 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3716 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3717 PropModeReplace, (guchar *)name, strlen (name));
3719 set_text_property (display, GDK_WINDOW_XID (window),
3720 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3725 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3726 GDK_WINDOW_XID (window),
3727 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3728 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3729 GDK_WINDOW_XID (window),
3730 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3735 gdk_x11_window_iconify (GdkWindow *window)
3737 if (GDK_WINDOW_DESTROYED (window) ||
3738 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3741 if (GDK_WINDOW_IS_MAPPED (window))
3743 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3744 GDK_WINDOW_XID (window),
3745 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3749 /* Flip our client side flag, the real work happens on map. */
3750 gdk_synthesize_window_state (window,
3752 GDK_WINDOW_STATE_ICONIFIED);
3753 gdk_wmspec_change_state (TRUE, window,
3754 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3760 gdk_x11_window_deiconify (GdkWindow *window)
3762 if (GDK_WINDOW_DESTROYED (window) ||
3763 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3766 if (GDK_WINDOW_IS_MAPPED (window))
3768 gdk_window_show (window);
3769 gdk_wmspec_change_state (FALSE, window,
3770 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3775 /* Flip our client side flag, the real work happens on map. */
3776 gdk_synthesize_window_state (window,
3777 GDK_WINDOW_STATE_ICONIFIED,
3779 gdk_wmspec_change_state (FALSE, window,
3780 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3786 gdk_x11_window_stick (GdkWindow *window)
3788 if (GDK_WINDOW_DESTROYED (window) ||
3789 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3792 if (GDK_WINDOW_IS_MAPPED (window))
3794 /* "stick" means stick to all desktops _and_ do not scroll with the
3795 * viewport. i.e. glue to the monitor glass in all cases.
3798 XClientMessageEvent xclient;
3800 /* Request stick during viewport scroll */
3801 gdk_wmspec_change_state (TRUE, window,
3802 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3805 /* Request desktop 0xFFFFFFFF */
3806 memset (&xclient, 0, sizeof (xclient));
3807 xclient.type = ClientMessage;
3808 xclient.window = GDK_WINDOW_XID (window);
3809 xclient.display = GDK_WINDOW_XDISPLAY (window);
3810 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3812 xclient.format = 32;
3814 xclient.data.l[0] = 0xFFFFFFFF;
3815 xclient.data.l[1] = 0;
3816 xclient.data.l[2] = 0;
3817 xclient.data.l[3] = 0;
3818 xclient.data.l[4] = 0;
3820 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3821 SubstructureRedirectMask | SubstructureNotifyMask,
3822 (XEvent *)&xclient);
3826 /* Flip our client side flag, the real work happens on map. */
3827 gdk_synthesize_window_state (window,
3829 GDK_WINDOW_STATE_STICKY);
3834 gdk_x11_window_unstick (GdkWindow *window)
3836 if (GDK_WINDOW_DESTROYED (window) ||
3837 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3840 if (GDK_WINDOW_IS_MAPPED (window))
3842 /* Request unstick from viewport */
3843 gdk_wmspec_change_state (FALSE, window,
3844 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3847 move_to_current_desktop (window);
3851 /* Flip our client side flag, the real work happens on map. */
3852 gdk_synthesize_window_state (window,
3853 GDK_WINDOW_STATE_STICKY,
3860 gdk_x11_window_maximize (GdkWindow *window)
3862 if (GDK_WINDOW_DESTROYED (window) ||
3863 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3866 if (GDK_WINDOW_IS_MAPPED (window))
3867 gdk_wmspec_change_state (TRUE, window,
3868 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3869 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3871 gdk_synthesize_window_state (window,
3873 GDK_WINDOW_STATE_MAXIMIZED);
3877 gdk_x11_window_unmaximize (GdkWindow *window)
3879 if (GDK_WINDOW_DESTROYED (window) ||
3880 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3883 if (GDK_WINDOW_IS_MAPPED (window))
3884 gdk_wmspec_change_state (FALSE, window,
3885 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3886 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3888 gdk_synthesize_window_state (window,
3889 GDK_WINDOW_STATE_MAXIMIZED,
3894 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3896 if (GDK_WINDOW_DESTROYED (window) ||
3897 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3900 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3901 * to which monitors so span across when the window is fullscreen, but it's
3902 * not a state in itself so this would have no effect if the window is not
3906 if (GDK_WINDOW_IS_MAPPED (window))
3908 XClientMessageEvent xclient;
3909 gint gdk_monitors[4];
3912 memset (&xclient, 0, sizeof (xclient));
3913 xclient.type = ClientMessage;
3914 xclient.window = GDK_WINDOW_XID (window);
3915 xclient.display = GDK_WINDOW_XDISPLAY (window);
3916 xclient.format = 32;
3918 switch (window->fullscreen_mode)
3920 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3922 /* FIXME: This is not part of the EWMH spec!
3924 * There is no documented mechanism to remove the property
3925 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3926 * invalid, largest possible value.
3928 * When given values larger than actual possible monitor values, most
3929 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3930 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3933 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3935 * Note, this (non documented) mechanism is unlikely to be an issue
3936 * as it's used only for transitionning back from "all monitors" to
3937 * "current monitor" mode.
3939 * Applications who don't change the default mode won't trigger this
3942 for (i = 0; i < 4; ++i)
3943 xclient.data.l[i] = G_MAXLONG;
3947 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3949 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3954 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3955 for (i = 0; i < 4; ++i)
3957 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3959 /* Sanity check, if XINERAMA is not available, we could have invalid
3960 * negative values for the XINERAMA indices.
3962 if (xclient.data.l[i] < 0)
3964 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3971 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3972 window->fullscreen_mode);
3976 /* Send fullscreen monitors client message */
3977 xclient.data.l[4] = 1; /* source indication */
3978 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3979 "_NET_WM_FULLSCREEN_MONITORS");
3980 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3981 SubstructureRedirectMask | SubstructureNotifyMask,
3982 (XEvent *)&xclient);
3987 gdk_x11_window_fullscreen (GdkWindow *window)
3989 if (GDK_WINDOW_DESTROYED (window) ||
3990 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3993 if (GDK_WINDOW_IS_MAPPED (window))
3995 gdk_wmspec_change_state (TRUE, window,
3996 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3998 /* Actual XRandR layout may have change since we computed the fullscreen
3999 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
4001 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
4002 gdk_x11_window_apply_fullscreen_mode (window);
4005 gdk_synthesize_window_state (window,
4007 GDK_WINDOW_STATE_FULLSCREEN);
4011 gdk_x11_window_unfullscreen (GdkWindow *window)
4013 if (GDK_WINDOW_DESTROYED (window) ||
4014 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4017 if (GDK_WINDOW_IS_MAPPED (window))
4018 gdk_wmspec_change_state (FALSE, window,
4019 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4023 gdk_synthesize_window_state (window,
4024 GDK_WINDOW_STATE_FULLSCREEN,
4029 gdk_x11_window_set_keep_above (GdkWindow *window,
4032 g_return_if_fail (GDK_IS_WINDOW (window));
4034 if (GDK_WINDOW_DESTROYED (window) ||
4035 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4038 if (GDK_WINDOW_IS_MAPPED (window))
4041 gdk_wmspec_change_state (FALSE, window,
4042 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4044 gdk_wmspec_change_state (setting, window,
4045 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4049 gdk_synthesize_window_state (window,
4050 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4051 setting ? GDK_WINDOW_STATE_ABOVE : 0);
4055 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
4057 g_return_if_fail (GDK_IS_WINDOW (window));
4059 if (GDK_WINDOW_DESTROYED (window) ||
4060 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4063 if (GDK_WINDOW_IS_MAPPED (window))
4066 gdk_wmspec_change_state (FALSE, window,
4067 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4069 gdk_wmspec_change_state (setting, window,
4070 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4074 gdk_synthesize_window_state (window,
4075 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4076 setting ? GDK_WINDOW_STATE_BELOW : 0);
4080 gdk_x11_window_get_group (GdkWindow *window)
4082 GdkToplevelX11 *toplevel;
4084 if (GDK_WINDOW_DESTROYED (window) ||
4085 !WINDOW_IS_TOPLEVEL (window))
4088 toplevel = _gdk_x11_window_get_toplevel (window);
4090 return toplevel->group_leader;
4094 gdk_x11_window_set_group (GdkWindow *window,
4097 GdkToplevelX11 *toplevel;
4099 g_return_if_fail (GDK_IS_WINDOW (window));
4100 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4101 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4103 if (GDK_WINDOW_DESTROYED (window) ||
4104 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4105 !WINDOW_IS_TOPLEVEL (window))
4108 toplevel = _gdk_x11_window_get_toplevel (window);
4111 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4113 if (toplevel->group_leader != leader)
4115 if (toplevel->group_leader)
4116 g_object_unref (toplevel->group_leader);
4117 toplevel->group_leader = g_object_ref (leader);
4118 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4121 update_wm_hints (window, FALSE);
4124 static MotifWmHints *
4125 gdk_window_get_mwm_hints (GdkWindow *window)
4127 GdkDisplay *display;
4128 Atom hints_atom = None;
4135 if (GDK_WINDOW_DESTROYED (window))
4138 display = gdk_window_get_display (window);
4140 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4142 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4143 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4144 False, AnyPropertyType, &type, &format, &nitems,
4145 &bytes_after, &data);
4150 return (MotifWmHints *)data;
4154 gdk_window_set_mwm_hints (GdkWindow *window,
4155 MotifWmHints *new_hints)
4157 GdkDisplay *display;
4158 Atom hints_atom = None;
4160 MotifWmHints *hints;
4166 if (GDK_WINDOW_DESTROYED (window))
4169 display = gdk_window_get_display (window);
4171 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4173 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4174 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4175 False, AnyPropertyType, &type, &format, &nitems,
4176 &bytes_after, &data);
4182 hints = (MotifWmHints *)data;
4184 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4186 hints->flags |= MWM_HINTS_FUNCTIONS;
4187 hints->functions = new_hints->functions;
4189 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4191 hints->flags |= MWM_HINTS_DECORATIONS;
4192 hints->decorations = new_hints->decorations;
4196 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4197 hints_atom, hints_atom, 32, PropModeReplace,
4198 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4200 if (hints != new_hints)
4205 gdk_x11_window_set_decorations (GdkWindow *window,
4206 GdkWMDecoration decorations)
4210 if (GDK_WINDOW_DESTROYED (window) ||
4211 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4214 /* initialize to zero to avoid writing uninitialized data to socket */
4215 memset(&hints, 0, sizeof(hints));
4216 hints.flags = MWM_HINTS_DECORATIONS;
4217 hints.decorations = decorations;
4219 gdk_window_set_mwm_hints (window, &hints);
4223 gdk_x11_window_get_decorations(GdkWindow *window,
4224 GdkWMDecoration *decorations)
4226 MotifWmHints *hints;
4227 gboolean result = FALSE;
4229 if (GDK_WINDOW_DESTROYED (window) ||
4230 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4233 hints = gdk_window_get_mwm_hints (window);
4237 if (hints->flags & MWM_HINTS_DECORATIONS)
4240 *decorations = hints->decorations;
4251 gdk_x11_window_set_functions (GdkWindow *window,
4252 GdkWMFunction functions)
4256 g_return_if_fail (GDK_IS_WINDOW (window));
4258 if (GDK_WINDOW_DESTROYED (window) ||
4259 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4262 /* initialize to zero to avoid writing uninitialized data to socket */
4263 memset(&hints, 0, sizeof(hints));
4264 hints.flags = MWM_HINTS_FUNCTIONS;
4265 hints.functions = functions;
4267 gdk_window_set_mwm_hints (window, &hints);
4271 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4275 cairo_region_t *shape;
4283 /* Note that XShapeGetRectangles returns NULL in two situations:
4284 * - the server doesn't support the SHAPE extension
4285 * - the shape is empty
4287 * Since we can't discriminate these here, we always return
4288 * an empty shape. It is the callers responsibility to check
4289 * whether the server supports the SHAPE extensions beforehand.
4291 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4294 return cairo_region_create (); /* Empty */
4296 if (ord != YXBanded)
4298 /* This really shouldn't happen with any xserver, as they
4299 * generally convert regions to YXBanded internally
4301 g_warning ("non YXBanded shape masks not supported");
4306 rl = g_new (GdkRectangle, rn);
4307 for (i = 0; i < rn; i++)
4311 rl[i].width = xrl[i].width;
4312 rl[i].height = xrl[i].height;
4316 shape = cairo_region_create_rectangles (rl, rn);
4323 static cairo_region_t *
4324 gdk_x11_window_get_shape (GdkWindow *window)
4326 if (!GDK_WINDOW_DESTROYED (window) &&
4327 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4328 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4329 GDK_WINDOW_XID (window),
4335 static cairo_region_t *
4336 gdk_x11_window_get_input_shape (GdkWindow *window)
4338 #if defined(ShapeInput)
4339 if (!GDK_WINDOW_DESTROYED (window) &&
4340 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4341 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4342 GDK_WINDOW_XID (window),
4350 gdk_window_set_static_bit_gravity (GdkWindow *window,
4353 XSetWindowAttributes xattributes;
4354 guint xattributes_mask = 0;
4356 g_return_if_fail (GDK_IS_WINDOW (window));
4358 if (window->input_only)
4361 xattributes.bit_gravity = StaticGravity;
4362 xattributes_mask |= CWBitGravity;
4363 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4364 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4365 GDK_WINDOW_XID (window),
4366 CWBitGravity, &xattributes);
4370 gdk_window_set_static_win_gravity (GdkWindow *window,
4373 XSetWindowAttributes xattributes;
4375 g_return_if_fail (GDK_IS_WINDOW (window));
4377 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4379 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4380 GDK_WINDOW_XID (window),
4381 CWWinGravity, &xattributes);
4385 gdk_window_x11_set_static_gravities (GdkWindow *window,
4386 gboolean use_static)
4390 if (!use_static == !window->guffaw_gravity)
4393 window->guffaw_gravity = use_static;
4395 if (!GDK_WINDOW_DESTROYED (window))
4397 gdk_window_set_static_bit_gravity (window, use_static);
4399 tmp_list = window->children;
4402 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4404 tmp_list = tmp_list->next;
4411 /* From the WM spec */
4412 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4413 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4414 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4415 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4416 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4417 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4418 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4419 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4420 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4421 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4422 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4423 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4426 wmspec_send_message (GdkDisplay *display,
4433 XClientMessageEvent xclient;
4435 memset (&xclient, 0, sizeof (xclient));
4436 xclient.type = ClientMessage;
4437 xclient.window = GDK_WINDOW_XID (window);
4438 xclient.message_type =
4439 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4440 xclient.format = 32;
4441 xclient.data.l[0] = root_x;
4442 xclient.data.l[1] = root_y;
4443 xclient.data.l[2] = action;
4444 xclient.data.l[3] = button;
4445 xclient.data.l[4] = 1; /* source indication */
4447 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4448 SubstructureRedirectMask | SubstructureNotifyMask,
4449 (XEvent *)&xclient);
4453 handle_wmspec_button_release (GdkDisplay *display,
4456 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4459 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4460 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4461 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4463 if (xevent->xany.type == GenericEvent)
4464 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4467 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4469 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4471 if ((xevent->xany.type == ButtonRelease &&
4472 xevent->xbutton.button == display_x11->wm_moveresize_button)
4473 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4475 (xevent->xany.type == GenericEvent &&
4476 xiev->evtype == XI_ButtonRelease &&
4477 xidev->detail == display_x11->wm_moveresize_button)
4481 display_x11->wm_moveresize_button = 0;
4482 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4488 wmspec_moveresize (GdkWindow *window,
4496 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4498 /* Release passive grab */
4499 gdk_device_ungrab (device, timestamp);
4500 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4502 wmspec_send_message (display, window, root_x, root_y, direction, button);
4506 wmspec_resize_drag (GdkWindow *window,
4516 /* Let the compiler turn a switch into a table, instead
4517 * of doing the table manually, this way is easier to verify.
4521 case GDK_WINDOW_EDGE_NORTH_WEST:
4522 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4525 case GDK_WINDOW_EDGE_NORTH:
4526 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4529 case GDK_WINDOW_EDGE_NORTH_EAST:
4530 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4533 case GDK_WINDOW_EDGE_WEST:
4534 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4537 case GDK_WINDOW_EDGE_EAST:
4538 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4541 case GDK_WINDOW_EDGE_SOUTH_WEST:
4542 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4545 case GDK_WINDOW_EDGE_SOUTH:
4546 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4549 case GDK_WINDOW_EDGE_SOUTH_EAST:
4550 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4554 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4559 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4562 typedef struct _MoveResizeData MoveResizeData;
4564 struct _MoveResizeData
4566 GdkDisplay *display;
4568 GdkWindow *moveresize_window;
4569 GdkWindow *moveresize_emulation_window;
4571 GdkWindowEdge resize_edge;
4573 gint moveresize_button;
4576 gint moveresize_orig_x;
4577 gint moveresize_orig_y;
4578 gint moveresize_orig_width;
4579 gint moveresize_orig_height;
4580 GdkWindowHints moveresize_geom_mask;
4581 GdkGeometry moveresize_geometry;
4582 Time moveresize_process_time;
4583 XEvent *moveresize_pending_event;
4586 static MoveResizeData *
4587 get_move_resize_data (GdkDisplay *display,
4590 MoveResizeData *mv_resize;
4591 static GQuark move_resize_quark = 0;
4593 if (!move_resize_quark)
4594 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4596 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4598 if (!mv_resize && create)
4600 mv_resize = g_new0 (MoveResizeData, 1);
4601 mv_resize->display = display;
4603 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4610 update_pos (MoveResizeData *mv_resize,
4616 dx = new_root_x - mv_resize->moveresize_x;
4617 dy = new_root_y - mv_resize->moveresize_y;
4619 if (mv_resize->is_resize)
4623 x = mv_resize->moveresize_orig_x;
4624 y = mv_resize->moveresize_orig_y;
4626 w = mv_resize->moveresize_orig_width;
4627 h = mv_resize->moveresize_orig_height;
4629 switch (mv_resize->resize_edge)
4631 case GDK_WINDOW_EDGE_NORTH_WEST:
4637 case GDK_WINDOW_EDGE_NORTH:
4641 case GDK_WINDOW_EDGE_NORTH_EAST:
4646 case GDK_WINDOW_EDGE_SOUTH_WEST:
4651 case GDK_WINDOW_EDGE_SOUTH_EAST:
4655 case GDK_WINDOW_EDGE_SOUTH:
4658 case GDK_WINDOW_EDGE_EAST:
4661 case GDK_WINDOW_EDGE_WEST:
4672 if (mv_resize->moveresize_geom_mask)
4674 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4675 mv_resize->moveresize_geom_mask,
4679 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4685 x = mv_resize->moveresize_orig_x + dx;
4686 y = mv_resize->moveresize_orig_y + dy;
4688 gdk_window_move (mv_resize->moveresize_window, x, y);
4693 finish_drag (MoveResizeData *mv_resize)
4695 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4696 mv_resize->moveresize_emulation_window = NULL;
4697 g_object_unref (mv_resize->moveresize_window);
4698 mv_resize->moveresize_window = NULL;
4700 if (mv_resize->moveresize_pending_event)
4702 g_free (mv_resize->moveresize_pending_event);
4703 mv_resize->moveresize_pending_event = NULL;
4708 lookahead_motion_predicate (Display *xdisplay,
4712 gboolean *seen_release = (gboolean *)arg;
4713 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4714 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4719 switch (event->xany.type)
4722 *seen_release = TRUE;
4725 mv_resize->moveresize_process_time = event->xmotion.time;
4735 moveresize_lookahead (MoveResizeData *mv_resize,
4739 gboolean seen_release = FALSE;
4741 if (mv_resize->moveresize_process_time)
4743 if (event->xmotion.time == mv_resize->moveresize_process_time)
4745 mv_resize->moveresize_process_time = 0;
4752 XCheckIfEvent (event->xany.display, &tmp_event,
4753 lookahead_motion_predicate, (XPointer) & seen_release);
4755 return mv_resize->moveresize_process_time == 0;
4759 _gdk_x11_moveresize_handle_event (XEvent *event)
4761 guint button_mask = 0;
4762 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4763 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4765 if (!mv_resize || !mv_resize->moveresize_window)
4767 handle_wmspec_button_release (display, event);
4771 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4773 switch (event->xany.type)
4776 if (mv_resize->moveresize_window->resize_count > 0)
4778 if (mv_resize->moveresize_pending_event)
4779 *mv_resize->moveresize_pending_event = *event;
4781 mv_resize->moveresize_pending_event =
4782 g_memdup (event, sizeof (XEvent));
4786 if (!moveresize_lookahead (mv_resize, event))
4789 update_pos (mv_resize,
4790 event->xmotion.x_root,
4791 event->xmotion.y_root);
4793 /* This should never be triggered in normal cases, but in the
4794 * case where the drag started without an implicit grab being
4795 * in effect, we could miss the release if it occurs before
4796 * we grab the pointer; this ensures that we will never
4797 * get a permanently stuck grab.
4799 if ((event->xmotion.state & button_mask) == 0)
4800 finish_drag (mv_resize);
4804 update_pos (mv_resize,
4805 event->xbutton.x_root,
4806 event->xbutton.y_root);
4808 if (event->xbutton.button == mv_resize->moveresize_button)
4809 finish_drag (mv_resize);
4812 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4815 /* we just assume this is an XI2 event */
4816 XIEvent *ev = (XIEvent *) event->xcookie.data;
4817 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4822 update_pos (mv_resize, xev->root_x, xev->root_y);
4823 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4824 if ((state & button_mask) == 0)
4825 finish_drag (mv_resize);
4828 case XI_ButtonRelease:
4829 update_pos (mv_resize, xev->root_x, xev->root_y);
4830 if (xev->detail == mv_resize->moveresize_button)
4831 finish_drag (mv_resize);
4843 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4847 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4849 if (!mv_resize || window != mv_resize->moveresize_window)
4852 if (mv_resize->moveresize_pending_event)
4854 tmp_event = mv_resize->moveresize_pending_event;
4855 mv_resize->moveresize_pending_event = NULL;
4856 _gdk_x11_moveresize_handle_event (tmp_event);
4864 create_moveresize_window (MoveResizeData *mv_resize,
4867 GdkWindowAttr attributes;
4868 gint attributes_mask;
4869 GdkGrabStatus status;
4871 g_assert (mv_resize->moveresize_emulation_window == NULL);
4873 attributes.x = -100;
4874 attributes.y = -100;
4875 attributes.width = 10;
4876 attributes.height = 10;
4877 attributes.window_type = GDK_WINDOW_TEMP;
4878 attributes.wclass = GDK_INPUT_ONLY;
4879 attributes.override_redirect = TRUE;
4880 attributes.event_mask = 0;
4882 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4884 mv_resize->moveresize_emulation_window =
4885 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4889 gdk_window_show (mv_resize->moveresize_emulation_window);
4891 status = gdk_device_grab (mv_resize->device,
4892 mv_resize->moveresize_emulation_window,
4895 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4899 if (status != GDK_GRAB_SUCCESS)
4901 /* If this fails, some other client has grabbed the window
4904 finish_drag (mv_resize);
4907 mv_resize->moveresize_process_time = 0;
4911 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4912 so that calling XMoveWindow with these coordinates will not move the
4914 Note that this depends on the WM to implement ICCCM-compliant reference
4918 calculate_unmoving_origin (MoveResizeData *mv_resize)
4923 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4924 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4926 gdk_window_get_origin (mv_resize->moveresize_window,
4927 &mv_resize->moveresize_orig_x,
4928 &mv_resize->moveresize_orig_y);
4932 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4933 gdk_window_get_geometry (mv_resize->moveresize_window,
4934 NULL, NULL, &width, &height);
4936 switch (mv_resize->moveresize_geometry.win_gravity)
4938 case GDK_GRAVITY_NORTH_WEST:
4939 mv_resize->moveresize_orig_x = rect.x;
4940 mv_resize->moveresize_orig_y = rect.y;
4942 case GDK_GRAVITY_NORTH:
4943 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4944 mv_resize->moveresize_orig_y = rect.y;
4946 case GDK_GRAVITY_NORTH_EAST:
4947 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4948 mv_resize->moveresize_orig_y = rect.y;
4950 case GDK_GRAVITY_WEST:
4951 mv_resize->moveresize_orig_x = rect.x;
4952 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4954 case GDK_GRAVITY_CENTER:
4955 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4956 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4958 case GDK_GRAVITY_EAST:
4959 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4960 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4962 case GDK_GRAVITY_SOUTH_WEST:
4963 mv_resize->moveresize_orig_x = rect.x;
4964 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4966 case GDK_GRAVITY_SOUTH:
4967 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4968 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4970 case GDK_GRAVITY_SOUTH_EAST:
4971 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4972 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4975 mv_resize->moveresize_orig_x = rect.x;
4976 mv_resize->moveresize_orig_y = rect.y;
4983 emulate_resize_drag (GdkWindow *window,
4991 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4993 mv_resize->is_resize = TRUE;
4994 mv_resize->moveresize_button = button;
4995 mv_resize->resize_edge = edge;
4996 mv_resize->device = device;
4997 mv_resize->moveresize_x = root_x;
4998 mv_resize->moveresize_y = root_y;
4999 mv_resize->moveresize_window = g_object_ref (window);
5001 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
5002 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
5004 mv_resize->moveresize_geom_mask = 0;
5005 gdk_window_get_geometry_hints (window,
5006 &mv_resize->moveresize_geometry,
5007 &mv_resize->moveresize_geom_mask);
5009 calculate_unmoving_origin (mv_resize);
5011 create_moveresize_window (mv_resize, timestamp);
5015 emulate_move_drag (GdkWindow *window,
5022 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5024 mv_resize->is_resize = FALSE;
5025 mv_resize->device = device;
5026 mv_resize->moveresize_button = button;
5027 mv_resize->moveresize_x = root_x;
5028 mv_resize->moveresize_y = root_y;
5030 mv_resize->moveresize_window = g_object_ref (window);
5032 calculate_unmoving_origin (mv_resize);
5034 create_moveresize_window (mv_resize, timestamp);
5038 gdk_x11_window_begin_resize_drag (GdkWindow *window,
5046 if (GDK_WINDOW_DESTROYED (window) ||
5047 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5050 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5051 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5052 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5054 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5058 gdk_x11_window_begin_move_drag (GdkWindow *window,
5065 if (GDK_WINDOW_DESTROYED (window) ||
5066 !WINDOW_IS_TOPLEVEL (window))
5069 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5070 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5071 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5072 device, button, root_x, root_y, timestamp);
5074 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5078 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
5080 GdkWindowImplX11 *impl;
5082 if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
5085 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5087 if (!impl->use_synchronized_configure)
5089 /* This basically means you want to do fancy X specific stuff, so
5090 ensure we have a native window */
5091 gdk_window_ensure_native (window);
5093 impl->use_synchronized_configure = TRUE;
5094 ensure_sync_counter (window);
5099 gdk_x11_window_configure_finished (GdkWindow *window)
5101 GdkWindowImplX11 *impl;
5103 if (!WINDOW_IS_TOPLEVEL (window))
5106 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5107 if (!impl->use_synchronized_configure)
5111 if (!GDK_WINDOW_DESTROYED (window))
5113 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5114 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5116 if (toplevel && toplevel->update_counter != None &&
5117 GDK_X11_DISPLAY (display)->use_sync &&
5118 toplevel->configure_counter_value != 0)
5120 if (toplevel->configure_counter_value_is_extended)
5122 toplevel->current_counter_value = toplevel->configure_counter_value;
5123 if ((toplevel->current_counter_value % 2) == 1)
5124 toplevel->current_counter_value += 1;
5126 toplevel->configure_counter_value = 0;
5128 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5129 toplevel->extended_update_counter,
5130 toplevel->current_counter_value);
5134 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5135 toplevel->update_counter,
5136 toplevel->configure_counter_value);
5144 gdk_x11_window_beep (GdkWindow *window)
5146 GdkDisplay *display;
5148 display = GDK_WINDOW_DISPLAY (window);
5151 if (GDK_X11_DISPLAY (display)->use_xkb)
5153 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5154 GDK_WINDOW_XID (window),
5165 gdk_x11_window_set_opacity (GdkWindow *window,
5168 GdkDisplay *display;
5171 g_return_if_fail (GDK_IS_WINDOW (window));
5173 if (GDK_WINDOW_DESTROYED (window) ||
5174 !WINDOW_IS_TOPLEVEL (window))
5177 display = gdk_window_get_display (window);
5181 else if (opacity > 1)
5184 cardinal = opacity * 0xffffffff;
5186 if (cardinal == 0xffffffff)
5187 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5188 GDK_WINDOW_XID (window),
5189 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5191 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5192 GDK_WINDOW_XID (window),
5193 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5196 (guchar *) &cardinal, 1);
5200 gdk_x11_window_set_composited (GdkWindow *window,
5201 gboolean composited)
5203 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5204 GdkWindowImplX11 *impl;
5205 GdkDisplay *display;
5209 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5211 display = gdk_window_get_display (window);
5212 dpy = GDK_DISPLAY_XDISPLAY (display);
5213 xid = GDK_WINDOW_XID (window);
5217 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5218 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5222 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5223 XDamageDestroy (dpy, impl->damage);
5224 impl->damage = None;
5230 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5231 cairo_region_t *region)
5233 _gdk_window_process_updates_recurse (window, region);
5237 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5242 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5244 /* Sync after all drawing, otherwise the client can get "ahead" of
5245 the server rendering during animations, such that we fill up
5246 the Xserver pipes with sync rendering ops not letting other
5247 clients (including the VM) do anything. */
5248 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5252 timestamp_predicate (Display *display,
5256 Window xwindow = GPOINTER_TO_UINT (arg);
5257 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5259 if (xevent->type == PropertyNotify &&
5260 xevent->xproperty.window == xwindow &&
5261 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5262 "GDK_TIMESTAMP_PROP"))
5269 * gdk_x11_get_server_time:
5270 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5271 * with the server. The window must have
5272 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5275 * Routine to get the current X server time stamp.
5277 * Return value: the time stamp.
5280 gdk_x11_get_server_time (GdkWindow *window)
5286 Atom timestamp_prop_atom;
5288 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5289 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5291 xdisplay = GDK_WINDOW_XDISPLAY (window);
5292 xwindow = GDK_WINDOW_XID (window);
5293 timestamp_prop_atom =
5294 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5295 "GDK_TIMESTAMP_PROP");
5297 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5298 timestamp_prop_atom,
5299 8, PropModeReplace, &c, 1);
5301 XIfEvent (xdisplay, &xevent,
5302 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5304 return xevent.xproperty.time;
5308 * gdk_x11_window_get_xid:
5309 * @window: (type GdkX11Window): a native #GdkWindow.
5311 * Returns the X resource (window) belonging to a #GdkWindow.
5313 * Return value: the ID of @drawable's X resource.
5316 gdk_x11_window_get_xid (GdkWindow *window)
5318 /* Try to ensure the window has a native window */
5319 if (!_gdk_window_has_impl (window))
5321 gdk_window_ensure_native (window);
5323 /* We sync here to ensure the window is created in the Xserver when
5324 * this function returns. This is required because the returned XID
5325 * for this window must be valid immediately, even with another
5326 * connection to the Xserver */
5327 gdk_display_sync (gdk_window_get_display (window));
5330 if (!GDK_WINDOW_IS_X11 (window))
5332 g_warning (G_STRLOC " drawable is not a native X11 window");
5336 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5340 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5342 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5343 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5345 object_class->finalize = gdk_window_impl_x11_finalize;
5347 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5348 impl_class->show = gdk_window_x11_show;
5349 impl_class->hide = gdk_window_x11_hide;
5350 impl_class->withdraw = gdk_window_x11_withdraw;
5351 impl_class->set_events = gdk_window_x11_set_events;
5352 impl_class->get_events = gdk_window_x11_get_events;
5353 impl_class->raise = gdk_window_x11_raise;
5354 impl_class->lower = gdk_window_x11_lower;
5355 impl_class->restack_under = gdk_window_x11_restack_under;
5356 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5357 impl_class->move_resize = gdk_window_x11_move_resize;
5358 impl_class->set_background = gdk_window_x11_set_background;
5359 impl_class->reparent = gdk_window_x11_reparent;
5360 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5361 impl_class->get_geometry = gdk_window_x11_get_geometry;
5362 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5363 impl_class->get_device_state = gdk_window_x11_get_device_state;
5364 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5365 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5366 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5367 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5368 impl_class->translate = _gdk_x11_window_translate;
5369 impl_class->destroy = gdk_x11_window_destroy;
5370 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5371 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5372 impl_class->get_shape = gdk_x11_window_get_shape;
5373 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5374 impl_class->beep = gdk_x11_window_beep;
5376 impl_class->focus = gdk_x11_window_focus;
5377 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5378 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5379 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5380 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5381 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5382 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5383 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5384 impl_class->set_title = gdk_x11_window_set_title;
5385 impl_class->set_role = gdk_x11_window_set_role;
5386 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5387 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5388 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5389 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5390 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5391 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5392 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5393 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5394 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5395 impl_class->iconify = gdk_x11_window_iconify;
5396 impl_class->deiconify = gdk_x11_window_deiconify;
5397 impl_class->stick = gdk_x11_window_stick;
5398 impl_class->unstick = gdk_x11_window_unstick;
5399 impl_class->maximize = gdk_x11_window_maximize;
5400 impl_class->unmaximize = gdk_x11_window_unmaximize;
5401 impl_class->fullscreen = gdk_x11_window_fullscreen;
5402 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5403 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5404 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5405 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5406 impl_class->get_group = gdk_x11_window_get_group;
5407 impl_class->set_group = gdk_x11_window_set_group;
5408 impl_class->set_decorations = gdk_x11_window_set_decorations;
5409 impl_class->get_decorations = gdk_x11_window_get_decorations;
5410 impl_class->set_functions = gdk_x11_window_set_functions;
5411 impl_class->set_functions = gdk_x11_window_set_functions;
5412 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5413 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5414 impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
5415 impl_class->configure_finished = gdk_x11_window_configure_finished;
5416 impl_class->set_opacity = gdk_x11_window_set_opacity;
5417 impl_class->set_composited = gdk_x11_window_set_composited;
5418 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5419 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5420 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5421 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5422 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5423 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5424 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5425 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5426 impl_class->get_property = _gdk_x11_window_get_property;
5427 impl_class->change_property = _gdk_x11_window_change_property;
5428 impl_class->delete_property = _gdk_x11_window_delete_property;