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"
35 #include "gdkframeclockprivate.h"
37 #include "gdkeventsource.h"
38 #include "gdkdisplay-x11.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;
286 gint64 presentation_time;
287 gint64 refresh_interval;
289 if (!WINDOW_IS_TOPLEVEL (window))
292 clock = gdk_window_get_frame_clock (window);
294 timings = gdk_frame_clock_get_current_timings (clock);
296 gdk_frame_clock_get_refresh_info (clock,
298 &refresh_interval, &presentation_time);
300 if (presentation_time != 0)
302 if (timings->slept_before)
304 presentation_time += refresh_interval;
308 if (presentation_time < timings->frame_time + refresh_interval / 2)
309 presentation_time += refresh_interval;
314 if (timings->slept_before)
315 presentation_time = timings->frame_time + refresh_interval + refresh_interval / 2;
317 presentation_time = timings->frame_time + refresh_interval;
320 if (presentation_time < impl->toplevel->throttled_presentation_time)
321 presentation_time = impl->toplevel->throttled_presentation_time;
323 timings->predicted_presentation_time = presentation_time;
327 gdk_x11_window_begin_frame (GdkWindow *window)
329 GdkWindowImplX11 *impl;
331 g_return_if_fail (GDK_IS_WINDOW (window));
333 impl = GDK_WINDOW_IMPL_X11 (window->impl);
335 if (!WINDOW_IS_TOPLEVEL (window) ||
336 impl->toplevel->extended_update_counter == None)
339 impl->toplevel->in_frame = TRUE;
341 if (impl->toplevel->configure_counter_value != 0 &&
342 impl->toplevel->configure_counter_value_is_extended)
344 impl->toplevel->current_counter_value = impl->toplevel->configure_counter_value;
345 if ((impl->toplevel->current_counter_value % 2) == 1)
346 impl->toplevel->current_counter_value += 1;
348 impl->toplevel->configure_counter_value = 0;
350 window_pre_damage (window);
354 hook_surface_changed (window);
359 gdk_x11_window_end_frame (GdkWindow *window)
361 GdkFrameClock *clock;
362 GdkFrameTimings *timings;
363 GdkWindowImplX11 *impl;
365 g_return_if_fail (GDK_IS_WINDOW (window));
367 impl = GDK_WINDOW_IMPL_X11 (window->impl);
369 if (!WINDOW_IS_TOPLEVEL (window) ||
370 impl->toplevel->extended_update_counter == None ||
371 !impl->toplevel->in_frame)
374 clock = gdk_window_get_frame_clock (window);
375 timings = gdk_frame_clock_get_current_timings (clock);
377 impl->toplevel->in_frame = FALSE;
379 if (impl->toplevel->current_counter_value % 2 == 1)
381 #ifdef G_ENABLE_DEBUG
382 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
384 XImage *image = XGetImage (GDK_WINDOW_XDISPLAY (window),
385 GDK_WINDOW_XID (window),
389 XDestroyImage (image);
391 #endif /* G_ENABLE_DEBUG */
393 /* An increment of 3 means that the frame was not drawn as fast as possible,
394 * but rather at a particular time. This can trigger different handling from
397 if (timings->slept_before)
398 impl->toplevel->current_counter_value += 3;
400 impl->toplevel->current_counter_value += 1;
402 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
403 impl->toplevel->extended_update_counter,
404 impl->toplevel->current_counter_value);
406 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
407 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
409 impl->toplevel->frame_pending = TRUE;
410 _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
411 timings->cookie = impl->toplevel->current_counter_value;
415 unhook_surface_changed (window);
417 if (impl->toplevel->configure_counter_value != 0 &&
418 !impl->toplevel->configure_counter_value_is_extended)
420 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
421 impl->toplevel->update_counter,
422 impl->toplevel->configure_counter_value);
424 impl->toplevel->configure_counter_value = 0;
427 if (!impl->toplevel->frame_pending)
428 timings->complete = TRUE;
431 /*****************************************************
432 * X11 specific implementations of generic functions *
433 *****************************************************/
436 gdk_x11_cairo_surface_destroy (void *data)
438 GdkWindowImplX11 *impl = data;
440 impl->cairo_surface = NULL;
443 static cairo_surface_t *
444 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
450 visual = gdk_window_get_visual (impl->wrapper);
451 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
452 GDK_WINDOW_IMPL_X11 (impl)->xid,
453 GDK_VISUAL_XVISUAL (visual),
457 static cairo_surface_t *
458 gdk_x11_ref_cairo_surface (GdkWindow *window)
460 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
462 if (GDK_WINDOW_DESTROYED (window))
465 if (!impl->cairo_surface)
467 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
468 gdk_window_get_width (window),
469 gdk_window_get_height (window));
471 if (impl->cairo_surface)
472 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
473 impl, gdk_x11_cairo_surface_destroy);
475 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
476 hook_surface_changed (window);
479 cairo_surface_reference (impl->cairo_surface);
481 return impl->cairo_surface;
485 gdk_window_impl_x11_finalize (GObject *object)
488 GdkWindowImplX11 *impl;
490 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
492 impl = GDK_WINDOW_IMPL_X11 (object);
494 wrapper = impl->wrapper;
496 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
497 unhook_surface_changed (wrapper);
499 _gdk_x11_window_grab_check_destroy (wrapper);
501 if (!GDK_WINDOW_DESTROYED (wrapper))
503 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
505 _gdk_x11_display_remove_window (display, impl->xid);
506 if (impl->toplevel && impl->toplevel->focus_window)
507 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
510 g_free (impl->toplevel);
513 g_object_unref (impl->cursor);
515 g_hash_table_destroy (impl->device_cursor);
517 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
526 free_pixmap (gpointer datap)
528 FreePixmapData *data = datap;
530 if (!gdk_display_is_closed (data->display))
532 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
536 g_object_unref (data->display);
537 g_slice_free (FreePixmapData, data);
541 attach_free_pixmap_handler (cairo_surface_t *surface,
545 static const cairo_user_data_key_t key;
546 FreePixmapData *data;
548 data = g_slice_new (FreePixmapData);
549 data->display = g_object_ref (display);
550 data->pixmap = pixmap;
552 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
555 /* Cairo does not guarantee we get an xlib surface if we call
556 * cairo_surface_create_similar(). In some cases however, we must use a
557 * pixmap or bitmap in the X11 API.
558 * These functions ensure an Xlib surface.
561 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
565 cairo_surface_t *surface;
568 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
569 GDK_WINDOW_XID (window),
571 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
573 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
575 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
580 /* Create a surface backed with a pixmap without alpha on the same screen as window */
581 static cairo_surface_t *
582 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
586 GdkScreen *screen = gdk_window_get_screen (window);
587 GdkVisual *visual = gdk_screen_get_system_visual (screen);
588 cairo_surface_t *surface;
591 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
592 GDK_WINDOW_XID (window),
594 gdk_visual_get_depth (visual));
595 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
597 GDK_VISUAL_XVISUAL (visual),
599 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
605 tmp_unset_bg (GdkWindow *window)
607 GdkWindowImplX11 *impl;
609 impl = GDK_WINDOW_IMPL_X11 (window->impl);
613 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
614 GDK_WINDOW_XID (window), None);
618 tmp_reset_bg (GdkWindow *window)
620 GdkWindowImplX11 *impl;
622 impl = GDK_WINDOW_IMPL_X11 (window->impl);
626 gdk_window_x11_set_background (window, window->background);
629 /* Unsetting and resetting window backgrounds.
631 * In many cases it is possible to avoid flicker by unsetting the
632 * background of windows. For example if the background of the
633 * parent window is unset when a window is unmapped, a brief flicker
634 * of background painting is avoided.
637 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
640 g_return_if_fail (GDK_IS_WINDOW (window));
642 if (window->input_only || window->destroyed ||
643 (window->window_type != GDK_WINDOW_ROOT &&
644 !GDK_WINDOW_IS_MAPPED (window)))
647 if (_gdk_window_has_impl (window) &&
648 GDK_WINDOW_IS_X11 (window) &&
649 window->window_type != GDK_WINDOW_ROOT &&
650 window->window_type != GDK_WINDOW_FOREIGN)
651 tmp_unset_bg (window);
657 for (l = window->children; l != NULL; l = l->next)
658 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
663 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
665 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
668 window = _gdk_window_get_impl_window (window->parent);
669 _gdk_x11_window_tmp_unset_bg (window, FALSE);
673 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
676 g_return_if_fail (GDK_IS_WINDOW (window));
678 if (window->input_only || window->destroyed ||
679 (window->window_type != GDK_WINDOW_ROOT &&
680 !GDK_WINDOW_IS_MAPPED (window)))
684 if (_gdk_window_has_impl (window) &&
685 GDK_WINDOW_IS_X11 (window) &&
686 window->window_type != GDK_WINDOW_ROOT &&
687 window->window_type != GDK_WINDOW_FOREIGN)
688 tmp_reset_bg (window);
694 for (l = window->children; l != NULL; l = l->next)
695 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
700 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
702 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
705 window = _gdk_window_get_impl_window (window->parent);
707 _gdk_x11_window_tmp_reset_bg (window, FALSE);
711 _gdk_x11_screen_init_root_window (GdkScreen *screen)
714 GdkWindowImplX11 *impl;
715 GdkX11Screen *x11_screen;
717 x11_screen = GDK_X11_SCREEN (screen);
719 g_assert (x11_screen->root_window == NULL);
721 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
723 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
724 window->impl_window = window;
725 window->visual = gdk_screen_get_system_visual (screen);
727 impl = GDK_WINDOW_IMPL_X11 (window->impl);
729 impl->xid = x11_screen->xroot_window;
730 impl->wrapper = window;
732 window->window_type = GDK_WINDOW_ROOT;
733 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
739 window->width = WidthOfScreen (x11_screen->xscreen);
740 window->height = HeightOfScreen (x11_screen->xscreen);
741 window->viewable = TRUE;
743 /* see init_randr_support() in gdkscreen-x11.c */
744 window->event_mask = GDK_STRUCTURE_MASK;
746 _gdk_window_update_size (x11_screen->root_window);
748 _gdk_x11_display_add_window (x11_screen->display,
749 &x11_screen->xroot_window,
750 x11_screen->root_window);
754 set_wm_protocols (GdkWindow *window)
756 GdkDisplay *display = gdk_window_get_display (window);
760 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
761 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
762 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
765 if (GDK_X11_DISPLAY (display)->use_sync)
766 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
769 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
773 get_default_title (void)
777 title = g_get_application_name ();
779 title = g_get_prgname ();
787 check_leader_window_title (GdkDisplay *display)
789 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
791 if (display_x11->leader_window && !display_x11->leader_window_title_set)
793 set_wm_name (display,
794 display_x11->leader_window,
795 get_default_title ());
797 display_x11->leader_window_title_set = TRUE;
802 create_focus_window (GdkDisplay *display,
805 GdkX11Display *display_x11;
806 GdkEventMask event_mask;
810 xdisplay = GDK_DISPLAY_XDISPLAY (display);
811 display_x11 = GDK_X11_DISPLAY (display);
813 focus_window = XCreateSimpleWindow (xdisplay, parent,
817 /* FIXME: probably better to actually track the requested event mask for the toplevel
819 event_mask = (GDK_KEY_PRESS_MASK |
820 GDK_KEY_RELEASE_MASK |
821 GDK_FOCUS_CHANGE_MASK);
823 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
827 XMapWindow (xdisplay, focus_window);
833 ensure_sync_counter (GdkWindow *window)
836 if (!GDK_WINDOW_DESTROYED (window))
838 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
839 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
842 toplevel->update_counter == None &&
843 GDK_X11_DISPLAY (display)->use_sync)
845 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
850 XSyncIntToValue (&value, 0);
852 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
853 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
855 atom = gdk_x11_get_xatom_by_name_for_display (display,
856 "_NET_WM_SYNC_REQUEST_COUNTER");
858 counters[0] = toplevel->update_counter;
859 counters[1] = toplevel->extended_update_counter;
860 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
863 (guchar *)counters, 2);
865 toplevel->current_counter_value = 0;
872 setup_toplevel_window (GdkWindow *window,
875 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
876 GdkDisplay *display = gdk_window_get_display (window);
877 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
878 XID xid = GDK_WINDOW_XID (window);
879 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
880 XSizeHints size_hints;
882 Window leader_window;
884 set_wm_protocols (window);
886 if (!window->input_only)
888 /* The focus window is off the visible area, and serves to receive key
889 * press events so they don't get sent to child windows.
891 toplevel->focus_window = create_focus_window (display, xid);
892 _gdk_x11_display_add_window (x11_screen->display,
893 &toplevel->focus_window,
897 check_leader_window_title (x11_screen->display);
899 /* FIXME: Is there any point in doing this? Do any WM's pay
900 * attention to PSize, and even if they do, is this the
903 size_hints.flags = PSize;
904 size_hints.width = window->width;
905 size_hints.height = window->height;
907 XSetWMNormalHints (xdisplay, xid, &size_hints);
909 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
910 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
913 XChangeProperty (xdisplay, xid,
914 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
919 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
922 XChangeProperty (xdisplay, xid,
923 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
924 XA_WINDOW, 32, PropModeReplace,
925 (guchar *) &leader_window, 1);
927 if (toplevel->focus_window != None)
928 XChangeProperty (xdisplay, xid,
929 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
930 XA_WINDOW, 32, PropModeReplace,
931 (guchar *) &toplevel->focus_window, 1);
933 if (!window->focus_on_map)
934 gdk_x11_window_set_user_time (window, 0);
935 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
936 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
938 ensure_sync_counter (window);
940 /* Start off in a frozen state - we'll finish this when we first paint */
941 gdk_x11_window_begin_frame (window);
945 on_frame_clock_before_paint (GdkFrameClock *clock,
948 gdk_x11_window_predict_presentation_time (window);
949 gdk_x11_window_begin_frame (window);
953 on_frame_clock_after_paint (GdkFrameClock *clock,
956 gdk_x11_window_end_frame (window);
961 connect_frame_clock (GdkWindow *window)
963 GdkWindowImplX11 *impl;
965 impl = GDK_WINDOW_IMPL_X11 (window->impl);
966 if (WINDOW_IS_TOPLEVEL (window) && !impl->frame_clock_connected)
968 GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window);
970 g_signal_connect (frame_clock, "before-paint",
971 G_CALLBACK (on_frame_clock_before_paint), window);
972 g_signal_connect (frame_clock, "after-paint",
973 G_CALLBACK (on_frame_clock_after_paint), window);
975 impl->frame_clock_connected = TRUE;
980 _gdk_x11_display_create_window_impl (GdkDisplay *display,
982 GdkWindow *real_parent,
984 GdkEventMask event_mask,
985 GdkWindowAttr *attributes,
986 gint attributes_mask)
988 GdkWindowImplX11 *impl;
989 GdkX11Screen *x11_screen;
990 GdkX11Display *display_x11;
996 XSetWindowAttributes xattributes;
997 long xattributes_mask;
998 XClassHint *class_hint;
1003 display_x11 = GDK_X11_DISPLAY (display);
1004 xparent = GDK_WINDOW_XID (real_parent);
1005 x11_screen = GDK_X11_SCREEN (screen);
1007 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1008 window->impl = GDK_WINDOW_IMPL (impl);
1009 impl->wrapper = GDK_WINDOW (window);
1011 xdisplay = x11_screen->xdisplay;
1013 xattributes_mask = 0;
1015 xvisual = gdk_x11_visual_get_xvisual (window->visual);
1017 if (attributes_mask & GDK_WA_NOREDIR)
1019 xattributes.override_redirect =
1020 (attributes->override_redirect == FALSE)?False:True;
1021 xattributes_mask |= CWOverrideRedirect;
1024 xattributes.override_redirect = False;
1026 impl->override_redirect = xattributes.override_redirect;
1028 if (window->parent && window->parent->guffaw_gravity)
1030 xattributes.win_gravity = StaticGravity;
1031 xattributes_mask |= CWWinGravity;
1035 switch (window->window_type)
1037 case GDK_WINDOW_TOPLEVEL:
1038 case GDK_WINDOW_TEMP:
1039 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
1041 /* The common code warns for this case */
1042 xparent = GDK_SCREEN_XROOTWIN (screen);
1046 if (!window->input_only)
1048 class = InputOutput;
1050 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1052 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1053 xattributes_mask |= CWBorderPixel | CWBackPixel;
1055 if (window->guffaw_gravity)
1056 xattributes.bit_gravity = StaticGravity;
1058 xattributes.bit_gravity = NorthWestGravity;
1060 xattributes_mask |= CWBitGravity;
1062 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
1063 xattributes_mask |= CWColormap;
1065 if (window->window_type == GDK_WINDOW_TEMP)
1067 xattributes.save_under = True;
1068 xattributes.override_redirect = True;
1069 xattributes.cursor = None;
1070 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
1072 impl->override_redirect = TRUE;
1080 if (window->width > 65535 ||
1081 window->height > 65535)
1083 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
1085 if (window->width > 65535)
1086 window->width = 65535;
1087 if (window->height > 65535)
1088 window->height = 65535;
1091 impl->xid = XCreateWindow (xdisplay, xparent,
1092 window->x + window->parent->abs_x,
1093 window->y + window->parent->abs_y,
1094 window->width, window->height,
1095 0, window->depth, class, xvisual,
1096 xattributes_mask, &xattributes);
1098 g_object_ref (window);
1099 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1101 switch (GDK_WINDOW_TYPE (window))
1103 case GDK_WINDOW_TOPLEVEL:
1104 case GDK_WINDOW_TEMP:
1105 if (attributes_mask & GDK_WA_TITLE)
1106 title = attributes->title;
1108 title = get_default_title ();
1110 gdk_window_set_title (window, title);
1112 if (attributes_mask & GDK_WA_WMCLASS)
1114 class_hint = XAllocClassHint ();
1115 class_hint->res_name = attributes->wmclass_name;
1116 class_hint->res_class = attributes->wmclass_class;
1117 XSetClassHint (xdisplay, impl->xid, class_hint);
1121 setup_toplevel_window (window, window->parent);
1124 case GDK_WINDOW_CHILD:
1129 if (attributes_mask & GDK_WA_TYPE_HINT)
1130 gdk_window_set_type_hint (window, attributes->type_hint);
1132 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1133 GDK_WINDOW_XID (window), event_mask,
1134 StructureNotifyMask | PropertyChangeMask);
1136 connect_frame_clock (window);
1138 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1139 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1143 x_event_mask_to_gdk_event_mask (long mask)
1145 GdkEventMask event_mask = 0;
1148 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1150 if (mask & _gdk_x11_event_mask_table[i])
1151 event_mask |= 1 << (i + 1);
1158 * gdk_x11_window_foreign_new_for_display:
1159 * @display: the #GdkDisplay where the window handle comes from.
1160 * @window: an XLib <type>Window</type>
1162 * Wraps a native window in a #GdkWindow. The function will try to
1163 * look up the window using gdk_x11_window_lookup_for_display() first.
1164 * If it does not find it there, it will create a new window.
1166 * This may fail if the window has been destroyed. If the window
1167 * was already known to GDK, a new reference to the existing
1168 * #GdkWindow is returned.
1170 * Return value: (transfer full): a #GdkWindow wrapper for the native
1171 * window, or %NULL if the window has been destroyed. The wrapper
1172 * will be newly created, if one doesn't exist already.
1177 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1182 GdkWindowImplX11 *impl;
1183 GdkX11Display *display_x11;
1184 XWindowAttributes attrs;
1185 Window root, parent;
1186 Window *children = NULL;
1190 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1192 display_x11 = GDK_X11_DISPLAY (display);
1194 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1195 return g_object_ref (win);
1197 gdk_x11_display_error_trap_push (display);
1198 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1199 if (gdk_x11_display_error_trap_pop (display) || !result)
1202 /* FIXME: This is pretty expensive.
1203 * Maybe the caller should supply the parent
1205 gdk_x11_display_error_trap_push (display);
1206 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1207 if (gdk_x11_display_error_trap_pop (display) || !result)
1213 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1215 win = _gdk_display_create_window (display);
1216 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1217 win->impl_window = win;
1218 win->visual = gdk_x11_screen_lookup_visual (screen,
1219 XVisualIDFromVisual (attrs.visual));
1221 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1222 impl->wrapper = win;
1224 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1226 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1227 win->parent = gdk_screen_get_root_window (screen);
1229 win->parent->children = g_list_prepend (win->parent->children, win);
1235 win->width = attrs.width;
1236 win->height = attrs.height;
1237 win->window_type = GDK_WINDOW_FOREIGN;
1238 win->destroyed = FALSE;
1240 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1242 if (attrs.map_state == IsUnmapped)
1243 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1246 win->viewable = TRUE;
1248 win->depth = attrs.depth;
1251 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1253 /* Update the clip region, etc */
1254 _gdk_window_update_size (win);
1260 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1261 GdkToplevelX11 *toplevel)
1263 if (toplevel->icon_pixmap)
1265 cairo_surface_destroy (toplevel->icon_pixmap);
1266 toplevel->icon_pixmap = NULL;
1268 if (toplevel->icon_mask)
1270 cairo_surface_destroy (toplevel->icon_mask);
1271 toplevel->icon_mask = NULL;
1273 if (toplevel->group_leader)
1275 g_object_unref (toplevel->group_leader);
1276 toplevel->group_leader = NULL;
1279 if (toplevel->update_counter != None)
1281 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1282 toplevel->update_counter);
1283 toplevel->update_counter = None;
1285 toplevel->current_counter_value = 0;
1291 gdk_x11_window_destroy (GdkWindow *window,
1293 gboolean foreign_destroy)
1295 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1296 GdkToplevelX11 *toplevel;
1298 g_return_if_fail (GDK_IS_WINDOW (window));
1300 _gdk_x11_selection_window_destroyed (window);
1302 toplevel = _gdk_x11_window_get_toplevel (window);
1304 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1306 if (impl->cairo_surface)
1308 cairo_surface_finish (impl->cairo_surface);
1309 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1313 if (!recursing && !foreign_destroy)
1314 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1317 static cairo_surface_t *
1318 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1319 cairo_surface_t *surface,
1323 cairo_xlib_surface_set_size (surface, width, height);
1329 gdk_x11_window_destroy_foreign (GdkWindow *window)
1331 /* It's somebody else's window, but in our hierarchy,
1332 * so reparent it to the root window, and then send
1333 * it a delete event, as if we were a WM
1335 XClientMessageEvent xclient;
1336 GdkDisplay *display;
1338 display = GDK_WINDOW_DISPLAY (window);
1339 gdk_x11_display_error_trap_push (display);
1340 gdk_window_hide (window);
1341 gdk_window_reparent (window, NULL, 0, 0);
1343 memset (&xclient, 0, sizeof (xclient));
1344 xclient.type = ClientMessage;
1345 xclient.window = GDK_WINDOW_XID (window);
1346 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1347 xclient.format = 32;
1348 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1349 xclient.data.l[1] = CurrentTime;
1350 xclient.data.l[2] = 0;
1351 xclient.data.l[3] = 0;
1352 xclient.data.l[4] = 0;
1354 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1355 GDK_WINDOW_XID (window),
1356 False, 0, (XEvent *)&xclient);
1357 gdk_x11_display_error_trap_pop_ignored (display);
1361 get_root (GdkWindow *window)
1363 GdkScreen *screen = gdk_window_get_screen (window);
1365 return gdk_screen_get_root_window (screen);
1368 /* This function is called when the XWindow is really gone.
1371 gdk_x11_window_destroy_notify (GdkWindow *window)
1373 GdkWindowImplX11 *window_impl;
1375 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1377 if (!GDK_WINDOW_DESTROYED (window))
1379 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1380 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1382 _gdk_window_destroy (window, TRUE);
1385 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1386 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1387 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1389 _gdk_x11_window_grab_check_destroy (window);
1391 g_object_unref (window);
1394 static GdkDragProtocol
1395 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1398 GdkDragProtocol protocol;
1399 GdkDisplay *display;
1403 display = gdk_window_get_display (window);
1404 xid = _gdk_x11_display_get_drag_protocol (display,
1405 GDK_WINDOW_XID (window->impl_window),
1412 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1421 update_wm_hints (GdkWindow *window,
1424 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1425 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1429 !toplevel->is_leader &&
1430 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1433 wm_hints.flags = StateHint | InputHint;
1434 wm_hints.input = window->accept_focus ? True : False;
1435 wm_hints.initial_state = NormalState;
1437 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1439 wm_hints.flags |= StateHint;
1440 wm_hints.initial_state = IconicState;
1443 if (toplevel->icon_pixmap)
1445 wm_hints.flags |= IconPixmapHint;
1446 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1449 if (toplevel->icon_mask)
1451 wm_hints.flags |= IconMaskHint;
1452 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1455 wm_hints.flags |= WindowGroupHint;
1456 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1458 wm_hints.flags |= WindowGroupHint;
1459 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1462 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1464 if (toplevel->urgency_hint)
1465 wm_hints.flags |= XUrgencyHint;
1467 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1468 GDK_WINDOW_XID (window),
1473 set_initial_hints (GdkWindow *window)
1475 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1476 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1477 Window xwindow = GDK_WINDOW_XID (window);
1478 GdkToplevelX11 *toplevel;
1482 toplevel = _gdk_x11_window_get_toplevel (window);
1487 update_wm_hints (window, TRUE);
1489 /* We set the spec hints regardless of whether the spec is supported,
1490 * since it can't hurt and it's kind of expensive to check whether
1496 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1498 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1499 "_NET_WM_STATE_MAXIMIZED_VERT");
1501 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1502 "_NET_WM_STATE_MAXIMIZED_HORZ");
1504 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1507 if (window->state & GDK_WINDOW_STATE_ABOVE)
1509 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1510 "_NET_WM_STATE_ABOVE");
1514 if (window->state & GDK_WINDOW_STATE_BELOW)
1516 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1517 "_NET_WM_STATE_BELOW");
1521 if (window->state & GDK_WINDOW_STATE_STICKY)
1523 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1524 "_NET_WM_STATE_STICKY");
1526 toplevel->have_sticky = TRUE;
1529 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1531 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1532 "_NET_WM_STATE_FULLSCREEN");
1534 toplevel->have_fullscreen = TRUE;
1537 if (window->modal_hint)
1539 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1540 "_NET_WM_STATE_MODAL");
1544 if (toplevel->skip_taskbar_hint)
1546 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1547 "_NET_WM_STATE_SKIP_TASKBAR");
1551 if (toplevel->skip_pager_hint)
1553 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1554 "_NET_WM_STATE_SKIP_PAGER");
1558 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1560 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1561 "_NET_WM_STATE_HIDDEN");
1563 toplevel->have_hidden = TRUE;
1568 XChangeProperty (xdisplay,
1570 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1571 XA_ATOM, 32, PropModeReplace,
1572 (guchar*) atoms, i);
1576 XDeleteProperty (xdisplay,
1578 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1581 if (window->state & GDK_WINDOW_STATE_STICKY)
1583 atoms[0] = 0xFFFFFFFF;
1584 XChangeProperty (xdisplay,
1586 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1587 XA_CARDINAL, 32, PropModeReplace,
1588 (guchar*) atoms, 1);
1589 toplevel->on_all_desktops = TRUE;
1593 XDeleteProperty (xdisplay,
1595 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1598 toplevel->map_serial = NextRequest (xdisplay);
1602 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1604 GdkDisplay *display;
1605 GdkX11Display *display_x11;
1606 GdkToplevelX11 *toplevel;
1607 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1608 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1609 Window xwindow = GDK_WINDOW_XID (window);
1612 if (!already_mapped)
1613 set_initial_hints (window);
1615 if (WINDOW_IS_TOPLEVEL (window))
1617 display = gdk_window_get_display (window);
1618 display_x11 = GDK_X11_DISPLAY (display);
1619 toplevel = _gdk_x11_window_get_toplevel (window);
1621 if (toplevel->user_time != 0 &&
1622 display_x11->user_time != 0 &&
1623 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1624 gdk_x11_window_set_user_time (window, display_x11->user_time);
1627 unset_bg = !window->input_only &&
1628 (window->window_type == GDK_WINDOW_CHILD ||
1629 impl->override_redirect) &&
1630 gdk_window_is_viewable (window);
1633 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1635 XMapWindow (xdisplay, xwindow);
1638 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1640 /* Fullscreen on current monitor is the default, no need to apply this mode
1641 * when mapping a window. This also ensures that the default behavior remains
1642 * consistent with pre-fullscreen mode implementation.
1644 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1645 gdk_x11_window_apply_fullscreen_mode (window);
1649 pre_unmap (GdkWindow *window)
1651 GdkWindow *start_window = NULL;
1653 if (window->input_only)
1656 if (window->window_type == GDK_WINDOW_CHILD)
1657 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1658 else if (window->window_type == GDK_WINDOW_TEMP)
1659 start_window = get_root (window);
1662 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1666 post_unmap (GdkWindow *window)
1668 GdkWindow *start_window = NULL;
1670 if (window->input_only)
1673 if (window->window_type == GDK_WINDOW_CHILD)
1674 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1675 else if (window->window_type == GDK_WINDOW_TEMP)
1676 start_window = get_root (window);
1680 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1682 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1684 GdkRectangle invalid_rect;
1686 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1687 invalid_rect.width = gdk_window_get_width (window);
1688 invalid_rect.height = gdk_window_get_height (window);
1689 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1690 &invalid_rect, TRUE);
1696 gdk_window_x11_hide (GdkWindow *window)
1698 /* We'll get the unmap notify eventually, and handle it then,
1699 * but checking here makes things more consistent if we are
1700 * just doing stuff ourself.
1702 _gdk_x11_window_grab_check_unmap (window,
1703 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1705 /* You can't simply unmap toplevel windows. */
1706 switch (window->window_type)
1708 case GDK_WINDOW_TOPLEVEL:
1709 case GDK_WINDOW_TEMP: /* ? */
1710 gdk_window_withdraw (window);
1713 case GDK_WINDOW_FOREIGN:
1714 case GDK_WINDOW_ROOT:
1715 case GDK_WINDOW_CHILD:
1719 _gdk_window_clear_update_area (window);
1722 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1723 GDK_WINDOW_XID (window));
1724 post_unmap (window);
1728 gdk_window_x11_withdraw (GdkWindow *window)
1730 if (!window->destroyed)
1732 if (GDK_WINDOW_IS_MAPPED (window))
1733 gdk_synthesize_window_state (window,
1735 GDK_WINDOW_STATE_WITHDRAWN);
1737 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1741 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1742 GDK_WINDOW_XID (window), 0);
1744 post_unmap (window);
1749 window_x11_move (GdkWindow *window,
1753 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1755 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1757 /* The window isn't actually damaged, but it's parent is */
1758 window_pre_damage (window);
1759 _gdk_x11_window_move_resize_child (window,
1761 window->width, window->height);
1765 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1766 GDK_WINDOW_XID (window),
1769 if (impl->override_redirect)
1778 window_x11_resize (GdkWindow *window,
1788 window_pre_damage (window);
1790 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1792 _gdk_x11_window_move_resize_child (window,
1793 window->x, window->y,
1798 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1800 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1801 GDK_WINDOW_XID (window),
1804 if (impl->override_redirect)
1806 window->width = width;
1807 window->height = height;
1808 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1812 if (width != window->width || height != window->height)
1813 window->resize_count += 1;
1817 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1821 window_x11_move_resize (GdkWindow *window,
1833 window_pre_damage (window);
1835 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1837 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1838 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1842 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1844 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1845 GDK_WINDOW_XID (window),
1846 x, y, width, height);
1848 if (impl->override_redirect)
1853 window->width = width;
1854 window->height = height;
1856 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1860 if (width != window->width || height != window->height)
1861 window->resize_count += 1;
1867 gdk_window_x11_move_resize (GdkWindow *window,
1874 if (with_move && (width < 0 && height < 0))
1875 window_x11_move (window, x, y);
1879 window_x11_move_resize (window, x, y, width, height);
1881 window_x11_resize (window, width, height);
1886 gdk_window_x11_reparent (GdkWindow *window,
1887 GdkWindow *new_parent,
1891 GdkWindowImplX11 *impl;
1893 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1895 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1896 _gdk_x11_window_tmp_unset_parent_bg (window);
1897 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1898 GDK_WINDOW_XID (window),
1899 GDK_WINDOW_XID (new_parent),
1900 new_parent->abs_x + x, new_parent->abs_y + y);
1901 _gdk_x11_window_tmp_reset_parent_bg (window);
1902 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1904 if (WINDOW_IS_TOPLEVEL (window))
1905 connect_frame_clock (window);
1907 /* old frame clock was disposed, our signal handlers removed */
1908 impl->frame_clock_connected = FALSE;
1910 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1911 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1913 window->parent = new_parent;
1915 /* Switch the window type as appropriate */
1917 switch (GDK_WINDOW_TYPE (new_parent))
1919 case GDK_WINDOW_ROOT:
1920 case GDK_WINDOW_FOREIGN:
1921 /* Reparenting to toplevel */
1923 if (!WINDOW_IS_TOPLEVEL (window) &&
1924 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1926 /* This is also done in common code at a later stage, but we
1927 need it in setup_toplevel, so do it here too */
1928 if (window->toplevel_window_type != -1)
1929 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1930 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1931 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1933 /* Wasn't a toplevel, set up */
1934 setup_toplevel_window (window, new_parent);
1939 case GDK_WINDOW_TOPLEVEL:
1940 case GDK_WINDOW_CHILD:
1941 case GDK_WINDOW_TEMP:
1942 if (WINDOW_IS_TOPLEVEL (window) &&
1945 if (impl->toplevel->focus_window)
1947 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1948 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1951 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1953 g_free (impl->toplevel);
1954 impl->toplevel = NULL;
1962 gdk_window_x11_raise (GdkWindow *window)
1964 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1968 gdk_window_x11_restack_under (GdkWindow *window,
1969 GList *native_siblings /* in requested order, first is bottom-most */)
1975 n_windows = g_list_length (native_siblings) + 1;
1976 windows = g_new (Window, n_windows);
1978 windows[0] = GDK_WINDOW_XID (window);
1979 /* Reverse order, as input order is bottom-most first */
1981 for (l = native_siblings; l != NULL; l = l->next)
1982 windows[i--] = GDK_WINDOW_XID (l->data);
1984 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1990 gdk_window_x11_restack_toplevel (GdkWindow *window,
1994 XWindowChanges changes;
1996 changes.sibling = GDK_WINDOW_XID (sibling);
1997 changes.stack_mode = above ? Above : Below;
1998 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1999 GDK_WINDOW_XID (window),
2000 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
2001 CWStackMode | CWSibling, &changes);
2005 gdk_window_x11_lower (GdkWindow *window)
2007 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
2011 * gdk_x11_window_move_to_current_desktop:
2012 * @window: (type GdkX11Window): a #GdkWindow
2014 * Moves the window to the correct workspace when running under a
2015 * window manager that supports multiple workspaces, as described
2016 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
2017 * Window Manager Hints</ulink>. Will not do anything if the
2018 * window is already on all workspaces.
2023 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
2025 GdkToplevelX11 *toplevel;
2027 g_return_if_fail (GDK_IS_WINDOW (window));
2028 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2030 toplevel = _gdk_x11_window_get_toplevel (window);
2032 if (toplevel->on_all_desktops)
2035 move_to_current_desktop (window);
2039 move_to_current_desktop (GdkWindow *window)
2041 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2042 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
2043 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2044 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
2051 gulong *current_desktop;
2052 GdkDisplay *display;
2054 display = gdk_window_get_display (window);
2056 /* Get current desktop, then set it; this is a race, but not
2057 * one that matters much in practice.
2059 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
2060 GDK_WINDOW_XROOTWIN (window),
2061 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
2063 False, XA_CARDINAL, &type, &format, &nitems,
2064 &bytes_after, &data);
2066 if (type == XA_CARDINAL)
2068 XClientMessageEvent xclient;
2069 current_desktop = (gulong *)data;
2071 memset (&xclient, 0, sizeof (xclient));
2072 xclient.type = ClientMessage;
2074 xclient.send_event = True;
2075 xclient.window = GDK_WINDOW_XID (window);
2076 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
2077 xclient.format = 32;
2079 xclient.data.l[0] = *current_desktop;
2080 xclient.data.l[1] = 1; /* source indication */
2081 xclient.data.l[2] = 0;
2082 xclient.data.l[3] = 0;
2083 xclient.data.l[4] = 0;
2085 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
2086 GDK_WINDOW_XROOTWIN (window),
2088 SubstructureRedirectMask | SubstructureNotifyMask,
2089 (XEvent *)&xclient);
2091 XFree (current_desktop);
2097 gdk_x11_window_focus (GdkWindow *window,
2100 GdkDisplay *display;
2102 g_return_if_fail (GDK_IS_WINDOW (window));
2104 if (GDK_WINDOW_DESTROYED (window) ||
2105 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2108 display = GDK_WINDOW_DISPLAY (window);
2110 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2111 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2113 XClientMessageEvent xclient;
2115 memset (&xclient, 0, sizeof (xclient));
2116 xclient.type = ClientMessage;
2117 xclient.window = GDK_WINDOW_XID (window);
2118 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2119 "_NET_ACTIVE_WINDOW");
2120 xclient.format = 32;
2121 xclient.data.l[0] = 1; /* requestor type; we're an app */
2122 xclient.data.l[1] = timestamp;
2123 xclient.data.l[2] = None; /* currently active window */
2124 xclient.data.l[3] = 0;
2125 xclient.data.l[4] = 0;
2127 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2128 SubstructureRedirectMask | SubstructureNotifyMask,
2129 (XEvent *)&xclient);
2133 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2135 /* There is no way of knowing reliably whether we are viewable;
2136 * so trap errors asynchronously around the XSetInputFocus call
2138 gdk_x11_display_error_trap_push (display);
2139 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2140 GDK_WINDOW_XID (window),
2143 gdk_x11_display_error_trap_pop_ignored (display);
2148 gdk_x11_window_set_type_hint (GdkWindow *window,
2149 GdkWindowTypeHint hint)
2151 GdkDisplay *display;
2154 if (GDK_WINDOW_DESTROYED (window) ||
2155 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2158 display = gdk_window_get_display (window);
2162 case GDK_WINDOW_TYPE_HINT_DIALOG:
2163 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2165 case GDK_WINDOW_TYPE_HINT_MENU:
2166 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2168 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2169 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2171 case GDK_WINDOW_TYPE_HINT_UTILITY:
2172 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2174 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2175 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2177 case GDK_WINDOW_TYPE_HINT_DOCK:
2178 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2180 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2181 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2183 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2184 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2186 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2187 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2189 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2190 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2192 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2193 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2195 case GDK_WINDOW_TYPE_HINT_COMBO:
2196 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2198 case GDK_WINDOW_TYPE_HINT_DND:
2199 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2202 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2204 case GDK_WINDOW_TYPE_HINT_NORMAL:
2205 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2209 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2210 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2211 XA_ATOM, 32, PropModeReplace,
2212 (guchar *)&atom, 1);
2215 static GdkWindowTypeHint
2216 gdk_x11_window_get_type_hint (GdkWindow *window)
2218 GdkDisplay *display;
2219 GdkWindowTypeHint type;
2222 gulong nitems_return;
2223 gulong bytes_after_return;
2224 guchar *data = NULL;
2226 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2228 if (GDK_WINDOW_DESTROYED (window) ||
2229 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2230 return GDK_WINDOW_TYPE_HINT_NORMAL;
2232 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2234 display = gdk_window_get_display (window);
2236 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2237 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2238 0, G_MAXLONG, False, XA_ATOM, &type_return,
2239 &format_return, &nitems_return, &bytes_after_return,
2242 if ((type_return == XA_ATOM) && (format_return == 32) &&
2243 (data) && (nitems_return == 1))
2245 Atom atom = *(Atom*)data;
2247 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2248 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2249 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2250 type = GDK_WINDOW_TYPE_HINT_MENU;
2251 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2252 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2253 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2254 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2255 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2256 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2257 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2258 type = GDK_WINDOW_TYPE_HINT_DOCK;
2259 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2260 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2261 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2262 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2263 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2264 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2265 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2266 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2267 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2268 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2269 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2270 type = GDK_WINDOW_TYPE_HINT_COMBO;
2271 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2272 type = GDK_WINDOW_TYPE_HINT_DND;
2275 if (type_return != None && data != NULL)
2283 gdk_wmspec_change_state (gboolean add,
2288 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2289 XClientMessageEvent xclient;
2291 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2292 #define _NET_WM_STATE_ADD 1 /* add/set property */
2293 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2295 memset (&xclient, 0, sizeof (xclient));
2296 xclient.type = ClientMessage;
2297 xclient.window = GDK_WINDOW_XID (window);
2298 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2299 xclient.format = 32;
2300 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2301 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2302 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2303 xclient.data.l[3] = 1; /* source indication */
2304 xclient.data.l[4] = 0;
2306 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2307 SubstructureRedirectMask | SubstructureNotifyMask,
2308 (XEvent *)&xclient);
2312 gdk_x11_window_set_modal_hint (GdkWindow *window,
2315 if (GDK_WINDOW_DESTROYED (window) ||
2316 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2319 window->modal_hint = modal;
2321 if (GDK_WINDOW_IS_MAPPED (window))
2322 gdk_wmspec_change_state (modal, window,
2323 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2328 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2329 gboolean skips_taskbar)
2331 GdkToplevelX11 *toplevel;
2333 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2335 if (GDK_WINDOW_DESTROYED (window) ||
2336 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2339 toplevel = _gdk_x11_window_get_toplevel (window);
2340 toplevel->skip_taskbar_hint = skips_taskbar;
2342 if (GDK_WINDOW_IS_MAPPED (window))
2343 gdk_wmspec_change_state (skips_taskbar, window,
2344 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2349 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2350 gboolean skips_pager)
2352 GdkToplevelX11 *toplevel;
2354 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2356 if (GDK_WINDOW_DESTROYED (window) ||
2357 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2360 toplevel = _gdk_x11_window_get_toplevel (window);
2361 toplevel->skip_pager_hint = skips_pager;
2363 if (GDK_WINDOW_IS_MAPPED (window))
2364 gdk_wmspec_change_state (skips_pager, window,
2365 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2370 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2373 GdkToplevelX11 *toplevel;
2375 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2377 if (GDK_WINDOW_DESTROYED (window) ||
2378 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2381 toplevel = _gdk_x11_window_get_toplevel (window);
2382 toplevel->urgency_hint = urgent;
2384 update_wm_hints (window, FALSE);
2388 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2389 const GdkGeometry *geometry,
2390 GdkWindowHints geom_mask)
2392 XSizeHints size_hints;
2394 if (GDK_WINDOW_DESTROYED (window) ||
2395 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2398 size_hints.flags = 0;
2400 if (geom_mask & GDK_HINT_POS)
2402 size_hints.flags |= PPosition;
2403 /* We need to initialize the following obsolete fields because KWM
2404 * apparently uses these fields if they are non-zero.
2411 if (geom_mask & GDK_HINT_USER_POS)
2413 size_hints.flags |= USPosition;
2416 if (geom_mask & GDK_HINT_USER_SIZE)
2418 size_hints.flags |= USSize;
2421 if (geom_mask & GDK_HINT_MIN_SIZE)
2423 size_hints.flags |= PMinSize;
2424 size_hints.min_width = geometry->min_width;
2425 size_hints.min_height = geometry->min_height;
2428 if (geom_mask & GDK_HINT_MAX_SIZE)
2430 size_hints.flags |= PMaxSize;
2431 size_hints.max_width = MAX (geometry->max_width, 1);
2432 size_hints.max_height = MAX (geometry->max_height, 1);
2435 if (geom_mask & GDK_HINT_BASE_SIZE)
2437 size_hints.flags |= PBaseSize;
2438 size_hints.base_width = geometry->base_width;
2439 size_hints.base_height = geometry->base_height;
2442 if (geom_mask & GDK_HINT_RESIZE_INC)
2444 size_hints.flags |= PResizeInc;
2445 size_hints.width_inc = geometry->width_inc;
2446 size_hints.height_inc = geometry->height_inc;
2449 if (geom_mask & GDK_HINT_ASPECT)
2451 size_hints.flags |= PAspect;
2452 if (geometry->min_aspect <= 1)
2454 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2455 size_hints.min_aspect.y = 65536;
2459 size_hints.min_aspect.x = 65536;
2460 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2462 if (geometry->max_aspect <= 1)
2464 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2465 size_hints.max_aspect.y = 65536;
2469 size_hints.max_aspect.x = 65536;
2470 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2474 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2476 size_hints.flags |= PWinGravity;
2477 size_hints.win_gravity = geometry->win_gravity;
2480 /* FIXME: Would it be better to delete this property if
2481 * geom_mask == 0? It would save space on the server
2483 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2484 GDK_WINDOW_XID (window),
2489 gdk_window_get_geometry_hints (GdkWindow *window,
2490 GdkGeometry *geometry,
2491 GdkWindowHints *geom_mask)
2493 XSizeHints *size_hints;
2494 glong junk_supplied_mask = 0;
2496 g_return_if_fail (GDK_IS_WINDOW (window));
2497 g_return_if_fail (geometry != NULL);
2498 g_return_if_fail (geom_mask != NULL);
2502 if (GDK_WINDOW_DESTROYED (window) ||
2503 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2506 size_hints = XAllocSizeHints ();
2510 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2511 GDK_WINDOW_XID (window),
2513 &junk_supplied_mask))
2514 size_hints->flags = 0;
2516 if (size_hints->flags & PMinSize)
2518 *geom_mask |= GDK_HINT_MIN_SIZE;
2519 geometry->min_width = size_hints->min_width;
2520 geometry->min_height = size_hints->min_height;
2523 if (size_hints->flags & PMaxSize)
2525 *geom_mask |= GDK_HINT_MAX_SIZE;
2526 geometry->max_width = MAX (size_hints->max_width, 1);
2527 geometry->max_height = MAX (size_hints->max_height, 1);
2530 if (size_hints->flags & PResizeInc)
2532 *geom_mask |= GDK_HINT_RESIZE_INC;
2533 geometry->width_inc = size_hints->width_inc;
2534 geometry->height_inc = size_hints->height_inc;
2537 if (size_hints->flags & PAspect)
2539 *geom_mask |= GDK_HINT_ASPECT;
2541 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2542 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2545 if (size_hints->flags & PWinGravity)
2547 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2548 geometry->win_gravity = size_hints->win_gravity;
2555 utf8_is_latin1 (const gchar *str)
2557 const char *p = str;
2561 gunichar ch = g_utf8_get_char (p);
2566 p = g_utf8_next_char (p);
2572 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2573 * convertable to STRING, otherwise, set it as compound text
2576 set_text_property (GdkDisplay *display,
2579 const gchar *utf8_str)
2581 gchar *prop_text = NULL;
2585 gboolean is_compound_text;
2587 if (utf8_is_latin1 (utf8_str))
2589 prop_type = XA_STRING;
2590 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2591 prop_length = prop_text ? strlen (prop_text) : 0;
2593 is_compound_text = FALSE;
2599 gdk_x11_display_utf8_to_compound_text (display,
2600 utf8_str, &gdk_type, &prop_format,
2601 (guchar **)&prop_text, &prop_length);
2602 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2603 is_compound_text = TRUE;
2608 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2611 prop_type, prop_format,
2612 PropModeReplace, (guchar *)prop_text,
2615 if (is_compound_text)
2616 gdk_x11_free_compound_text ((guchar *)prop_text);
2622 /* Set WM_NAME and _NET_WM_NAME
2625 set_wm_name (GdkDisplay *display,
2629 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2630 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2631 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2632 PropModeReplace, (guchar *)name, strlen (name));
2634 set_text_property (display, xwindow,
2635 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2640 gdk_x11_window_set_title (GdkWindow *window,
2643 GdkDisplay *display;
2647 g_return_if_fail (title != NULL);
2649 if (GDK_WINDOW_DESTROYED (window) ||
2650 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2653 display = gdk_window_get_display (window);
2654 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2655 xwindow = GDK_WINDOW_XID (window);
2657 set_wm_name (display, xwindow, title);
2659 if (!gdk_window_icon_name_set (window))
2661 XChangeProperty (xdisplay, xwindow,
2662 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2663 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2664 PropModeReplace, (guchar *)title, strlen (title));
2666 set_text_property (display, xwindow,
2667 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2673 gdk_x11_window_set_role (GdkWindow *window,
2676 GdkDisplay *display;
2678 display = gdk_window_get_display (window);
2680 if (GDK_WINDOW_DESTROYED (window) ||
2681 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2685 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2686 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2687 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2689 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2690 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2694 gdk_x11_window_set_startup_id (GdkWindow *window,
2695 const gchar *startup_id)
2697 GdkDisplay *display;
2699 g_return_if_fail (GDK_IS_WINDOW (window));
2701 display = gdk_window_get_display (window);
2703 if (GDK_WINDOW_DESTROYED (window) ||
2704 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2708 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2709 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2710 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2711 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2713 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2714 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2718 gdk_x11_window_set_transient_for (GdkWindow *window,
2721 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2722 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2723 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2724 GDK_WINDOW_XID (window),
2725 GDK_WINDOW_XID (parent));
2729 gdk_window_x11_set_back_color (GdkWindow *window,
2735 GdkVisual *visual = gdk_window_get_visual (window);
2737 /* I suppose we could handle these, but that'd require fiddling with
2738 * xrender formats... */
2742 switch (visual->type)
2744 case GDK_VISUAL_DIRECT_COLOR:
2745 case GDK_VISUAL_TRUE_COLOR:
2747 /* If bits not used for color are used for something other than padding,
2748 * it's likely alpha, so we set them to 1s.
2750 guint padding, pixel;
2752 /* Shifting by >= width-of-type isn't defined in C */
2753 if (visual->depth >= 32)
2756 padding = ((~(guint32)0)) << visual->depth;
2758 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2760 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2761 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2762 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2764 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2765 GDK_WINDOW_XID (window), pixel);
2769 /* These require fiddling with the colormap, and as they're essentially unused
2770 * we're just gonna skip them for now.
2772 case GDK_VISUAL_PSEUDO_COLOR:
2773 case GDK_VISUAL_GRAYSCALE:
2774 case GDK_VISUAL_STATIC_GRAY:
2775 case GDK_VISUAL_STATIC_COLOR:
2784 matrix_is_identity (cairo_matrix_t *matrix)
2786 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2787 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2788 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2792 gdk_window_x11_set_background (GdkWindow *window,
2793 cairo_pattern_t *pattern)
2796 cairo_surface_t *surface;
2797 cairo_matrix_t matrix;
2799 if (GDK_WINDOW_DESTROYED (window))
2802 if (pattern == NULL)
2806 /* X throws BadMatch if the parent has a different visual when
2807 * using ParentRelative */
2808 parent = gdk_window_get_parent (window);
2809 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2810 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2811 GDK_WINDOW_XID (window), ParentRelative);
2813 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2814 GDK_WINDOW_XID (window), None);
2818 switch (cairo_pattern_get_type (pattern))
2820 case CAIRO_PATTERN_TYPE_SOLID:
2821 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2822 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2825 case CAIRO_PATTERN_TYPE_SURFACE:
2826 cairo_pattern_get_matrix (pattern, &matrix);
2827 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2828 matrix_is_identity (&matrix) &&
2829 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2830 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2831 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2835 cairo_surface_get_device_offset (surface, &x, &y);
2836 /* XXX: This still bombs for non-pixmaps, but there's no way to
2837 * detect we're not a pixmap in Cairo... */
2838 if (x == 0.0 && y == 0.0)
2840 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2841 GDK_WINDOW_XID (window),
2842 cairo_xlib_surface_get_drawable (surface));
2847 case CAIRO_PATTERN_TYPE_LINEAR:
2848 case CAIRO_PATTERN_TYPE_RADIAL:
2850 /* fallback: just use black */
2854 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2855 GDK_WINDOW_XID (window), None);
2859 gdk_window_x11_set_device_cursor (GdkWindow *window,
2863 GdkWindowImplX11 *impl;
2865 g_return_if_fail (GDK_IS_WINDOW (window));
2866 g_return_if_fail (GDK_IS_DEVICE (device));
2868 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2871 g_hash_table_remove (impl->device_cursor, device);
2874 _gdk_x11_cursor_update_theme (cursor);
2875 g_hash_table_replace (impl->device_cursor,
2876 device, g_object_ref (cursor));
2879 if (!GDK_WINDOW_DESTROYED (window))
2880 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2884 _gdk_x11_window_get_cursor (GdkWindow *window)
2886 GdkWindowImplX11 *impl;
2888 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2890 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2892 return impl->cursor;
2896 gdk_window_x11_get_geometry (GdkWindow *window,
2907 guint tborder_width;
2910 if (!GDK_WINDOW_DESTROYED (window))
2912 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2913 GDK_WINDOW_XID (window),
2914 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2928 gdk_window_x11_get_root_coords (GdkWindow *window,
2939 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2940 GDK_WINDOW_XID (window),
2941 GDK_WINDOW_XROOTWIN (window),
2954 gdk_x11_window_get_root_origin (GdkWindow *window,
2960 gdk_window_get_frame_extents (window, &rect);
2970 gdk_x11_window_get_frame_extents (GdkWindow *window,
2973 GdkDisplay *display;
2974 GdkWindowImplX11 *impl;
2985 gulong nitems_return;
2986 gulong bytes_after_return;
2989 guint ww, wh, wb, wd;
2991 gboolean got_frame_extents = FALSE;
2993 g_return_if_fail (rect != NULL);
3000 while (window->parent && (window->parent)->parent)
3001 window = window->parent;
3003 /* Refine our fallback answer a bit using local information */
3004 rect->x = window->x;
3005 rect->y = window->y;
3006 rect->width = window->width;
3007 rect->height = window->height;
3009 impl = GDK_WINDOW_IMPL_X11 (window->impl);
3010 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
3016 display = gdk_window_get_display (window);
3018 gdk_x11_display_error_trap_push (display);
3020 xwindow = GDK_WINDOW_XID (window);
3022 /* first try: use _NET_FRAME_EXTENTS */
3023 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3024 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
3025 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
3026 gdk_x11_get_xatom_by_name_for_display (display,
3027 "_NET_FRAME_EXTENTS"),
3028 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
3029 &format_return, &nitems_return, &bytes_after_return,
3033 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
3034 (nitems_return == 4) && (data))
3036 gulong *ldata = (gulong *) data;
3037 got_frame_extents = TRUE;
3039 /* try to get the real client window geometry */
3040 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3041 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
3042 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
3043 xwindow, root, 0, 0, &wx, &wy, &child))
3051 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
3052 rect->x -= ldata[0];
3053 rect->y -= ldata[2];
3054 rect->width += ldata[0] + ldata[1];
3055 rect->height += ldata[2] + ldata[3];
3062 if (got_frame_extents)
3065 /* no frame extents property available, which means we either have a WM that
3066 is not EWMH compliant or is broken - try fallback and walk up the window
3067 tree to get our window's parent which hopefully is the window frame */
3069 /* use NETWM_VIRTUAL_ROOTS if available */
3070 root = GDK_WINDOW_XROOTWIN (window);
3072 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3073 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
3074 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
3075 gdk_x11_get_xatom_by_name_for_display (display,
3076 "_NET_VIRTUAL_ROOTS"),
3077 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3078 &format_return, &nitems_return, &bytes_after_return,
3082 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
3084 nvroots = nitems_return;
3085 vroots = (Window *)data;
3089 xparent = GDK_WINDOW_XID (window);
3095 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3097 &children, &nchildren))
3103 /* check virtual roots */
3104 for (i = 0; i < nvroots; i++)
3106 if (xparent == vroots[i])
3113 while (xparent != root);
3115 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3116 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3128 gdk_x11_display_error_trap_pop_ignored (display);
3132 gdk_window_x11_get_device_state (GdkWindow *window,
3136 GdkModifierType *mask)
3140 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3142 if (GDK_WINDOW_DESTROYED (window))
3145 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3149 return child != NULL;
3153 gdk_window_x11_get_events (GdkWindow *window)
3155 XWindowAttributes attrs;
3156 GdkEventMask event_mask;
3157 GdkEventMask filtered;
3159 if (GDK_WINDOW_DESTROYED (window))
3163 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3164 GDK_WINDOW_XID (window),
3166 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3167 /* if property change was filtered out before, keep it filtered out */
3168 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3169 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3175 gdk_window_x11_set_events (GdkWindow *window,
3176 GdkEventMask event_mask)
3178 long xevent_mask = 0;
3180 if (!GDK_WINDOW_DESTROYED (window))
3182 GdkX11Display *display_x11;
3184 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3185 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3187 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3188 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3189 GDK_WINDOW_XID (window), event_mask,
3195 do_shape_combine_region (GdkWindow *window,
3196 const cairo_region_t *shape_region,
3201 if (GDK_WINDOW_DESTROYED (window))
3204 if (shape_region == NULL)
3206 /* Use NULL mask to unset the shape */
3207 if (shape == ShapeBounding
3208 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3209 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3211 if (shape == ShapeBounding)
3213 _gdk_x11_window_tmp_unset_parent_bg (window);
3214 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3216 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3217 GDK_WINDOW_XID (window),
3222 if (shape == ShapeBounding)
3224 _gdk_x11_window_tmp_reset_parent_bg (window);
3225 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3231 if (shape == ShapeBounding
3232 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3233 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3236 XRectangle *xrects = NULL;
3238 _gdk_x11_region_get_xrectangles (shape_region,
3242 if (shape == ShapeBounding)
3244 _gdk_x11_window_tmp_unset_parent_bg (window);
3245 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3247 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3248 GDK_WINDOW_XID (window),
3255 if (shape == ShapeBounding)
3257 _gdk_x11_window_tmp_reset_parent_bg (window);
3258 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3266 gdk_window_x11_shape_combine_region (GdkWindow *window,
3267 const cairo_region_t *shape_region,
3271 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3275 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3276 const cairo_region_t *shape_region,
3281 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3287 gdk_x11_window_set_override_redirect (GdkWindow *window,
3288 gboolean override_redirect)
3290 XSetWindowAttributes attr;
3292 if (!GDK_WINDOW_DESTROYED (window) &&
3293 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3295 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3297 attr.override_redirect = (override_redirect? True : False);
3298 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3299 GDK_WINDOW_XID (window),
3303 impl->override_redirect = attr.override_redirect;
3308 gdk_x11_window_set_accept_focus (GdkWindow *window,
3309 gboolean accept_focus)
3311 accept_focus = accept_focus != FALSE;
3313 if (window->accept_focus != accept_focus)
3315 window->accept_focus = accept_focus;
3317 if (!GDK_WINDOW_DESTROYED (window) &&
3318 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3319 update_wm_hints (window, FALSE);
3324 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3325 gboolean focus_on_map)
3327 focus_on_map = focus_on_map != FALSE;
3329 if (window->focus_on_map != focus_on_map)
3331 window->focus_on_map = focus_on_map;
3333 if ((!GDK_WINDOW_DESTROYED (window)) &&
3334 (!window->focus_on_map) &&
3335 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3336 gdk_x11_window_set_user_time (window, 0);
3341 * gdk_x11_window_set_user_time:
3342 * @window: (type GdkX11Window): A toplevel #GdkWindow
3343 * @timestamp: An XServer timestamp to which the property should be set
3345 * The application can use this call to update the _NET_WM_USER_TIME
3346 * property on a toplevel window. This property stores an Xserver
3347 * time which represents the time of the last user input event
3348 * received for this window. This property may be used by the window
3349 * manager to alter the focus, stacking, and/or placement behavior of
3350 * windows when they are mapped depending on whether the new window
3351 * was created by a user action or is a "pop-up" window activated by a
3352 * timer or some other event.
3354 * Note that this property is automatically updated by GDK, so this
3355 * function should only be used by applications which handle input
3356 * events bypassing GDK.
3361 gdk_x11_window_set_user_time (GdkWindow *window,
3364 GdkDisplay *display;
3365 GdkX11Display *display_x11;
3366 GdkToplevelX11 *toplevel;
3367 glong timestamp_long = (glong)timestamp;
3370 if (GDK_WINDOW_DESTROYED (window) ||
3371 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3374 display = gdk_window_get_display (window);
3375 display_x11 = GDK_X11_DISPLAY (display);
3376 toplevel = _gdk_x11_window_get_toplevel (window);
3380 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3384 if (toplevel->focus_window != None &&
3385 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3386 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3387 xid = toplevel->focus_window;
3389 xid = GDK_WINDOW_XID (window);
3391 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3392 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3393 XA_CARDINAL, 32, PropModeReplace,
3394 (guchar *)×tamp_long, 1);
3396 if (timestamp_long != GDK_CURRENT_TIME &&
3397 (display_x11->user_time == GDK_CURRENT_TIME ||
3398 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3399 display_x11->user_time = timestamp_long;
3402 toplevel->user_time = timestamp_long;
3406 * gdk_x11_window_set_utf8_property:
3407 * @window: (type GdkX11Window): a #GdkWindow
3408 * @name: Property name, will be interned as an X atom
3409 * @value: (allow-none): Property value, or %NULL to delete
3411 * This function modifies or removes an arbitrary X11 window
3412 * property of type UTF8_STRING. If the given @window is
3413 * not a toplevel window, it is ignored.
3418 gdk_x11_window_set_utf8_property (GdkWindow *window,
3422 GdkDisplay *display;
3424 if (!WINDOW_IS_TOPLEVEL (window))
3427 display = gdk_window_get_display (window);
3431 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3432 GDK_WINDOW_XID (window),
3433 gdk_x11_get_xatom_by_name_for_display (display, name),
3434 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3435 PropModeReplace, (guchar *)value, strlen (value));
3439 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3440 GDK_WINDOW_XID (window),
3441 gdk_x11_get_xatom_by_name_for_display (display, name));
3446 * gdk_x11_window_set_hide_titlebar_when_maximized:
3447 * @window: (type GdkX11Window): a #GdkWindow
3448 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3451 * Set a hint for the window manager, requesting that the titlebar
3452 * should be hidden when the window is maximized.
3454 * Note that this property is automatically updated by GTK+, so this
3455 * function should only be used by applications which do not use GTK+
3456 * to create toplevel windows.
3461 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3462 gboolean hide_titlebar_when_maximized)
3464 GdkDisplay *display;
3466 if (!WINDOW_IS_TOPLEVEL (window))
3469 display = gdk_window_get_display (window);
3471 if (hide_titlebar_when_maximized)
3474 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3475 GDK_WINDOW_XID (window),
3476 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3478 PropModeReplace, (guchar *)&hide, 1);
3482 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3483 GDK_WINDOW_XID (window),
3484 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3489 * gdk_x11_window_set_theme_variant:
3490 * @window: (type GdkX11Window): a #GdkWindow
3491 * @variant: the theme variant to export
3493 * GTK+ applications can request a dark theme variant. In order to
3494 * make other applications - namely window managers using GTK+ for
3495 * themeing - aware of this choice, GTK+ uses this function to
3496 * export the requested theme variant as _GTK_THEME_VARIANT property
3497 * on toplevel windows.
3499 * Note that this property is automatically updated by GTK+, so this
3500 * function should only be used by applications which do not use GTK+
3501 * to create toplevel windows.
3506 gdk_x11_window_set_theme_variant (GdkWindow *window,
3509 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3512 #define GDK_SELECTION_MAX_SIZE(display) \
3514 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3515 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3516 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3519 gdk_window_update_icon (GdkWindow *window,
3522 GdkToplevelX11 *toplevel;
3523 GdkPixbuf *best_icon;
3527 toplevel = _gdk_x11_window_get_toplevel (window);
3529 if (toplevel->icon_pixmap != NULL)
3531 cairo_surface_destroy (toplevel->icon_pixmap);
3532 toplevel->icon_pixmap = NULL;
3535 if (toplevel->icon_mask != NULL)
3537 cairo_surface_destroy (toplevel->icon_mask);
3538 toplevel->icon_mask = NULL;
3541 #define IDEAL_SIZE 48
3543 best_size = G_MAXINT;
3545 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3547 GdkPixbuf *pixbuf = tmp_list->data;
3550 /* average width and height - if someone passes in a rectangular
3551 * icon they deserve what they get.
3553 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3556 if (best_icon == NULL)
3563 /* icon is better if it's 32 pixels or larger, and closer to
3564 * the ideal size than the current best.
3567 (ABS (best_size - IDEAL_SIZE) <
3568 ABS (this - IDEAL_SIZE)))
3578 int width = gdk_pixbuf_get_width (best_icon);
3579 int height = gdk_pixbuf_get_height (best_icon);
3582 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3586 cr = cairo_create (toplevel->icon_pixmap);
3587 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3588 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3589 if (gdk_pixbuf_get_has_alpha (best_icon))
3591 /* Saturate the image, so it has bilevel alpha */
3592 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3594 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3596 cairo_pop_group_to_source (cr);
3601 if (gdk_pixbuf_get_has_alpha (best_icon))
3603 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3607 cr = cairo_create (toplevel->icon_mask);
3608 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3609 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3615 update_wm_hints (window, FALSE);
3619 gdk_x11_window_set_icon_list (GdkWindow *window,
3628 gint width, height, stride;
3631 GdkDisplay *display;
3634 if (GDK_WINDOW_DESTROYED (window) ||
3635 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3638 display = gdk_window_get_display (window);
3646 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3648 width = gdk_pixbuf_get_width (pixbuf);
3649 height = gdk_pixbuf_get_height (pixbuf);
3651 /* silently ignore overlarge icons */
3652 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3654 g_warning ("gdk_window_set_icon_list: icons too large");
3659 size += 2 + width * height;
3661 l = g_list_next (l);
3664 data = g_malloc (size * sizeof (gulong));
3672 width = gdk_pixbuf_get_width (pixbuf);
3673 height = gdk_pixbuf_get_height (pixbuf);
3674 stride = gdk_pixbuf_get_rowstride (pixbuf);
3675 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3680 pixels = gdk_pixbuf_get_pixels (pixbuf);
3682 for (y = 0; y < height; y++)
3684 for (x = 0; x < width; x++)
3688 r = pixels[y*stride + x*n_channels + 0];
3689 g = pixels[y*stride + x*n_channels + 1];
3690 b = pixels[y*stride + x*n_channels + 2];
3691 if (n_channels >= 4)
3692 a = pixels[y*stride + x*n_channels + 3];
3696 *p++ = a << 24 | r << 16 | g << 8 | b ;
3700 l = g_list_next (l);
3706 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3707 GDK_WINDOW_XID (window),
3708 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3711 (guchar*) data, size);
3715 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3716 GDK_WINDOW_XID (window),
3717 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3722 gdk_window_update_icon (window, pixbufs);
3726 gdk_window_icon_name_set (GdkWindow *window)
3728 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3729 g_quark_from_static_string ("gdk-icon-name-set")));
3733 gdk_x11_window_set_icon_name (GdkWindow *window,
3736 GdkDisplay *display;
3738 if (GDK_WINDOW_DESTROYED (window) ||
3739 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3742 display = gdk_window_get_display (window);
3744 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3745 GUINT_TO_POINTER (name != NULL));
3749 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3750 GDK_WINDOW_XID (window),
3751 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3752 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3753 PropModeReplace, (guchar *)name, strlen (name));
3755 set_text_property (display, GDK_WINDOW_XID (window),
3756 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3761 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3762 GDK_WINDOW_XID (window),
3763 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3764 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3765 GDK_WINDOW_XID (window),
3766 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3771 gdk_x11_window_iconify (GdkWindow *window)
3773 if (GDK_WINDOW_DESTROYED (window) ||
3774 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3777 if (GDK_WINDOW_IS_MAPPED (window))
3779 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3780 GDK_WINDOW_XID (window),
3781 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3785 /* Flip our client side flag, the real work happens on map. */
3786 gdk_synthesize_window_state (window,
3788 GDK_WINDOW_STATE_ICONIFIED);
3789 gdk_wmspec_change_state (TRUE, window,
3790 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3796 gdk_x11_window_deiconify (GdkWindow *window)
3798 if (GDK_WINDOW_DESTROYED (window) ||
3799 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3802 if (GDK_WINDOW_IS_MAPPED (window))
3804 gdk_window_show (window);
3805 gdk_wmspec_change_state (FALSE, window,
3806 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3811 /* Flip our client side flag, the real work happens on map. */
3812 gdk_synthesize_window_state (window,
3813 GDK_WINDOW_STATE_ICONIFIED,
3815 gdk_wmspec_change_state (FALSE, window,
3816 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3822 gdk_x11_window_stick (GdkWindow *window)
3824 if (GDK_WINDOW_DESTROYED (window) ||
3825 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3828 if (GDK_WINDOW_IS_MAPPED (window))
3830 /* "stick" means stick to all desktops _and_ do not scroll with the
3831 * viewport. i.e. glue to the monitor glass in all cases.
3834 XClientMessageEvent xclient;
3836 /* Request stick during viewport scroll */
3837 gdk_wmspec_change_state (TRUE, window,
3838 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3841 /* Request desktop 0xFFFFFFFF */
3842 memset (&xclient, 0, sizeof (xclient));
3843 xclient.type = ClientMessage;
3844 xclient.window = GDK_WINDOW_XID (window);
3845 xclient.display = GDK_WINDOW_XDISPLAY (window);
3846 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3848 xclient.format = 32;
3850 xclient.data.l[0] = 0xFFFFFFFF;
3851 xclient.data.l[1] = 0;
3852 xclient.data.l[2] = 0;
3853 xclient.data.l[3] = 0;
3854 xclient.data.l[4] = 0;
3856 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3857 SubstructureRedirectMask | SubstructureNotifyMask,
3858 (XEvent *)&xclient);
3862 /* Flip our client side flag, the real work happens on map. */
3863 gdk_synthesize_window_state (window,
3865 GDK_WINDOW_STATE_STICKY);
3870 gdk_x11_window_unstick (GdkWindow *window)
3872 if (GDK_WINDOW_DESTROYED (window) ||
3873 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3876 if (GDK_WINDOW_IS_MAPPED (window))
3878 /* Request unstick from viewport */
3879 gdk_wmspec_change_state (FALSE, window,
3880 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3883 move_to_current_desktop (window);
3887 /* Flip our client side flag, the real work happens on map. */
3888 gdk_synthesize_window_state (window,
3889 GDK_WINDOW_STATE_STICKY,
3896 gdk_x11_window_maximize (GdkWindow *window)
3898 if (GDK_WINDOW_DESTROYED (window) ||
3899 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3902 if (GDK_WINDOW_IS_MAPPED (window))
3903 gdk_wmspec_change_state (TRUE, window,
3904 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3905 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3907 gdk_synthesize_window_state (window,
3909 GDK_WINDOW_STATE_MAXIMIZED);
3913 gdk_x11_window_unmaximize (GdkWindow *window)
3915 if (GDK_WINDOW_DESTROYED (window) ||
3916 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3919 if (GDK_WINDOW_IS_MAPPED (window))
3920 gdk_wmspec_change_state (FALSE, window,
3921 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3922 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3924 gdk_synthesize_window_state (window,
3925 GDK_WINDOW_STATE_MAXIMIZED,
3930 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3932 if (GDK_WINDOW_DESTROYED (window) ||
3933 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3936 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3937 * to which monitors so span across when the window is fullscreen, but it's
3938 * not a state in itself so this would have no effect if the window is not
3942 if (GDK_WINDOW_IS_MAPPED (window))
3944 XClientMessageEvent xclient;
3945 gint gdk_monitors[4];
3948 memset (&xclient, 0, sizeof (xclient));
3949 xclient.type = ClientMessage;
3950 xclient.window = GDK_WINDOW_XID (window);
3951 xclient.display = GDK_WINDOW_XDISPLAY (window);
3952 xclient.format = 32;
3954 switch (window->fullscreen_mode)
3956 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3958 /* FIXME: This is not part of the EWMH spec!
3960 * There is no documented mechanism to remove the property
3961 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3962 * invalid, largest possible value.
3964 * When given values larger than actual possible monitor values, most
3965 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3966 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3969 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3971 * Note, this (non documented) mechanism is unlikely to be an issue
3972 * as it's used only for transitionning back from "all monitors" to
3973 * "current monitor" mode.
3975 * Applications who don't change the default mode won't trigger this
3978 for (i = 0; i < 4; ++i)
3979 xclient.data.l[i] = G_MAXLONG;
3983 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3985 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3990 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3991 for (i = 0; i < 4; ++i)
3993 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3995 /* Sanity check, if XINERAMA is not available, we could have invalid
3996 * negative values for the XINERAMA indices.
3998 if (xclient.data.l[i] < 0)
4000 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
4007 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
4008 window->fullscreen_mode);
4012 /* Send fullscreen monitors client message */
4013 xclient.data.l[4] = 1; /* source indication */
4014 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
4015 "_NET_WM_FULLSCREEN_MONITORS");
4016 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
4017 SubstructureRedirectMask | SubstructureNotifyMask,
4018 (XEvent *)&xclient);
4023 gdk_x11_window_fullscreen (GdkWindow *window)
4025 if (GDK_WINDOW_DESTROYED (window) ||
4026 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4029 if (GDK_WINDOW_IS_MAPPED (window))
4031 gdk_wmspec_change_state (TRUE, window,
4032 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4034 /* Actual XRandR layout may have change since we computed the fullscreen
4035 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
4037 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
4038 gdk_x11_window_apply_fullscreen_mode (window);
4041 gdk_synthesize_window_state (window,
4043 GDK_WINDOW_STATE_FULLSCREEN);
4047 gdk_x11_window_unfullscreen (GdkWindow *window)
4049 if (GDK_WINDOW_DESTROYED (window) ||
4050 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4053 if (GDK_WINDOW_IS_MAPPED (window))
4054 gdk_wmspec_change_state (FALSE, window,
4055 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4059 gdk_synthesize_window_state (window,
4060 GDK_WINDOW_STATE_FULLSCREEN,
4065 gdk_x11_window_set_keep_above (GdkWindow *window,
4068 g_return_if_fail (GDK_IS_WINDOW (window));
4070 if (GDK_WINDOW_DESTROYED (window) ||
4071 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4074 if (GDK_WINDOW_IS_MAPPED (window))
4077 gdk_wmspec_change_state (FALSE, window,
4078 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4080 gdk_wmspec_change_state (setting, window,
4081 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4085 gdk_synthesize_window_state (window,
4086 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4087 setting ? GDK_WINDOW_STATE_ABOVE : 0);
4091 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
4093 g_return_if_fail (GDK_IS_WINDOW (window));
4095 if (GDK_WINDOW_DESTROYED (window) ||
4096 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4099 if (GDK_WINDOW_IS_MAPPED (window))
4102 gdk_wmspec_change_state (FALSE, window,
4103 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4105 gdk_wmspec_change_state (setting, window,
4106 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4110 gdk_synthesize_window_state (window,
4111 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4112 setting ? GDK_WINDOW_STATE_BELOW : 0);
4116 gdk_x11_window_get_group (GdkWindow *window)
4118 GdkToplevelX11 *toplevel;
4120 if (GDK_WINDOW_DESTROYED (window) ||
4121 !WINDOW_IS_TOPLEVEL (window))
4124 toplevel = _gdk_x11_window_get_toplevel (window);
4126 return toplevel->group_leader;
4130 gdk_x11_window_set_group (GdkWindow *window,
4133 GdkToplevelX11 *toplevel;
4135 g_return_if_fail (GDK_IS_WINDOW (window));
4136 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4137 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4139 if (GDK_WINDOW_DESTROYED (window) ||
4140 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4141 !WINDOW_IS_TOPLEVEL (window))
4144 toplevel = _gdk_x11_window_get_toplevel (window);
4147 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4149 if (toplevel->group_leader != leader)
4151 if (toplevel->group_leader)
4152 g_object_unref (toplevel->group_leader);
4153 toplevel->group_leader = g_object_ref (leader);
4154 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4157 update_wm_hints (window, FALSE);
4160 static MotifWmHints *
4161 gdk_window_get_mwm_hints (GdkWindow *window)
4163 GdkDisplay *display;
4164 Atom hints_atom = None;
4171 if (GDK_WINDOW_DESTROYED (window))
4174 display = gdk_window_get_display (window);
4176 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4178 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4179 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4180 False, AnyPropertyType, &type, &format, &nitems,
4181 &bytes_after, &data);
4186 return (MotifWmHints *)data;
4190 gdk_window_set_mwm_hints (GdkWindow *window,
4191 MotifWmHints *new_hints)
4193 GdkDisplay *display;
4194 Atom hints_atom = None;
4196 MotifWmHints *hints;
4202 if (GDK_WINDOW_DESTROYED (window))
4205 display = gdk_window_get_display (window);
4207 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4209 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4210 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4211 False, AnyPropertyType, &type, &format, &nitems,
4212 &bytes_after, &data);
4218 hints = (MotifWmHints *)data;
4220 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4222 hints->flags |= MWM_HINTS_FUNCTIONS;
4223 hints->functions = new_hints->functions;
4225 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4227 hints->flags |= MWM_HINTS_DECORATIONS;
4228 hints->decorations = new_hints->decorations;
4232 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4233 hints_atom, hints_atom, 32, PropModeReplace,
4234 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4236 if (hints != new_hints)
4241 gdk_x11_window_set_decorations (GdkWindow *window,
4242 GdkWMDecoration decorations)
4246 if (GDK_WINDOW_DESTROYED (window) ||
4247 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4250 /* initialize to zero to avoid writing uninitialized data to socket */
4251 memset(&hints, 0, sizeof(hints));
4252 hints.flags = MWM_HINTS_DECORATIONS;
4253 hints.decorations = decorations;
4255 gdk_window_set_mwm_hints (window, &hints);
4259 gdk_x11_window_get_decorations(GdkWindow *window,
4260 GdkWMDecoration *decorations)
4262 MotifWmHints *hints;
4263 gboolean result = FALSE;
4265 if (GDK_WINDOW_DESTROYED (window) ||
4266 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4269 hints = gdk_window_get_mwm_hints (window);
4273 if (hints->flags & MWM_HINTS_DECORATIONS)
4276 *decorations = hints->decorations;
4287 gdk_x11_window_set_functions (GdkWindow *window,
4288 GdkWMFunction functions)
4292 g_return_if_fail (GDK_IS_WINDOW (window));
4294 if (GDK_WINDOW_DESTROYED (window) ||
4295 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4298 /* initialize to zero to avoid writing uninitialized data to socket */
4299 memset(&hints, 0, sizeof(hints));
4300 hints.flags = MWM_HINTS_FUNCTIONS;
4301 hints.functions = functions;
4303 gdk_window_set_mwm_hints (window, &hints);
4307 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4311 cairo_region_t *shape;
4319 /* Note that XShapeGetRectangles returns NULL in two situations:
4320 * - the server doesn't support the SHAPE extension
4321 * - the shape is empty
4323 * Since we can't discriminate these here, we always return
4324 * an empty shape. It is the callers responsibility to check
4325 * whether the server supports the SHAPE extensions beforehand.
4327 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4330 return cairo_region_create (); /* Empty */
4332 if (ord != YXBanded)
4334 /* This really shouldn't happen with any xserver, as they
4335 * generally convert regions to YXBanded internally
4337 g_warning ("non YXBanded shape masks not supported");
4342 rl = g_new (GdkRectangle, rn);
4343 for (i = 0; i < rn; i++)
4347 rl[i].width = xrl[i].width;
4348 rl[i].height = xrl[i].height;
4352 shape = cairo_region_create_rectangles (rl, rn);
4359 static cairo_region_t *
4360 gdk_x11_window_get_shape (GdkWindow *window)
4362 if (!GDK_WINDOW_DESTROYED (window) &&
4363 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4364 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4365 GDK_WINDOW_XID (window),
4371 static cairo_region_t *
4372 gdk_x11_window_get_input_shape (GdkWindow *window)
4374 #if defined(ShapeInput)
4375 if (!GDK_WINDOW_DESTROYED (window) &&
4376 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4377 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4378 GDK_WINDOW_XID (window),
4386 gdk_window_set_static_bit_gravity (GdkWindow *window,
4389 XSetWindowAttributes xattributes;
4390 guint xattributes_mask = 0;
4392 g_return_if_fail (GDK_IS_WINDOW (window));
4394 if (window->input_only)
4397 xattributes.bit_gravity = StaticGravity;
4398 xattributes_mask |= CWBitGravity;
4399 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4400 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4401 GDK_WINDOW_XID (window),
4402 CWBitGravity, &xattributes);
4406 gdk_window_set_static_win_gravity (GdkWindow *window,
4409 XSetWindowAttributes xattributes;
4411 g_return_if_fail (GDK_IS_WINDOW (window));
4413 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4415 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4416 GDK_WINDOW_XID (window),
4417 CWWinGravity, &xattributes);
4421 gdk_window_x11_set_static_gravities (GdkWindow *window,
4422 gboolean use_static)
4426 if (!use_static == !window->guffaw_gravity)
4429 window->guffaw_gravity = use_static;
4431 if (!GDK_WINDOW_DESTROYED (window))
4433 gdk_window_set_static_bit_gravity (window, use_static);
4435 tmp_list = window->children;
4438 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4440 tmp_list = tmp_list->next;
4447 /* From the WM spec */
4448 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4449 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4450 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4451 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4452 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4453 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4454 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4455 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4456 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4457 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4458 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4459 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4462 wmspec_send_message (GdkDisplay *display,
4469 XClientMessageEvent xclient;
4471 memset (&xclient, 0, sizeof (xclient));
4472 xclient.type = ClientMessage;
4473 xclient.window = GDK_WINDOW_XID (window);
4474 xclient.message_type =
4475 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4476 xclient.format = 32;
4477 xclient.data.l[0] = root_x;
4478 xclient.data.l[1] = root_y;
4479 xclient.data.l[2] = action;
4480 xclient.data.l[3] = button;
4481 xclient.data.l[4] = 1; /* source indication */
4483 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4484 SubstructureRedirectMask | SubstructureNotifyMask,
4485 (XEvent *)&xclient);
4489 handle_wmspec_button_release (GdkDisplay *display,
4492 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4495 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4496 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4497 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4499 if (xevent->xany.type == GenericEvent)
4500 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4503 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4505 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4507 if ((xevent->xany.type == ButtonRelease &&
4508 xevent->xbutton.button == display_x11->wm_moveresize_button)
4509 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4511 (xevent->xany.type == GenericEvent &&
4512 xiev->evtype == XI_ButtonRelease &&
4513 xidev->detail == display_x11->wm_moveresize_button)
4517 display_x11->wm_moveresize_button = 0;
4518 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4524 wmspec_moveresize (GdkWindow *window,
4532 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4534 /* Release passive grab */
4535 gdk_device_ungrab (device, timestamp);
4536 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4538 wmspec_send_message (display, window, root_x, root_y, direction, button);
4542 wmspec_resize_drag (GdkWindow *window,
4552 /* Let the compiler turn a switch into a table, instead
4553 * of doing the table manually, this way is easier to verify.
4557 case GDK_WINDOW_EDGE_NORTH_WEST:
4558 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4561 case GDK_WINDOW_EDGE_NORTH:
4562 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4565 case GDK_WINDOW_EDGE_NORTH_EAST:
4566 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4569 case GDK_WINDOW_EDGE_WEST:
4570 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4573 case GDK_WINDOW_EDGE_EAST:
4574 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4577 case GDK_WINDOW_EDGE_SOUTH_WEST:
4578 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4581 case GDK_WINDOW_EDGE_SOUTH:
4582 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4585 case GDK_WINDOW_EDGE_SOUTH_EAST:
4586 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4590 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4595 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4598 typedef struct _MoveResizeData MoveResizeData;
4600 struct _MoveResizeData
4602 GdkDisplay *display;
4604 GdkWindow *moveresize_window;
4605 GdkWindow *moveresize_emulation_window;
4607 GdkWindowEdge resize_edge;
4609 gint moveresize_button;
4612 gint moveresize_orig_x;
4613 gint moveresize_orig_y;
4614 gint moveresize_orig_width;
4615 gint moveresize_orig_height;
4616 GdkWindowHints moveresize_geom_mask;
4617 GdkGeometry moveresize_geometry;
4618 Time moveresize_process_time;
4619 XEvent *moveresize_pending_event;
4622 static MoveResizeData *
4623 get_move_resize_data (GdkDisplay *display,
4626 MoveResizeData *mv_resize;
4627 static GQuark move_resize_quark = 0;
4629 if (!move_resize_quark)
4630 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4632 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4634 if (!mv_resize && create)
4636 mv_resize = g_new0 (MoveResizeData, 1);
4637 mv_resize->display = display;
4639 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4646 update_pos (MoveResizeData *mv_resize,
4652 dx = new_root_x - mv_resize->moveresize_x;
4653 dy = new_root_y - mv_resize->moveresize_y;
4655 if (mv_resize->is_resize)
4659 x = mv_resize->moveresize_orig_x;
4660 y = mv_resize->moveresize_orig_y;
4662 w = mv_resize->moveresize_orig_width;
4663 h = mv_resize->moveresize_orig_height;
4665 switch (mv_resize->resize_edge)
4667 case GDK_WINDOW_EDGE_NORTH_WEST:
4673 case GDK_WINDOW_EDGE_NORTH:
4677 case GDK_WINDOW_EDGE_NORTH_EAST:
4682 case GDK_WINDOW_EDGE_SOUTH_WEST:
4687 case GDK_WINDOW_EDGE_SOUTH_EAST:
4691 case GDK_WINDOW_EDGE_SOUTH:
4694 case GDK_WINDOW_EDGE_EAST:
4697 case GDK_WINDOW_EDGE_WEST:
4708 if (mv_resize->moveresize_geom_mask)
4710 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4711 mv_resize->moveresize_geom_mask,
4715 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4721 x = mv_resize->moveresize_orig_x + dx;
4722 y = mv_resize->moveresize_orig_y + dy;
4724 gdk_window_move (mv_resize->moveresize_window, x, y);
4729 finish_drag (MoveResizeData *mv_resize)
4731 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4732 mv_resize->moveresize_emulation_window = NULL;
4733 g_object_unref (mv_resize->moveresize_window);
4734 mv_resize->moveresize_window = NULL;
4736 if (mv_resize->moveresize_pending_event)
4738 g_free (mv_resize->moveresize_pending_event);
4739 mv_resize->moveresize_pending_event = NULL;
4744 lookahead_motion_predicate (Display *xdisplay,
4748 gboolean *seen_release = (gboolean *)arg;
4749 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4750 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4755 switch (event->xany.type)
4758 *seen_release = TRUE;
4761 mv_resize->moveresize_process_time = event->xmotion.time;
4771 moveresize_lookahead (MoveResizeData *mv_resize,
4775 gboolean seen_release = FALSE;
4777 if (mv_resize->moveresize_process_time)
4779 if (event->xmotion.time == mv_resize->moveresize_process_time)
4781 mv_resize->moveresize_process_time = 0;
4788 XCheckIfEvent (event->xany.display, &tmp_event,
4789 lookahead_motion_predicate, (XPointer) & seen_release);
4791 return mv_resize->moveresize_process_time == 0;
4795 _gdk_x11_moveresize_handle_event (XEvent *event)
4797 guint button_mask = 0;
4798 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4799 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4801 if (!mv_resize || !mv_resize->moveresize_window)
4803 handle_wmspec_button_release (display, event);
4807 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4809 switch (event->xany.type)
4812 if (mv_resize->moveresize_window->resize_count > 0)
4814 if (mv_resize->moveresize_pending_event)
4815 *mv_resize->moveresize_pending_event = *event;
4817 mv_resize->moveresize_pending_event =
4818 g_memdup (event, sizeof (XEvent));
4822 if (!moveresize_lookahead (mv_resize, event))
4825 update_pos (mv_resize,
4826 event->xmotion.x_root,
4827 event->xmotion.y_root);
4829 /* This should never be triggered in normal cases, but in the
4830 * case where the drag started without an implicit grab being
4831 * in effect, we could miss the release if it occurs before
4832 * we grab the pointer; this ensures that we will never
4833 * get a permanently stuck grab.
4835 if ((event->xmotion.state & button_mask) == 0)
4836 finish_drag (mv_resize);
4840 update_pos (mv_resize,
4841 event->xbutton.x_root,
4842 event->xbutton.y_root);
4844 if (event->xbutton.button == mv_resize->moveresize_button)
4845 finish_drag (mv_resize);
4848 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4851 /* we just assume this is an XI2 event */
4852 XIEvent *ev = (XIEvent *) event->xcookie.data;
4853 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4858 update_pos (mv_resize, xev->root_x, xev->root_y);
4859 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4860 if ((state & button_mask) == 0)
4861 finish_drag (mv_resize);
4864 case XI_ButtonRelease:
4865 update_pos (mv_resize, xev->root_x, xev->root_y);
4866 if (xev->detail == mv_resize->moveresize_button)
4867 finish_drag (mv_resize);
4879 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4883 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4885 if (!mv_resize || window != mv_resize->moveresize_window)
4888 if (mv_resize->moveresize_pending_event)
4890 tmp_event = mv_resize->moveresize_pending_event;
4891 mv_resize->moveresize_pending_event = NULL;
4892 _gdk_x11_moveresize_handle_event (tmp_event);
4900 create_moveresize_window (MoveResizeData *mv_resize,
4903 GdkWindowAttr attributes;
4904 gint attributes_mask;
4905 GdkGrabStatus status;
4907 g_assert (mv_resize->moveresize_emulation_window == NULL);
4909 attributes.x = -100;
4910 attributes.y = -100;
4911 attributes.width = 10;
4912 attributes.height = 10;
4913 attributes.window_type = GDK_WINDOW_TEMP;
4914 attributes.wclass = GDK_INPUT_ONLY;
4915 attributes.override_redirect = TRUE;
4916 attributes.event_mask = 0;
4918 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4920 mv_resize->moveresize_emulation_window =
4921 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4925 gdk_window_show (mv_resize->moveresize_emulation_window);
4927 status = gdk_device_grab (mv_resize->device,
4928 mv_resize->moveresize_emulation_window,
4931 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4935 if (status != GDK_GRAB_SUCCESS)
4937 /* If this fails, some other client has grabbed the window
4940 finish_drag (mv_resize);
4943 mv_resize->moveresize_process_time = 0;
4947 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4948 so that calling XMoveWindow with these coordinates will not move the
4950 Note that this depends on the WM to implement ICCCM-compliant reference
4954 calculate_unmoving_origin (MoveResizeData *mv_resize)
4959 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4960 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4962 gdk_window_get_origin (mv_resize->moveresize_window,
4963 &mv_resize->moveresize_orig_x,
4964 &mv_resize->moveresize_orig_y);
4968 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4969 gdk_window_get_geometry (mv_resize->moveresize_window,
4970 NULL, NULL, &width, &height);
4972 switch (mv_resize->moveresize_geometry.win_gravity)
4974 case GDK_GRAVITY_NORTH_WEST:
4975 mv_resize->moveresize_orig_x = rect.x;
4976 mv_resize->moveresize_orig_y = rect.y;
4978 case GDK_GRAVITY_NORTH:
4979 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4980 mv_resize->moveresize_orig_y = rect.y;
4982 case GDK_GRAVITY_NORTH_EAST:
4983 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4984 mv_resize->moveresize_orig_y = rect.y;
4986 case GDK_GRAVITY_WEST:
4987 mv_resize->moveresize_orig_x = rect.x;
4988 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4990 case GDK_GRAVITY_CENTER:
4991 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4992 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4994 case GDK_GRAVITY_EAST:
4995 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4996 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4998 case GDK_GRAVITY_SOUTH_WEST:
4999 mv_resize->moveresize_orig_x = rect.x;
5000 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5002 case GDK_GRAVITY_SOUTH:
5003 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5004 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5006 case GDK_GRAVITY_SOUTH_EAST:
5007 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5008 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5011 mv_resize->moveresize_orig_x = rect.x;
5012 mv_resize->moveresize_orig_y = rect.y;
5019 emulate_resize_drag (GdkWindow *window,
5027 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5029 mv_resize->is_resize = TRUE;
5030 mv_resize->moveresize_button = button;
5031 mv_resize->resize_edge = edge;
5032 mv_resize->device = device;
5033 mv_resize->moveresize_x = root_x;
5034 mv_resize->moveresize_y = root_y;
5035 mv_resize->moveresize_window = g_object_ref (window);
5037 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
5038 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
5040 mv_resize->moveresize_geom_mask = 0;
5041 gdk_window_get_geometry_hints (window,
5042 &mv_resize->moveresize_geometry,
5043 &mv_resize->moveresize_geom_mask);
5045 calculate_unmoving_origin (mv_resize);
5047 create_moveresize_window (mv_resize, timestamp);
5051 emulate_move_drag (GdkWindow *window,
5058 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5060 mv_resize->is_resize = FALSE;
5061 mv_resize->device = device;
5062 mv_resize->moveresize_button = button;
5063 mv_resize->moveresize_x = root_x;
5064 mv_resize->moveresize_y = root_y;
5066 mv_resize->moveresize_window = g_object_ref (window);
5068 calculate_unmoving_origin (mv_resize);
5070 create_moveresize_window (mv_resize, timestamp);
5074 gdk_x11_window_begin_resize_drag (GdkWindow *window,
5082 if (GDK_WINDOW_DESTROYED (window) ||
5083 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5086 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5087 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5088 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5090 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5094 gdk_x11_window_begin_move_drag (GdkWindow *window,
5101 if (GDK_WINDOW_DESTROYED (window) ||
5102 !WINDOW_IS_TOPLEVEL (window))
5105 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5106 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5107 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5108 device, button, root_x, root_y, timestamp);
5110 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5114 gdk_x11_window_beep (GdkWindow *window)
5116 GdkDisplay *display;
5118 display = GDK_WINDOW_DISPLAY (window);
5121 if (GDK_X11_DISPLAY (display)->use_xkb)
5123 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5124 GDK_WINDOW_XID (window),
5135 gdk_x11_window_set_opacity (GdkWindow *window,
5138 GdkDisplay *display;
5141 g_return_if_fail (GDK_IS_WINDOW (window));
5143 if (GDK_WINDOW_DESTROYED (window) ||
5144 !WINDOW_IS_TOPLEVEL (window))
5147 display = gdk_window_get_display (window);
5151 else if (opacity > 1)
5154 cardinal = opacity * 0xffffffff;
5156 if (cardinal == 0xffffffff)
5157 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5158 GDK_WINDOW_XID (window),
5159 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5161 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5162 GDK_WINDOW_XID (window),
5163 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5166 (guchar *) &cardinal, 1);
5170 gdk_x11_window_set_composited (GdkWindow *window,
5171 gboolean composited)
5173 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5174 GdkWindowImplX11 *impl;
5175 GdkDisplay *display;
5179 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5181 display = gdk_window_get_display (window);
5182 dpy = GDK_DISPLAY_XDISPLAY (display);
5183 xid = GDK_WINDOW_XID (window);
5187 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5188 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5192 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5193 XDamageDestroy (dpy, impl->damage);
5194 impl->damage = None;
5200 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5201 cairo_region_t *region)
5203 _gdk_window_process_updates_recurse (window, region);
5207 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5212 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5214 /* Sync after all drawing, otherwise the client can get "ahead" of
5215 the server rendering during animations, such that we fill up
5216 the Xserver pipes with sync rendering ops not letting other
5217 clients (including the VM) do anything. */
5218 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5222 timestamp_predicate (Display *display,
5226 Window xwindow = GPOINTER_TO_UINT (arg);
5227 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5229 if (xevent->type == PropertyNotify &&
5230 xevent->xproperty.window == xwindow &&
5231 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5232 "GDK_TIMESTAMP_PROP"))
5239 * gdk_x11_get_server_time:
5240 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5241 * with the server. The window must have
5242 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5245 * Routine to get the current X server time stamp.
5247 * Return value: the time stamp.
5250 gdk_x11_get_server_time (GdkWindow *window)
5256 Atom timestamp_prop_atom;
5258 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5259 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5261 xdisplay = GDK_WINDOW_XDISPLAY (window);
5262 xwindow = GDK_WINDOW_XID (window);
5263 timestamp_prop_atom =
5264 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5265 "GDK_TIMESTAMP_PROP");
5267 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5268 timestamp_prop_atom,
5269 8, PropModeReplace, &c, 1);
5271 XIfEvent (xdisplay, &xevent,
5272 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5274 return xevent.xproperty.time;
5278 * gdk_x11_window_get_xid:
5279 * @window: (type GdkX11Window): a native #GdkWindow.
5281 * Returns the X resource (window) belonging to a #GdkWindow.
5283 * Return value: the ID of @drawable's X resource.
5286 gdk_x11_window_get_xid (GdkWindow *window)
5288 /* Try to ensure the window has a native window */
5289 if (!_gdk_window_has_impl (window))
5291 gdk_window_ensure_native (window);
5293 /* We sync here to ensure the window is created in the Xserver when
5294 * this function returns. This is required because the returned XID
5295 * for this window must be valid immediately, even with another
5296 * connection to the Xserver */
5297 gdk_display_sync (gdk_window_get_display (window));
5300 if (!GDK_WINDOW_IS_X11 (window))
5302 g_warning (G_STRLOC " drawable is not a native X11 window");
5306 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5310 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5312 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5313 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5315 object_class->finalize = gdk_window_impl_x11_finalize;
5317 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5318 impl_class->show = gdk_window_x11_show;
5319 impl_class->hide = gdk_window_x11_hide;
5320 impl_class->withdraw = gdk_window_x11_withdraw;
5321 impl_class->set_events = gdk_window_x11_set_events;
5322 impl_class->get_events = gdk_window_x11_get_events;
5323 impl_class->raise = gdk_window_x11_raise;
5324 impl_class->lower = gdk_window_x11_lower;
5325 impl_class->restack_under = gdk_window_x11_restack_under;
5326 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5327 impl_class->move_resize = gdk_window_x11_move_resize;
5328 impl_class->set_background = gdk_window_x11_set_background;
5329 impl_class->reparent = gdk_window_x11_reparent;
5330 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5331 impl_class->get_geometry = gdk_window_x11_get_geometry;
5332 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5333 impl_class->get_device_state = gdk_window_x11_get_device_state;
5334 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5335 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5336 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5337 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5338 impl_class->translate = _gdk_x11_window_translate;
5339 impl_class->destroy = gdk_x11_window_destroy;
5340 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5341 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5342 impl_class->get_shape = gdk_x11_window_get_shape;
5343 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5344 impl_class->beep = gdk_x11_window_beep;
5346 impl_class->focus = gdk_x11_window_focus;
5347 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5348 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5349 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5350 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5351 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5352 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5353 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5354 impl_class->set_title = gdk_x11_window_set_title;
5355 impl_class->set_role = gdk_x11_window_set_role;
5356 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5357 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5358 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5359 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5360 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5361 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5362 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5363 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5364 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5365 impl_class->iconify = gdk_x11_window_iconify;
5366 impl_class->deiconify = gdk_x11_window_deiconify;
5367 impl_class->stick = gdk_x11_window_stick;
5368 impl_class->unstick = gdk_x11_window_unstick;
5369 impl_class->maximize = gdk_x11_window_maximize;
5370 impl_class->unmaximize = gdk_x11_window_unmaximize;
5371 impl_class->fullscreen = gdk_x11_window_fullscreen;
5372 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5373 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5374 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5375 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5376 impl_class->get_group = gdk_x11_window_get_group;
5377 impl_class->set_group = gdk_x11_window_set_group;
5378 impl_class->set_decorations = gdk_x11_window_set_decorations;
5379 impl_class->get_decorations = gdk_x11_window_get_decorations;
5380 impl_class->set_functions = gdk_x11_window_set_functions;
5381 impl_class->set_functions = gdk_x11_window_set_functions;
5382 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5383 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5384 impl_class->set_opacity = gdk_x11_window_set_opacity;
5385 impl_class->set_composited = gdk_x11_window_set_composited;
5386 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5387 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5388 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5389 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5390 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5391 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5392 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5393 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5394 impl_class->get_property = _gdk_x11_window_get_property;
5395 impl_class->change_property = _gdk_x11_window_change_property;
5396 impl_class->delete_property = _gdk_x11_window_delete_property;