1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gdkwindow-x11.h"
30 #include "gdkwindow.h"
31 #include "gdkwindowimpl.h"
32 #include "gdkvisualprivate.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
36 #include "gdkeventsource.h"
37 #include "gdkdisplay-x11.h"
38 #include "gdkframeclockidle.h"
39 #include "gdkprivate-x11.h"
44 #include <netinet/in.h>
47 #include <cairo-xlib.h>
52 #include <X11/Xutil.h>
53 #include <X11/Xatom.h>
55 #include <X11/extensions/shape.h>
58 #include <X11/XKBlib.h>
61 #ifdef HAVE_XCOMPOSITE
62 #include <X11/extensions/Xcomposite.h>
66 #include <X11/extensions/Xfixes.h>
70 #include <X11/extensions/Xdamage.h>
73 const int _gdk_x11_event_mask_table[21] =
77 PointerMotionHintMask,
94 SubstructureNotifyMask,
95 ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
98 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
100 /* Forward declarations */
101 static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
102 static void gdk_window_set_static_win_gravity (GdkWindow *window,
104 static gboolean gdk_window_icon_name_set (GdkWindow *window);
105 static void set_wm_name (GdkDisplay *display,
108 static void move_to_current_desktop (GdkWindow *window);
109 static void gdk_window_x11_set_background (GdkWindow *window,
110 cairo_pattern_t *pattern);
112 static void gdk_window_impl_x11_finalize (GObject *object);
114 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
115 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
116 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
118 #define WINDOW_IS_TOPLEVEL(window) \
119 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
120 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
121 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
123 /* Return whether time1 is considered later than time2 as far as xserver
124 * time is concerned. Accounts for wraparound.
126 #define XSERVER_TIME_IS_LATER(time1, time2) \
127 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
128 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
131 struct _GdkX11Window {
135 struct _GdkX11WindowClass {
136 GdkWindowClass parent_class;
139 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
142 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
147 gdk_x11_window_init (GdkX11Window *x11_window)
152 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
155 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
157 impl->toplevel_window_type = -1;
158 impl->device_cursor = g_hash_table_new_full (NULL, NULL,
159 NULL, g_object_unref);
163 _gdk_x11_window_get_toplevel (GdkWindow *window)
165 GdkWindowImplX11 *impl;
167 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
169 if (!WINDOW_IS_TOPLEVEL (window))
172 impl = GDK_WINDOW_IMPL_X11 (window->impl);
176 impl->toplevel = g_new0 (GdkToplevelX11, 1);
177 impl->toplevel->have_focused = TRUE;
180 return impl->toplevel;
183 static const cairo_user_data_key_t gdk_x11_cairo_key;
186 * _gdk_x11_window_update_size:
187 * @impl: a #GdkWindowImplX11.
189 * Updates the state of the window (in particular the drawable's
190 * cairo surface) when its size has changed.
193 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
195 if (impl->cairo_surface)
197 cairo_xlib_surface_set_size (impl->cairo_surface,
198 gdk_window_get_width (impl->wrapper),
199 gdk_window_get_height (impl->wrapper));
204 set_sync_counter(Display *display,
205 XSyncCounter counter,
208 XSyncValue sync_value;
210 XSyncIntsToValue(&sync_value,
211 value & G_GINT64_CONSTANT(0xFFFFFFFF),
213 XSyncSetCounter(display, counter, sync_value);
217 window_pre_damage (GdkWindow *window)
219 GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
220 GdkWindowImplX11 *impl;
222 if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
225 impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
227 if (impl->toplevel->in_frame &&
228 impl->toplevel->current_counter_value % 2 == 0)
230 impl->toplevel->current_counter_value += 1;
231 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
232 impl->toplevel->extended_update_counter,
233 impl->toplevel->current_counter_value);
238 on_surface_changed (void *data)
240 GdkWindow *window = data;
242 window_pre_damage (window);
245 /* We want to know when cairo drawing causes damage to the window,
246 * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
247 * window only when there actually is drawing. To do that we use
248 * a technique (hack) suggested by Uli Schlachter - if we set
249 * a dummy "mime data" on the cairo surface (this facility is
250 * used to attach JPEG data to an imager), then cairo wil flush
251 * and remove the mime data before making any changes to the window.
255 hook_surface_changed (GdkWindow *window)
257 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
259 if (impl->cairo_surface)
260 cairo_surface_set_mime_data (impl->cairo_surface,
261 "x-gdk/change-notify",
262 (unsigned char *)"X",
269 unhook_surface_changed (GdkWindow *window)
271 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
273 if (impl->cairo_surface)
274 cairo_surface_set_mime_data (impl->cairo_surface,
275 "x-gdk/change-notify",
281 gdk_x11_window_begin_frame (GdkWindow *window)
283 GdkWindowImplX11 *impl;
285 g_return_if_fail (GDK_IS_WINDOW (window));
287 impl = GDK_WINDOW_IMPL_X11 (window->impl);
289 if (!WINDOW_IS_TOPLEVEL (window) ||
290 impl->toplevel->extended_update_counter == None)
293 impl->toplevel->in_frame = TRUE;
295 hook_surface_changed (window);
299 gdk_x11_window_end_frame (GdkWindow *window)
301 GdkFrameClock *clock;
302 GdkFrameHistory *history;
303 gint64 frame_counter;
304 GdkFrameTimings *timings;
305 GdkWindowImplX11 *impl;
307 g_return_if_fail (GDK_IS_WINDOW (window));
309 impl = GDK_WINDOW_IMPL_X11 (window->impl);
311 if (!WINDOW_IS_TOPLEVEL (window) ||
312 impl->toplevel->extended_update_counter == None ||
313 !impl->toplevel->in_frame)
316 clock = gdk_window_get_frame_clock (window);
317 history = gdk_frame_clock_get_history (clock);
318 frame_counter = gdk_frame_history_get_frame_counter (history);
319 timings = gdk_frame_history_get_timings (history, frame_counter);
321 impl->toplevel->in_frame = FALSE;
323 if (impl->toplevel->current_counter_value % 2 == 1)
325 #ifdef G_ENABLE_DEBUG
326 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
328 XImage *image = XGetImage (GDK_WINDOW_XDISPLAY (window),
329 GDK_WINDOW_XID (window),
333 XDestroyImage (image);
335 #endif /* G_ENABLE_DEBUG */
337 /* An increment of 3 means that the frame was not drawn as fast as possible,
338 * but rather at a particular time. This can trigger different handling from
341 if (gdk_frame_timings_get_slept_before (timings))
342 impl->toplevel->current_counter_value += 3;
344 impl->toplevel->current_counter_value += 1;
346 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
347 impl->toplevel->extended_update_counter,
348 impl->toplevel->current_counter_value);
350 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
351 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
353 impl->toplevel->frame_pending = TRUE;
354 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
355 gdk_frame_timings_set_cookie (timings,
356 impl->toplevel->current_counter_value);
360 unhook_surface_changed (window);
362 if (!impl->toplevel->frame_pending)
363 gdk_frame_timings_set_complete (timings, TRUE);
366 /*****************************************************
367 * X11 specific implementations of generic functions *
368 *****************************************************/
371 gdk_x11_cairo_surface_destroy (void *data)
373 GdkWindowImplX11 *impl = data;
375 impl->cairo_surface = NULL;
378 static cairo_surface_t *
379 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
385 visual = gdk_window_get_visual (impl->wrapper);
386 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
387 GDK_WINDOW_IMPL_X11 (impl)->xid,
388 GDK_VISUAL_XVISUAL (visual),
392 static cairo_surface_t *
393 gdk_x11_ref_cairo_surface (GdkWindow *window)
395 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
397 if (GDK_WINDOW_DESTROYED (window))
400 if (!impl->cairo_surface)
402 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
403 gdk_window_get_width (window),
404 gdk_window_get_height (window));
406 if (impl->cairo_surface)
407 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
408 impl, gdk_x11_cairo_surface_destroy);
410 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
411 hook_surface_changed (window);
414 cairo_surface_reference (impl->cairo_surface);
416 return impl->cairo_surface;
420 gdk_window_impl_x11_finalize (GObject *object)
423 GdkWindowImplX11 *impl;
425 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
427 impl = GDK_WINDOW_IMPL_X11 (object);
429 wrapper = impl->wrapper;
431 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
432 unhook_surface_changed (wrapper);
434 _gdk_x11_window_grab_check_destroy (wrapper);
436 if (!GDK_WINDOW_DESTROYED (wrapper))
438 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
440 _gdk_x11_display_remove_window (display, impl->xid);
441 if (impl->toplevel && impl->toplevel->focus_window)
442 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
445 g_free (impl->toplevel);
448 g_object_unref (impl->cursor);
450 g_hash_table_destroy (impl->device_cursor);
452 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
461 free_pixmap (gpointer datap)
463 FreePixmapData *data = datap;
465 if (!gdk_display_is_closed (data->display))
467 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
471 g_object_unref (data->display);
472 g_slice_free (FreePixmapData, data);
476 attach_free_pixmap_handler (cairo_surface_t *surface,
480 static const cairo_user_data_key_t key;
481 FreePixmapData *data;
483 data = g_slice_new (FreePixmapData);
484 data->display = g_object_ref (display);
485 data->pixmap = pixmap;
487 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
490 /* Cairo does not guarantee we get an xlib surface if we call
491 * cairo_surface_create_similar(). In some cases however, we must use a
492 * pixmap or bitmap in the X11 API.
493 * These functions ensure an Xlib surface.
496 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
500 cairo_surface_t *surface;
503 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
504 GDK_WINDOW_XID (window),
506 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
508 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
510 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
515 /* Create a surface backed with a pixmap without alpha on the same screen as window */
516 static cairo_surface_t *
517 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
521 GdkScreen *screen = gdk_window_get_screen (window);
522 GdkVisual *visual = gdk_screen_get_system_visual (screen);
523 cairo_surface_t *surface;
526 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
527 GDK_WINDOW_XID (window),
529 gdk_visual_get_depth (visual));
530 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
532 GDK_VISUAL_XVISUAL (visual),
534 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
540 tmp_unset_bg (GdkWindow *window)
542 GdkWindowImplX11 *impl;
544 impl = GDK_WINDOW_IMPL_X11 (window->impl);
548 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
549 GDK_WINDOW_XID (window), None);
553 tmp_reset_bg (GdkWindow *window)
555 GdkWindowImplX11 *impl;
557 impl = GDK_WINDOW_IMPL_X11 (window->impl);
561 gdk_window_x11_set_background (window, window->background);
564 /* Unsetting and resetting window backgrounds.
566 * In many cases it is possible to avoid flicker by unsetting the
567 * background of windows. For example if the background of the
568 * parent window is unset when a window is unmapped, a brief flicker
569 * of background painting is avoided.
572 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
575 g_return_if_fail (GDK_IS_WINDOW (window));
577 if (window->input_only || window->destroyed ||
578 (window->window_type != GDK_WINDOW_ROOT &&
579 !GDK_WINDOW_IS_MAPPED (window)))
582 if (_gdk_window_has_impl (window) &&
583 GDK_WINDOW_IS_X11 (window) &&
584 window->window_type != GDK_WINDOW_ROOT &&
585 window->window_type != GDK_WINDOW_FOREIGN)
586 tmp_unset_bg (window);
592 for (l = window->children; l != NULL; l = l->next)
593 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
598 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
600 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
603 window = _gdk_window_get_impl_window (window->parent);
604 _gdk_x11_window_tmp_unset_bg (window, FALSE);
608 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
611 g_return_if_fail (GDK_IS_WINDOW (window));
613 if (window->input_only || window->destroyed ||
614 (window->window_type != GDK_WINDOW_ROOT &&
615 !GDK_WINDOW_IS_MAPPED (window)))
619 if (_gdk_window_has_impl (window) &&
620 GDK_WINDOW_IS_X11 (window) &&
621 window->window_type != GDK_WINDOW_ROOT &&
622 window->window_type != GDK_WINDOW_FOREIGN)
623 tmp_reset_bg (window);
629 for (l = window->children; l != NULL; l = l->next)
630 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
635 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
637 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
640 window = _gdk_window_get_impl_window (window->parent);
642 _gdk_x11_window_tmp_reset_bg (window, FALSE);
646 _gdk_x11_screen_init_root_window (GdkScreen *screen)
649 GdkWindowImplX11 *impl;
650 GdkX11Screen *x11_screen;
652 x11_screen = GDK_X11_SCREEN (screen);
654 g_assert (x11_screen->root_window == NULL);
656 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
658 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
659 window->impl_window = window;
660 window->visual = gdk_screen_get_system_visual (screen);
662 impl = GDK_WINDOW_IMPL_X11 (window->impl);
664 impl->xid = x11_screen->xroot_window;
665 impl->wrapper = window;
667 window->window_type = GDK_WINDOW_ROOT;
668 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
674 window->width = WidthOfScreen (x11_screen->xscreen);
675 window->height = HeightOfScreen (x11_screen->xscreen);
676 window->viewable = TRUE;
678 /* see init_randr_support() in gdkscreen-x11.c */
679 window->event_mask = GDK_STRUCTURE_MASK;
681 _gdk_window_update_size (x11_screen->root_window);
683 _gdk_x11_display_add_window (x11_screen->display,
684 &x11_screen->xroot_window,
685 x11_screen->root_window);
689 set_wm_protocols (GdkWindow *window)
691 GdkDisplay *display = gdk_window_get_display (window);
695 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
696 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
697 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
700 if (GDK_X11_DISPLAY (display)->use_sync)
701 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
704 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
708 get_default_title (void)
712 title = g_get_application_name ();
714 title = g_get_prgname ();
722 check_leader_window_title (GdkDisplay *display)
724 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
726 if (display_x11->leader_window && !display_x11->leader_window_title_set)
728 set_wm_name (display,
729 display_x11->leader_window,
730 get_default_title ());
732 display_x11->leader_window_title_set = TRUE;
737 create_focus_window (GdkDisplay *display,
740 GdkX11Display *display_x11;
741 GdkEventMask event_mask;
745 xdisplay = GDK_DISPLAY_XDISPLAY (display);
746 display_x11 = GDK_X11_DISPLAY (display);
748 focus_window = XCreateSimpleWindow (xdisplay, parent,
752 /* FIXME: probably better to actually track the requested event mask for the toplevel
754 event_mask = (GDK_KEY_PRESS_MASK |
755 GDK_KEY_RELEASE_MASK |
756 GDK_FOCUS_CHANGE_MASK);
758 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
762 XMapWindow (xdisplay, focus_window);
768 ensure_sync_counter (GdkWindow *window)
771 if (!GDK_WINDOW_DESTROYED (window))
773 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
774 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
777 toplevel->update_counter == None &&
778 GDK_X11_DISPLAY (display)->use_sync)
780 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
785 XSyncIntToValue (&value, 0);
787 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
788 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
790 atom = gdk_x11_get_xatom_by_name_for_display (display,
791 "_NET_WM_SYNC_REQUEST_COUNTER");
793 counters[0] = toplevel->update_counter;
794 counters[1] = toplevel->extended_update_counter;
795 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
798 (guchar *)counters, 2);
800 toplevel->current_counter_value = 0;
807 setup_toplevel_window (GdkWindow *window,
810 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
811 GdkDisplay *display = gdk_window_get_display (window);
812 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
813 XID xid = GDK_WINDOW_XID (window);
814 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
815 XSizeHints size_hints;
817 Window leader_window;
819 set_wm_protocols (window);
821 if (!window->input_only)
823 /* The focus window is off the visible area, and serves to receive key
824 * press events so they don't get sent to child windows.
826 toplevel->focus_window = create_focus_window (display, xid);
827 _gdk_x11_display_add_window (x11_screen->display,
828 &toplevel->focus_window,
832 check_leader_window_title (x11_screen->display);
834 /* FIXME: Is there any point in doing this? Do any WM's pay
835 * attention to PSize, and even if they do, is this the
838 size_hints.flags = PSize;
839 size_hints.width = window->width;
840 size_hints.height = window->height;
842 XSetWMNormalHints (xdisplay, xid, &size_hints);
844 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
845 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
848 XChangeProperty (xdisplay, xid,
849 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
854 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
857 XChangeProperty (xdisplay, xid,
858 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
859 XA_WINDOW, 32, PropModeReplace,
860 (guchar *) &leader_window, 1);
862 if (toplevel->focus_window != None)
863 XChangeProperty (xdisplay, xid,
864 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
865 XA_WINDOW, 32, PropModeReplace,
866 (guchar *) &toplevel->focus_window, 1);
868 if (!window->focus_on_map)
869 gdk_x11_window_set_user_time (window, 0);
870 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
871 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
873 ensure_sync_counter (window);
875 /* Start off in a frozen state - we'll finish this when we first paint */
876 gdk_x11_window_begin_frame (window);
880 on_frame_clock_before_paint (GdkFrameClock *clock,
883 gdk_x11_window_begin_frame (window);
887 on_frame_clock_after_paint (GdkFrameClock *clock,
890 gdk_x11_window_end_frame (window);
895 _gdk_x11_display_create_window_impl (GdkDisplay *display,
897 GdkWindow *real_parent,
899 GdkEventMask event_mask,
900 GdkWindowAttr *attributes,
901 gint attributes_mask)
903 GdkWindowImplX11 *impl;
904 GdkX11Screen *x11_screen;
905 GdkX11Display *display_x11;
906 GdkFrameClock *clock;
912 XSetWindowAttributes xattributes;
913 long xattributes_mask;
914 XClassHint *class_hint;
919 display_x11 = GDK_X11_DISPLAY (display);
920 xparent = GDK_WINDOW_XID (real_parent);
921 x11_screen = GDK_X11_SCREEN (screen);
923 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
924 window->impl = GDK_WINDOW_IMPL (impl);
925 impl->wrapper = GDK_WINDOW (window);
927 xdisplay = x11_screen->xdisplay;
929 xattributes_mask = 0;
931 xvisual = gdk_x11_visual_get_xvisual (window->visual);
933 if (attributes_mask & GDK_WA_NOREDIR)
935 xattributes.override_redirect =
936 (attributes->override_redirect == FALSE)?False:True;
937 xattributes_mask |= CWOverrideRedirect;
940 xattributes.override_redirect = False;
942 impl->override_redirect = xattributes.override_redirect;
944 if (window->parent && window->parent->guffaw_gravity)
946 xattributes.win_gravity = StaticGravity;
947 xattributes_mask |= CWWinGravity;
951 switch (window->window_type)
953 case GDK_WINDOW_TOPLEVEL:
954 case GDK_WINDOW_TEMP:
955 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
957 /* The common code warns for this case */
958 xparent = GDK_SCREEN_XROOTWIN (screen);
962 if (!window->input_only)
966 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
968 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
969 xattributes_mask |= CWBorderPixel | CWBackPixel;
971 if (window->guffaw_gravity)
972 xattributes.bit_gravity = StaticGravity;
974 xattributes.bit_gravity = NorthWestGravity;
976 xattributes_mask |= CWBitGravity;
978 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
979 xattributes_mask |= CWColormap;
981 if (window->window_type == GDK_WINDOW_TEMP)
983 xattributes.save_under = True;
984 xattributes.override_redirect = True;
985 xattributes.cursor = None;
986 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
988 impl->override_redirect = TRUE;
996 if (window->width > 65535 ||
997 window->height > 65535)
999 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
1001 if (window->width > 65535)
1002 window->width = 65535;
1003 if (window->height > 65535)
1004 window->height = 65535;
1007 impl->xid = XCreateWindow (xdisplay, xparent,
1008 window->x + window->parent->abs_x,
1009 window->y + window->parent->abs_y,
1010 window->width, window->height,
1011 0, window->depth, class, xvisual,
1012 xattributes_mask, &xattributes);
1014 g_object_ref (window);
1015 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1017 switch (GDK_WINDOW_TYPE (window))
1019 case GDK_WINDOW_TOPLEVEL:
1020 case GDK_WINDOW_TEMP:
1021 if (attributes_mask & GDK_WA_TITLE)
1022 title = attributes->title;
1024 title = get_default_title ();
1026 gdk_window_set_title (window, title);
1028 if (attributes_mask & GDK_WA_WMCLASS)
1030 class_hint = XAllocClassHint ();
1031 class_hint->res_name = attributes->wmclass_name;
1032 class_hint->res_class = attributes->wmclass_class;
1033 XSetClassHint (xdisplay, impl->xid, class_hint);
1037 setup_toplevel_window (window, window->parent);
1040 case GDK_WINDOW_CHILD:
1045 if (attributes_mask & GDK_WA_TYPE_HINT)
1046 gdk_window_set_type_hint (window, attributes->type_hint);
1048 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1049 GDK_WINDOW_XID (window), event_mask,
1050 StructureNotifyMask | PropertyChangeMask);
1052 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1053 gdk_window_set_frame_clock (window, clock);
1054 g_signal_connect (clock, "before-paint",
1055 G_CALLBACK (on_frame_clock_before_paint), window);
1056 g_signal_connect (clock, "after-paint",
1057 G_CALLBACK (on_frame_clock_after_paint), window);
1059 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1060 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1064 x_event_mask_to_gdk_event_mask (long mask)
1066 GdkEventMask event_mask = 0;
1069 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1071 if (mask & _gdk_x11_event_mask_table[i])
1072 event_mask |= 1 << (i + 1);
1079 * gdk_x11_window_foreign_new_for_display:
1080 * @display: the #GdkDisplay where the window handle comes from.
1081 * @window: an XLib <type>Window</type>
1083 * Wraps a native window in a #GdkWindow. The function will try to
1084 * look up the window using gdk_x11_window_lookup_for_display() first.
1085 * If it does not find it there, it will create a new window.
1087 * This may fail if the window has been destroyed. If the window
1088 * was already known to GDK, a new reference to the existing
1089 * #GdkWindow is returned.
1091 * Return value: (transfer full): a #GdkWindow wrapper for the native
1092 * window, or %NULL if the window has been destroyed. The wrapper
1093 * will be newly created, if one doesn't exist already.
1098 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1103 GdkWindowImplX11 *impl;
1104 GdkX11Display *display_x11;
1105 XWindowAttributes attrs;
1106 Window root, parent;
1107 Window *children = NULL;
1111 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1113 display_x11 = GDK_X11_DISPLAY (display);
1115 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1116 return g_object_ref (win);
1118 gdk_x11_display_error_trap_push (display);
1119 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1120 if (gdk_x11_display_error_trap_pop (display) || !result)
1123 /* FIXME: This is pretty expensive.
1124 * Maybe the caller should supply the parent
1126 gdk_x11_display_error_trap_push (display);
1127 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1128 if (gdk_x11_display_error_trap_pop (display) || !result)
1134 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1136 win = _gdk_display_create_window (display);
1137 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1138 win->impl_window = win;
1139 win->visual = gdk_x11_screen_lookup_visual (screen,
1140 XVisualIDFromVisual (attrs.visual));
1142 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1143 impl->wrapper = win;
1145 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1147 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1148 win->parent = gdk_screen_get_root_window (screen);
1150 win->parent->children = g_list_prepend (win->parent->children, win);
1156 win->width = attrs.width;
1157 win->height = attrs.height;
1158 win->window_type = GDK_WINDOW_FOREIGN;
1159 win->destroyed = FALSE;
1161 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1163 if (attrs.map_state == IsUnmapped)
1164 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1167 win->viewable = TRUE;
1169 win->depth = attrs.depth;
1172 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1174 /* Update the clip region, etc */
1175 _gdk_window_update_size (win);
1181 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1182 GdkToplevelX11 *toplevel)
1184 if (toplevel->icon_pixmap)
1186 cairo_surface_destroy (toplevel->icon_pixmap);
1187 toplevel->icon_pixmap = NULL;
1189 if (toplevel->icon_mask)
1191 cairo_surface_destroy (toplevel->icon_mask);
1192 toplevel->icon_mask = NULL;
1194 if (toplevel->group_leader)
1196 g_object_unref (toplevel->group_leader);
1197 toplevel->group_leader = NULL;
1200 if (toplevel->update_counter != None)
1202 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1203 toplevel->update_counter);
1204 toplevel->update_counter = None;
1206 toplevel->current_counter_value = 0;
1212 gdk_x11_window_destroy (GdkWindow *window,
1214 gboolean foreign_destroy)
1216 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1217 GdkToplevelX11 *toplevel;
1219 g_return_if_fail (GDK_IS_WINDOW (window));
1221 _gdk_x11_selection_window_destroyed (window);
1223 toplevel = _gdk_x11_window_get_toplevel (window);
1225 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1227 if (impl->cairo_surface)
1229 cairo_surface_finish (impl->cairo_surface);
1230 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1234 if (!recursing && !foreign_destroy)
1235 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1238 static cairo_surface_t *
1239 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1240 cairo_surface_t *surface,
1244 cairo_xlib_surface_set_size (surface, width, height);
1250 gdk_x11_window_destroy_foreign (GdkWindow *window)
1252 /* It's somebody else's window, but in our hierarchy,
1253 * so reparent it to the root window, and then send
1254 * it a delete event, as if we were a WM
1256 XClientMessageEvent xclient;
1257 GdkDisplay *display;
1259 display = GDK_WINDOW_DISPLAY (window);
1260 gdk_x11_display_error_trap_push (display);
1261 gdk_window_hide (window);
1262 gdk_window_reparent (window, NULL, 0, 0);
1264 memset (&xclient, 0, sizeof (xclient));
1265 xclient.type = ClientMessage;
1266 xclient.window = GDK_WINDOW_XID (window);
1267 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1268 xclient.format = 32;
1269 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1270 xclient.data.l[1] = CurrentTime;
1271 xclient.data.l[2] = 0;
1272 xclient.data.l[3] = 0;
1273 xclient.data.l[4] = 0;
1275 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1276 GDK_WINDOW_XID (window),
1277 False, 0, (XEvent *)&xclient);
1278 gdk_x11_display_error_trap_pop_ignored (display);
1282 get_root (GdkWindow *window)
1284 GdkScreen *screen = gdk_window_get_screen (window);
1286 return gdk_screen_get_root_window (screen);
1289 /* This function is called when the XWindow is really gone.
1292 gdk_x11_window_destroy_notify (GdkWindow *window)
1294 GdkWindowImplX11 *window_impl;
1296 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1298 if (!GDK_WINDOW_DESTROYED (window))
1300 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1301 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1303 _gdk_window_destroy (window, TRUE);
1306 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1307 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1308 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1310 _gdk_x11_window_grab_check_destroy (window);
1312 g_object_unref (window);
1315 static GdkDragProtocol
1316 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1319 GdkDragProtocol protocol;
1320 GdkDisplay *display;
1324 display = gdk_window_get_display (window);
1325 xid = _gdk_x11_display_get_drag_protocol (display,
1326 GDK_WINDOW_XID (window->impl_window),
1333 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1342 update_wm_hints (GdkWindow *window,
1345 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1346 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1350 !toplevel->is_leader &&
1351 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1354 wm_hints.flags = StateHint | InputHint;
1355 wm_hints.input = window->accept_focus ? True : False;
1356 wm_hints.initial_state = NormalState;
1358 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1360 wm_hints.flags |= StateHint;
1361 wm_hints.initial_state = IconicState;
1364 if (toplevel->icon_pixmap)
1366 wm_hints.flags |= IconPixmapHint;
1367 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1370 if (toplevel->icon_mask)
1372 wm_hints.flags |= IconMaskHint;
1373 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1376 wm_hints.flags |= WindowGroupHint;
1377 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1379 wm_hints.flags |= WindowGroupHint;
1380 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1383 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1385 if (toplevel->urgency_hint)
1386 wm_hints.flags |= XUrgencyHint;
1388 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1389 GDK_WINDOW_XID (window),
1394 set_initial_hints (GdkWindow *window)
1396 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1397 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1398 Window xwindow = GDK_WINDOW_XID (window);
1399 GdkToplevelX11 *toplevel;
1403 toplevel = _gdk_x11_window_get_toplevel (window);
1408 update_wm_hints (window, TRUE);
1410 /* We set the spec hints regardless of whether the spec is supported,
1411 * since it can't hurt and it's kind of expensive to check whether
1417 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1419 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1420 "_NET_WM_STATE_MAXIMIZED_VERT");
1422 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1423 "_NET_WM_STATE_MAXIMIZED_HORZ");
1425 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1428 if (window->state & GDK_WINDOW_STATE_ABOVE)
1430 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1431 "_NET_WM_STATE_ABOVE");
1435 if (window->state & GDK_WINDOW_STATE_BELOW)
1437 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1438 "_NET_WM_STATE_BELOW");
1442 if (window->state & GDK_WINDOW_STATE_STICKY)
1444 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1445 "_NET_WM_STATE_STICKY");
1447 toplevel->have_sticky = TRUE;
1450 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1452 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1453 "_NET_WM_STATE_FULLSCREEN");
1455 toplevel->have_fullscreen = TRUE;
1458 if (window->modal_hint)
1460 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1461 "_NET_WM_STATE_MODAL");
1465 if (toplevel->skip_taskbar_hint)
1467 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1468 "_NET_WM_STATE_SKIP_TASKBAR");
1472 if (toplevel->skip_pager_hint)
1474 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1475 "_NET_WM_STATE_SKIP_PAGER");
1479 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1481 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1482 "_NET_WM_STATE_HIDDEN");
1484 toplevel->have_hidden = TRUE;
1489 XChangeProperty (xdisplay,
1491 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1492 XA_ATOM, 32, PropModeReplace,
1493 (guchar*) atoms, i);
1497 XDeleteProperty (xdisplay,
1499 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1502 if (window->state & GDK_WINDOW_STATE_STICKY)
1504 atoms[0] = 0xFFFFFFFF;
1505 XChangeProperty (xdisplay,
1507 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1508 XA_CARDINAL, 32, PropModeReplace,
1509 (guchar*) atoms, 1);
1510 toplevel->on_all_desktops = TRUE;
1514 XDeleteProperty (xdisplay,
1516 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1519 toplevel->map_serial = NextRequest (xdisplay);
1523 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1525 GdkDisplay *display;
1526 GdkX11Display *display_x11;
1527 GdkToplevelX11 *toplevel;
1528 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1529 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1530 Window xwindow = GDK_WINDOW_XID (window);
1533 if (!already_mapped)
1534 set_initial_hints (window);
1536 if (WINDOW_IS_TOPLEVEL (window))
1538 display = gdk_window_get_display (window);
1539 display_x11 = GDK_X11_DISPLAY (display);
1540 toplevel = _gdk_x11_window_get_toplevel (window);
1542 if (toplevel->user_time != 0 &&
1543 display_x11->user_time != 0 &&
1544 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1545 gdk_x11_window_set_user_time (window, display_x11->user_time);
1548 unset_bg = !window->input_only &&
1549 (window->window_type == GDK_WINDOW_CHILD ||
1550 impl->override_redirect) &&
1551 gdk_window_is_viewable (window);
1554 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1556 XMapWindow (xdisplay, xwindow);
1559 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1561 /* Fullscreen on current monitor is the default, no need to apply this mode
1562 * when mapping a window. This also ensures that the default behavior remains
1563 * consistent with pre-fullscreen mode implementation.
1565 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1566 gdk_x11_window_apply_fullscreen_mode (window);
1570 pre_unmap (GdkWindow *window)
1572 GdkWindow *start_window = NULL;
1574 if (window->input_only)
1577 if (window->window_type == GDK_WINDOW_CHILD)
1578 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1579 else if (window->window_type == GDK_WINDOW_TEMP)
1580 start_window = get_root (window);
1583 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1587 post_unmap (GdkWindow *window)
1589 GdkWindow *start_window = NULL;
1591 if (window->input_only)
1594 if (window->window_type == GDK_WINDOW_CHILD)
1595 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1596 else if (window->window_type == GDK_WINDOW_TEMP)
1597 start_window = get_root (window);
1601 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1603 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1605 GdkRectangle invalid_rect;
1607 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1608 invalid_rect.width = gdk_window_get_width (window);
1609 invalid_rect.height = gdk_window_get_height (window);
1610 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1611 &invalid_rect, TRUE);
1617 gdk_window_x11_hide (GdkWindow *window)
1619 /* We'll get the unmap notify eventually, and handle it then,
1620 * but checking here makes things more consistent if we are
1621 * just doing stuff ourself.
1623 _gdk_x11_window_grab_check_unmap (window,
1624 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1626 /* You can't simply unmap toplevel windows. */
1627 switch (window->window_type)
1629 case GDK_WINDOW_TOPLEVEL:
1630 case GDK_WINDOW_TEMP: /* ? */
1631 gdk_window_withdraw (window);
1634 case GDK_WINDOW_FOREIGN:
1635 case GDK_WINDOW_ROOT:
1636 case GDK_WINDOW_CHILD:
1640 _gdk_window_clear_update_area (window);
1643 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1644 GDK_WINDOW_XID (window));
1645 post_unmap (window);
1649 gdk_window_x11_withdraw (GdkWindow *window)
1651 if (!window->destroyed)
1653 if (GDK_WINDOW_IS_MAPPED (window))
1654 gdk_synthesize_window_state (window,
1656 GDK_WINDOW_STATE_WITHDRAWN);
1658 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1662 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1663 GDK_WINDOW_XID (window), 0);
1665 post_unmap (window);
1670 window_x11_move (GdkWindow *window,
1674 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1676 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1678 /* The window isn't actually damaged, but it's parent is */
1679 window_pre_damage (window);
1680 _gdk_x11_window_move_resize_child (window,
1682 window->width, window->height);
1686 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1687 GDK_WINDOW_XID (window),
1690 if (impl->override_redirect)
1699 window_x11_resize (GdkWindow *window,
1709 window_pre_damage (window);
1711 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1713 _gdk_x11_window_move_resize_child (window,
1714 window->x, window->y,
1719 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1721 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1722 GDK_WINDOW_XID (window),
1725 if (impl->override_redirect)
1727 window->width = width;
1728 window->height = height;
1729 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1733 if (width != window->width || height != window->height)
1734 window->resize_count += 1;
1738 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1742 window_x11_move_resize (GdkWindow *window,
1754 window_pre_damage (window);
1756 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1758 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1759 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1763 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1765 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1766 GDK_WINDOW_XID (window),
1767 x, y, width, height);
1769 if (impl->override_redirect)
1774 window->width = width;
1775 window->height = height;
1777 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1781 if (width != window->width || height != window->height)
1782 window->resize_count += 1;
1788 gdk_window_x11_move_resize (GdkWindow *window,
1795 if (with_move && (width < 0 && height < 0))
1796 window_x11_move (window, x, y);
1800 window_x11_move_resize (window, x, y, width, height);
1802 window_x11_resize (window, width, height);
1807 gdk_window_x11_reparent (GdkWindow *window,
1808 GdkWindow *new_parent,
1812 GdkWindowImplX11 *impl;
1814 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1816 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1817 _gdk_x11_window_tmp_unset_parent_bg (window);
1818 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1819 GDK_WINDOW_XID (window),
1820 GDK_WINDOW_XID (new_parent),
1821 new_parent->abs_x + x, new_parent->abs_y + y);
1822 _gdk_x11_window_tmp_reset_parent_bg (window);
1823 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1825 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1826 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1828 window->parent = new_parent;
1830 /* Switch the window type as appropriate */
1832 switch (GDK_WINDOW_TYPE (new_parent))
1834 case GDK_WINDOW_ROOT:
1835 case GDK_WINDOW_FOREIGN:
1836 /* Reparenting to toplevel */
1838 if (!WINDOW_IS_TOPLEVEL (window) &&
1839 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1841 /* This is also done in common code at a later stage, but we
1842 need it in setup_toplevel, so do it here too */
1843 if (window->toplevel_window_type != -1)
1844 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1845 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1846 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1848 /* Wasn't a toplevel, set up */
1849 setup_toplevel_window (window, new_parent);
1854 case GDK_WINDOW_TOPLEVEL:
1855 case GDK_WINDOW_CHILD:
1856 case GDK_WINDOW_TEMP:
1857 if (WINDOW_IS_TOPLEVEL (window) &&
1860 if (impl->toplevel->focus_window)
1862 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1863 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1866 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1868 g_free (impl->toplevel);
1869 impl->toplevel = NULL;
1877 gdk_window_x11_raise (GdkWindow *window)
1879 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1883 gdk_window_x11_restack_under (GdkWindow *window,
1884 GList *native_siblings /* in requested order, first is bottom-most */)
1890 n_windows = g_list_length (native_siblings) + 1;
1891 windows = g_new (Window, n_windows);
1893 windows[0] = GDK_WINDOW_XID (window);
1894 /* Reverse order, as input order is bottom-most first */
1896 for (l = native_siblings; l != NULL; l = l->next)
1897 windows[i--] = GDK_WINDOW_XID (l->data);
1899 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1905 gdk_window_x11_restack_toplevel (GdkWindow *window,
1909 XWindowChanges changes;
1911 changes.sibling = GDK_WINDOW_XID (sibling);
1912 changes.stack_mode = above ? Above : Below;
1913 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1914 GDK_WINDOW_XID (window),
1915 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1916 CWStackMode | CWSibling, &changes);
1920 gdk_window_x11_lower (GdkWindow *window)
1922 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1926 * gdk_x11_window_move_to_current_desktop:
1927 * @window: (type GdkX11Window): a #GdkWindow
1929 * Moves the window to the correct workspace when running under a
1930 * window manager that supports multiple workspaces, as described
1931 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
1932 * Window Manager Hints</ulink>. Will not do anything if the
1933 * window is already on all workspaces.
1938 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1940 GdkToplevelX11 *toplevel;
1942 g_return_if_fail (GDK_IS_WINDOW (window));
1943 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1945 toplevel = _gdk_x11_window_get_toplevel (window);
1947 if (toplevel->on_all_desktops)
1950 move_to_current_desktop (window);
1954 move_to_current_desktop (GdkWindow *window)
1956 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1957 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
1958 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1959 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
1966 gulong *current_desktop;
1967 GdkDisplay *display;
1969 display = gdk_window_get_display (window);
1971 /* Get current desktop, then set it; this is a race, but not
1972 * one that matters much in practice.
1974 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1975 GDK_WINDOW_XROOTWIN (window),
1976 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1978 False, XA_CARDINAL, &type, &format, &nitems,
1979 &bytes_after, &data);
1981 if (type == XA_CARDINAL)
1983 XClientMessageEvent xclient;
1984 current_desktop = (gulong *)data;
1986 memset (&xclient, 0, sizeof (xclient));
1987 xclient.type = ClientMessage;
1989 xclient.send_event = True;
1990 xclient.window = GDK_WINDOW_XID (window);
1991 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1992 xclient.format = 32;
1994 xclient.data.l[0] = *current_desktop;
1995 xclient.data.l[1] = 1; /* source indication */
1996 xclient.data.l[2] = 0;
1997 xclient.data.l[3] = 0;
1998 xclient.data.l[4] = 0;
2000 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
2001 GDK_WINDOW_XROOTWIN (window),
2003 SubstructureRedirectMask | SubstructureNotifyMask,
2004 (XEvent *)&xclient);
2006 XFree (current_desktop);
2012 gdk_x11_window_focus (GdkWindow *window,
2015 GdkDisplay *display;
2017 g_return_if_fail (GDK_IS_WINDOW (window));
2019 if (GDK_WINDOW_DESTROYED (window) ||
2020 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2023 display = GDK_WINDOW_DISPLAY (window);
2025 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2026 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2028 XClientMessageEvent xclient;
2030 memset (&xclient, 0, sizeof (xclient));
2031 xclient.type = ClientMessage;
2032 xclient.window = GDK_WINDOW_XID (window);
2033 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2034 "_NET_ACTIVE_WINDOW");
2035 xclient.format = 32;
2036 xclient.data.l[0] = 1; /* requestor type; we're an app */
2037 xclient.data.l[1] = timestamp;
2038 xclient.data.l[2] = None; /* currently active window */
2039 xclient.data.l[3] = 0;
2040 xclient.data.l[4] = 0;
2042 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2043 SubstructureRedirectMask | SubstructureNotifyMask,
2044 (XEvent *)&xclient);
2048 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2050 /* There is no way of knowing reliably whether we are viewable;
2051 * so trap errors asynchronously around the XSetInputFocus call
2053 gdk_x11_display_error_trap_push (display);
2054 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2055 GDK_WINDOW_XID (window),
2058 gdk_x11_display_error_trap_pop_ignored (display);
2063 gdk_x11_window_set_type_hint (GdkWindow *window,
2064 GdkWindowTypeHint hint)
2066 GdkDisplay *display;
2069 if (GDK_WINDOW_DESTROYED (window) ||
2070 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2073 display = gdk_window_get_display (window);
2077 case GDK_WINDOW_TYPE_HINT_DIALOG:
2078 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2080 case GDK_WINDOW_TYPE_HINT_MENU:
2081 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2083 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2084 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2086 case GDK_WINDOW_TYPE_HINT_UTILITY:
2087 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2089 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2090 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2092 case GDK_WINDOW_TYPE_HINT_DOCK:
2093 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2095 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2096 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2098 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2099 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2101 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2102 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2104 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2105 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2107 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2108 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2110 case GDK_WINDOW_TYPE_HINT_COMBO:
2111 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2113 case GDK_WINDOW_TYPE_HINT_DND:
2114 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2117 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2119 case GDK_WINDOW_TYPE_HINT_NORMAL:
2120 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2124 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2125 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2126 XA_ATOM, 32, PropModeReplace,
2127 (guchar *)&atom, 1);
2130 static GdkWindowTypeHint
2131 gdk_x11_window_get_type_hint (GdkWindow *window)
2133 GdkDisplay *display;
2134 GdkWindowTypeHint type;
2137 gulong nitems_return;
2138 gulong bytes_after_return;
2139 guchar *data = NULL;
2141 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2143 if (GDK_WINDOW_DESTROYED (window) ||
2144 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2145 return GDK_WINDOW_TYPE_HINT_NORMAL;
2147 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2149 display = gdk_window_get_display (window);
2151 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2152 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2153 0, G_MAXLONG, False, XA_ATOM, &type_return,
2154 &format_return, &nitems_return, &bytes_after_return,
2157 if ((type_return == XA_ATOM) && (format_return == 32) &&
2158 (data) && (nitems_return == 1))
2160 Atom atom = *(Atom*)data;
2162 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2163 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2164 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2165 type = GDK_WINDOW_TYPE_HINT_MENU;
2166 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2167 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2168 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2169 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2170 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2171 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2172 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2173 type = GDK_WINDOW_TYPE_HINT_DOCK;
2174 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2175 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2176 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2177 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2178 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2179 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2180 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2181 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2182 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2183 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2184 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2185 type = GDK_WINDOW_TYPE_HINT_COMBO;
2186 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2187 type = GDK_WINDOW_TYPE_HINT_DND;
2190 if (type_return != None && data != NULL)
2198 gdk_wmspec_change_state (gboolean add,
2203 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2204 XClientMessageEvent xclient;
2206 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2207 #define _NET_WM_STATE_ADD 1 /* add/set property */
2208 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2210 memset (&xclient, 0, sizeof (xclient));
2211 xclient.type = ClientMessage;
2212 xclient.window = GDK_WINDOW_XID (window);
2213 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2214 xclient.format = 32;
2215 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2216 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2217 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2218 xclient.data.l[3] = 1; /* source indication */
2219 xclient.data.l[4] = 0;
2221 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2222 SubstructureRedirectMask | SubstructureNotifyMask,
2223 (XEvent *)&xclient);
2227 gdk_x11_window_set_modal_hint (GdkWindow *window,
2230 if (GDK_WINDOW_DESTROYED (window) ||
2231 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2234 window->modal_hint = modal;
2236 if (GDK_WINDOW_IS_MAPPED (window))
2237 gdk_wmspec_change_state (modal, window,
2238 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2243 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2244 gboolean skips_taskbar)
2246 GdkToplevelX11 *toplevel;
2248 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2250 if (GDK_WINDOW_DESTROYED (window) ||
2251 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2254 toplevel = _gdk_x11_window_get_toplevel (window);
2255 toplevel->skip_taskbar_hint = skips_taskbar;
2257 if (GDK_WINDOW_IS_MAPPED (window))
2258 gdk_wmspec_change_state (skips_taskbar, window,
2259 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2264 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2265 gboolean skips_pager)
2267 GdkToplevelX11 *toplevel;
2269 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2271 if (GDK_WINDOW_DESTROYED (window) ||
2272 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2275 toplevel = _gdk_x11_window_get_toplevel (window);
2276 toplevel->skip_pager_hint = skips_pager;
2278 if (GDK_WINDOW_IS_MAPPED (window))
2279 gdk_wmspec_change_state (skips_pager, window,
2280 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2285 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2288 GdkToplevelX11 *toplevel;
2290 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2292 if (GDK_WINDOW_DESTROYED (window) ||
2293 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2296 toplevel = _gdk_x11_window_get_toplevel (window);
2297 toplevel->urgency_hint = urgent;
2299 update_wm_hints (window, FALSE);
2303 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2304 const GdkGeometry *geometry,
2305 GdkWindowHints geom_mask)
2307 XSizeHints size_hints;
2309 if (GDK_WINDOW_DESTROYED (window) ||
2310 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2313 size_hints.flags = 0;
2315 if (geom_mask & GDK_HINT_POS)
2317 size_hints.flags |= PPosition;
2318 /* We need to initialize the following obsolete fields because KWM
2319 * apparently uses these fields if they are non-zero.
2326 if (geom_mask & GDK_HINT_USER_POS)
2328 size_hints.flags |= USPosition;
2331 if (geom_mask & GDK_HINT_USER_SIZE)
2333 size_hints.flags |= USSize;
2336 if (geom_mask & GDK_HINT_MIN_SIZE)
2338 size_hints.flags |= PMinSize;
2339 size_hints.min_width = geometry->min_width;
2340 size_hints.min_height = geometry->min_height;
2343 if (geom_mask & GDK_HINT_MAX_SIZE)
2345 size_hints.flags |= PMaxSize;
2346 size_hints.max_width = MAX (geometry->max_width, 1);
2347 size_hints.max_height = MAX (geometry->max_height, 1);
2350 if (geom_mask & GDK_HINT_BASE_SIZE)
2352 size_hints.flags |= PBaseSize;
2353 size_hints.base_width = geometry->base_width;
2354 size_hints.base_height = geometry->base_height;
2357 if (geom_mask & GDK_HINT_RESIZE_INC)
2359 size_hints.flags |= PResizeInc;
2360 size_hints.width_inc = geometry->width_inc;
2361 size_hints.height_inc = geometry->height_inc;
2364 if (geom_mask & GDK_HINT_ASPECT)
2366 size_hints.flags |= PAspect;
2367 if (geometry->min_aspect <= 1)
2369 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2370 size_hints.min_aspect.y = 65536;
2374 size_hints.min_aspect.x = 65536;
2375 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2377 if (geometry->max_aspect <= 1)
2379 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2380 size_hints.max_aspect.y = 65536;
2384 size_hints.max_aspect.x = 65536;
2385 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2389 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2391 size_hints.flags |= PWinGravity;
2392 size_hints.win_gravity = geometry->win_gravity;
2395 /* FIXME: Would it be better to delete this property if
2396 * geom_mask == 0? It would save space on the server
2398 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2399 GDK_WINDOW_XID (window),
2404 gdk_window_get_geometry_hints (GdkWindow *window,
2405 GdkGeometry *geometry,
2406 GdkWindowHints *geom_mask)
2408 XSizeHints *size_hints;
2409 glong junk_supplied_mask = 0;
2411 g_return_if_fail (GDK_IS_WINDOW (window));
2412 g_return_if_fail (geometry != NULL);
2413 g_return_if_fail (geom_mask != NULL);
2417 if (GDK_WINDOW_DESTROYED (window) ||
2418 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2421 size_hints = XAllocSizeHints ();
2425 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2426 GDK_WINDOW_XID (window),
2428 &junk_supplied_mask))
2429 size_hints->flags = 0;
2431 if (size_hints->flags & PMinSize)
2433 *geom_mask |= GDK_HINT_MIN_SIZE;
2434 geometry->min_width = size_hints->min_width;
2435 geometry->min_height = size_hints->min_height;
2438 if (size_hints->flags & PMaxSize)
2440 *geom_mask |= GDK_HINT_MAX_SIZE;
2441 geometry->max_width = MAX (size_hints->max_width, 1);
2442 geometry->max_height = MAX (size_hints->max_height, 1);
2445 if (size_hints->flags & PResizeInc)
2447 *geom_mask |= GDK_HINT_RESIZE_INC;
2448 geometry->width_inc = size_hints->width_inc;
2449 geometry->height_inc = size_hints->height_inc;
2452 if (size_hints->flags & PAspect)
2454 *geom_mask |= GDK_HINT_ASPECT;
2456 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2457 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2460 if (size_hints->flags & PWinGravity)
2462 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2463 geometry->win_gravity = size_hints->win_gravity;
2470 utf8_is_latin1 (const gchar *str)
2472 const char *p = str;
2476 gunichar ch = g_utf8_get_char (p);
2481 p = g_utf8_next_char (p);
2487 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2488 * convertable to STRING, otherwise, set it as compound text
2491 set_text_property (GdkDisplay *display,
2494 const gchar *utf8_str)
2496 gchar *prop_text = NULL;
2500 gboolean is_compound_text;
2502 if (utf8_is_latin1 (utf8_str))
2504 prop_type = XA_STRING;
2505 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2506 prop_length = prop_text ? strlen (prop_text) : 0;
2508 is_compound_text = FALSE;
2514 gdk_x11_display_utf8_to_compound_text (display,
2515 utf8_str, &gdk_type, &prop_format,
2516 (guchar **)&prop_text, &prop_length);
2517 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2518 is_compound_text = TRUE;
2523 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2526 prop_type, prop_format,
2527 PropModeReplace, (guchar *)prop_text,
2530 if (is_compound_text)
2531 gdk_x11_free_compound_text ((guchar *)prop_text);
2537 /* Set WM_NAME and _NET_WM_NAME
2540 set_wm_name (GdkDisplay *display,
2544 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2545 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2546 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2547 PropModeReplace, (guchar *)name, strlen (name));
2549 set_text_property (display, xwindow,
2550 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2555 gdk_x11_window_set_title (GdkWindow *window,
2558 GdkDisplay *display;
2562 g_return_if_fail (title != NULL);
2564 if (GDK_WINDOW_DESTROYED (window) ||
2565 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2568 display = gdk_window_get_display (window);
2569 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2570 xwindow = GDK_WINDOW_XID (window);
2572 set_wm_name (display, xwindow, title);
2574 if (!gdk_window_icon_name_set (window))
2576 XChangeProperty (xdisplay, xwindow,
2577 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2578 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2579 PropModeReplace, (guchar *)title, strlen (title));
2581 set_text_property (display, xwindow,
2582 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2588 gdk_x11_window_set_role (GdkWindow *window,
2591 GdkDisplay *display;
2593 display = gdk_window_get_display (window);
2595 if (GDK_WINDOW_DESTROYED (window) ||
2596 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2600 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2601 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2602 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2604 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2605 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2609 gdk_x11_window_set_startup_id (GdkWindow *window,
2610 const gchar *startup_id)
2612 GdkDisplay *display;
2614 g_return_if_fail (GDK_IS_WINDOW (window));
2616 display = gdk_window_get_display (window);
2618 if (GDK_WINDOW_DESTROYED (window) ||
2619 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2623 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2624 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2625 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2626 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2628 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2629 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2633 gdk_x11_window_set_transient_for (GdkWindow *window,
2636 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2637 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2638 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2639 GDK_WINDOW_XID (window),
2640 GDK_WINDOW_XID (parent));
2644 gdk_window_x11_set_back_color (GdkWindow *window,
2650 GdkVisual *visual = gdk_window_get_visual (window);
2652 /* I suppose we could handle these, but that'd require fiddling with
2653 * xrender formats... */
2657 switch (visual->type)
2659 case GDK_VISUAL_DIRECT_COLOR:
2660 case GDK_VISUAL_TRUE_COLOR:
2662 /* If bits not used for color are used for something other than padding,
2663 * it's likely alpha, so we set them to 1s.
2665 guint padding, pixel;
2667 /* Shifting by >= width-of-type isn't defined in C */
2668 if (visual->depth >= 32)
2671 padding = ((~(guint32)0)) << visual->depth;
2673 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2675 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2676 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2677 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2679 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2680 GDK_WINDOW_XID (window), pixel);
2684 /* These require fiddling with the colormap, and as they're essentially unused
2685 * we're just gonna skip them for now.
2687 case GDK_VISUAL_PSEUDO_COLOR:
2688 case GDK_VISUAL_GRAYSCALE:
2689 case GDK_VISUAL_STATIC_GRAY:
2690 case GDK_VISUAL_STATIC_COLOR:
2699 matrix_is_identity (cairo_matrix_t *matrix)
2701 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2702 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2703 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2707 gdk_window_x11_set_background (GdkWindow *window,
2708 cairo_pattern_t *pattern)
2711 cairo_surface_t *surface;
2712 cairo_matrix_t matrix;
2714 if (GDK_WINDOW_DESTROYED (window))
2717 if (pattern == NULL)
2721 /* X throws BadMatch if the parent has a different visual when
2722 * using ParentRelative */
2723 parent = gdk_window_get_parent (window);
2724 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2725 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2726 GDK_WINDOW_XID (window), ParentRelative);
2728 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2729 GDK_WINDOW_XID (window), None);
2733 switch (cairo_pattern_get_type (pattern))
2735 case CAIRO_PATTERN_TYPE_SOLID:
2736 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2737 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2740 case CAIRO_PATTERN_TYPE_SURFACE:
2741 cairo_pattern_get_matrix (pattern, &matrix);
2742 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2743 matrix_is_identity (&matrix) &&
2744 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2745 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2746 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2750 cairo_surface_get_device_offset (surface, &x, &y);
2751 /* XXX: This still bombs for non-pixmaps, but there's no way to
2752 * detect we're not a pixmap in Cairo... */
2753 if (x == 0.0 && y == 0.0)
2755 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2756 GDK_WINDOW_XID (window),
2757 cairo_xlib_surface_get_drawable (surface));
2762 case CAIRO_PATTERN_TYPE_LINEAR:
2763 case CAIRO_PATTERN_TYPE_RADIAL:
2765 /* fallback: just use black */
2769 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2770 GDK_WINDOW_XID (window), None);
2774 gdk_window_x11_set_device_cursor (GdkWindow *window,
2778 GdkWindowImplX11 *impl;
2780 g_return_if_fail (GDK_IS_WINDOW (window));
2781 g_return_if_fail (GDK_IS_DEVICE (device));
2783 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2786 g_hash_table_remove (impl->device_cursor, device);
2789 _gdk_x11_cursor_update_theme (cursor);
2790 g_hash_table_replace (impl->device_cursor,
2791 device, g_object_ref (cursor));
2794 if (!GDK_WINDOW_DESTROYED (window))
2795 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2799 _gdk_x11_window_get_cursor (GdkWindow *window)
2801 GdkWindowImplX11 *impl;
2803 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2805 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2807 return impl->cursor;
2811 gdk_window_x11_get_geometry (GdkWindow *window,
2822 guint tborder_width;
2825 if (!GDK_WINDOW_DESTROYED (window))
2827 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2828 GDK_WINDOW_XID (window),
2829 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2843 gdk_window_x11_get_root_coords (GdkWindow *window,
2854 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2855 GDK_WINDOW_XID (window),
2856 GDK_WINDOW_XROOTWIN (window),
2869 gdk_x11_window_get_root_origin (GdkWindow *window,
2875 gdk_window_get_frame_extents (window, &rect);
2885 gdk_x11_window_get_frame_extents (GdkWindow *window,
2888 GdkDisplay *display;
2889 GdkWindowImplX11 *impl;
2900 gulong nitems_return;
2901 gulong bytes_after_return;
2904 guint ww, wh, wb, wd;
2906 gboolean got_frame_extents = FALSE;
2908 g_return_if_fail (rect != NULL);
2915 while (window->parent && (window->parent)->parent)
2916 window = window->parent;
2918 /* Refine our fallback answer a bit using local information */
2919 rect->x = window->x;
2920 rect->y = window->y;
2921 rect->width = window->width;
2922 rect->height = window->height;
2924 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2925 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2931 display = gdk_window_get_display (window);
2933 gdk_x11_display_error_trap_push (display);
2935 xwindow = GDK_WINDOW_XID (window);
2937 /* first try: use _NET_FRAME_EXTENTS */
2938 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2939 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
2940 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2941 gdk_x11_get_xatom_by_name_for_display (display,
2942 "_NET_FRAME_EXTENTS"),
2943 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2944 &format_return, &nitems_return, &bytes_after_return,
2948 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2949 (nitems_return == 4) && (data))
2951 gulong *ldata = (gulong *) data;
2952 got_frame_extents = TRUE;
2954 /* try to get the real client window geometry */
2955 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2956 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2957 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2958 xwindow, root, 0, 0, &wx, &wy, &child))
2966 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2967 rect->x -= ldata[0];
2968 rect->y -= ldata[2];
2969 rect->width += ldata[0] + ldata[1];
2970 rect->height += ldata[2] + ldata[3];
2977 if (got_frame_extents)
2980 /* no frame extents property available, which means we either have a WM that
2981 is not EWMH compliant or is broken - try fallback and walk up the window
2982 tree to get our window's parent which hopefully is the window frame */
2984 /* use NETWM_VIRTUAL_ROOTS if available */
2985 root = GDK_WINDOW_XROOTWIN (window);
2987 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2988 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
2989 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
2990 gdk_x11_get_xatom_by_name_for_display (display,
2991 "_NET_VIRTUAL_ROOTS"),
2992 0, G_MAXLONG, False, XA_WINDOW, &type_return,
2993 &format_return, &nitems_return, &bytes_after_return,
2997 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
2999 nvroots = nitems_return;
3000 vroots = (Window *)data;
3004 xparent = GDK_WINDOW_XID (window);
3010 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3012 &children, &nchildren))
3018 /* check virtual roots */
3019 for (i = 0; i < nvroots; i++)
3021 if (xparent == vroots[i])
3028 while (xparent != root);
3030 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3031 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3043 gdk_x11_display_error_trap_pop_ignored (display);
3047 gdk_window_x11_get_device_state (GdkWindow *window,
3051 GdkModifierType *mask)
3055 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3057 if (GDK_WINDOW_DESTROYED (window))
3060 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3064 return child != NULL;
3068 gdk_window_x11_get_events (GdkWindow *window)
3070 XWindowAttributes attrs;
3071 GdkEventMask event_mask;
3072 GdkEventMask filtered;
3074 if (GDK_WINDOW_DESTROYED (window))
3078 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3079 GDK_WINDOW_XID (window),
3081 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3082 /* if property change was filtered out before, keep it filtered out */
3083 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3084 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3090 gdk_window_x11_set_events (GdkWindow *window,
3091 GdkEventMask event_mask)
3093 long xevent_mask = 0;
3095 if (!GDK_WINDOW_DESTROYED (window))
3097 GdkX11Display *display_x11;
3099 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3100 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3102 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3103 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3104 GDK_WINDOW_XID (window), event_mask,
3110 do_shape_combine_region (GdkWindow *window,
3111 const cairo_region_t *shape_region,
3116 if (GDK_WINDOW_DESTROYED (window))
3119 if (shape_region == NULL)
3121 /* Use NULL mask to unset the shape */
3122 if (shape == ShapeBounding
3123 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3124 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3126 if (shape == ShapeBounding)
3128 _gdk_x11_window_tmp_unset_parent_bg (window);
3129 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3131 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3132 GDK_WINDOW_XID (window),
3137 if (shape == ShapeBounding)
3139 _gdk_x11_window_tmp_reset_parent_bg (window);
3140 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3146 if (shape == ShapeBounding
3147 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3148 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3151 XRectangle *xrects = NULL;
3153 _gdk_x11_region_get_xrectangles (shape_region,
3157 if (shape == ShapeBounding)
3159 _gdk_x11_window_tmp_unset_parent_bg (window);
3160 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3162 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3163 GDK_WINDOW_XID (window),
3170 if (shape == ShapeBounding)
3172 _gdk_x11_window_tmp_reset_parent_bg (window);
3173 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3181 gdk_window_x11_shape_combine_region (GdkWindow *window,
3182 const cairo_region_t *shape_region,
3186 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3190 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3191 const cairo_region_t *shape_region,
3196 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3202 gdk_x11_window_set_override_redirect (GdkWindow *window,
3203 gboolean override_redirect)
3205 XSetWindowAttributes attr;
3207 if (!GDK_WINDOW_DESTROYED (window) &&
3208 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3210 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3212 attr.override_redirect = (override_redirect? True : False);
3213 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3214 GDK_WINDOW_XID (window),
3218 impl->override_redirect = attr.override_redirect;
3223 gdk_x11_window_set_accept_focus (GdkWindow *window,
3224 gboolean accept_focus)
3226 accept_focus = accept_focus != FALSE;
3228 if (window->accept_focus != accept_focus)
3230 window->accept_focus = accept_focus;
3232 if (!GDK_WINDOW_DESTROYED (window) &&
3233 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3234 update_wm_hints (window, FALSE);
3239 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3240 gboolean focus_on_map)
3242 focus_on_map = focus_on_map != FALSE;
3244 if (window->focus_on_map != focus_on_map)
3246 window->focus_on_map = focus_on_map;
3248 if ((!GDK_WINDOW_DESTROYED (window)) &&
3249 (!window->focus_on_map) &&
3250 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3251 gdk_x11_window_set_user_time (window, 0);
3256 * gdk_x11_window_set_user_time:
3257 * @window: (type GdkX11Window): A toplevel #GdkWindow
3258 * @timestamp: An XServer timestamp to which the property should be set
3260 * The application can use this call to update the _NET_WM_USER_TIME
3261 * property on a toplevel window. This property stores an Xserver
3262 * time which represents the time of the last user input event
3263 * received for this window. This property may be used by the window
3264 * manager to alter the focus, stacking, and/or placement behavior of
3265 * windows when they are mapped depending on whether the new window
3266 * was created by a user action or is a "pop-up" window activated by a
3267 * timer or some other event.
3269 * Note that this property is automatically updated by GDK, so this
3270 * function should only be used by applications which handle input
3271 * events bypassing GDK.
3276 gdk_x11_window_set_user_time (GdkWindow *window,
3279 GdkDisplay *display;
3280 GdkX11Display *display_x11;
3281 GdkToplevelX11 *toplevel;
3282 glong timestamp_long = (glong)timestamp;
3285 if (GDK_WINDOW_DESTROYED (window) ||
3286 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3289 display = gdk_window_get_display (window);
3290 display_x11 = GDK_X11_DISPLAY (display);
3291 toplevel = _gdk_x11_window_get_toplevel (window);
3295 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3299 if (toplevel->focus_window != None &&
3300 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3301 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3302 xid = toplevel->focus_window;
3304 xid = GDK_WINDOW_XID (window);
3306 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3307 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3308 XA_CARDINAL, 32, PropModeReplace,
3309 (guchar *)×tamp_long, 1);
3311 if (timestamp_long != GDK_CURRENT_TIME &&
3312 (display_x11->user_time == GDK_CURRENT_TIME ||
3313 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3314 display_x11->user_time = timestamp_long;
3317 toplevel->user_time = timestamp_long;
3321 * gdk_x11_window_set_utf8_property:
3322 * @window: (type GdkX11Window): a #GdkWindow
3323 * @name: Property name, will be interned as an X atom
3324 * @value: (allow-none): Property value, or %NULL to delete
3326 * This function modifies or removes an arbitrary X11 window
3327 * property of type UTF8_STRING. If the given @window is
3328 * not a toplevel window, it is ignored.
3333 gdk_x11_window_set_utf8_property (GdkWindow *window,
3337 GdkDisplay *display;
3339 if (!WINDOW_IS_TOPLEVEL (window))
3342 display = gdk_window_get_display (window);
3346 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3347 GDK_WINDOW_XID (window),
3348 gdk_x11_get_xatom_by_name_for_display (display, name),
3349 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3350 PropModeReplace, (guchar *)value, strlen (value));
3354 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3355 GDK_WINDOW_XID (window),
3356 gdk_x11_get_xatom_by_name_for_display (display, name));
3361 * gdk_x11_window_set_hide_titlebar_when_maximized:
3362 * @window: (type GdkX11Window): a #GdkWindow
3363 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3366 * Set a hint for the window manager, requesting that the titlebar
3367 * should be hidden when the window is maximized.
3369 * Note that this property is automatically updated by GTK+, so this
3370 * function should only be used by applications which do not use GTK+
3371 * to create toplevel windows.
3376 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3377 gboolean hide_titlebar_when_maximized)
3379 GdkDisplay *display;
3381 if (!WINDOW_IS_TOPLEVEL (window))
3384 display = gdk_window_get_display (window);
3386 if (hide_titlebar_when_maximized)
3389 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3390 GDK_WINDOW_XID (window),
3391 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3393 PropModeReplace, (guchar *)&hide, 1);
3397 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3398 GDK_WINDOW_XID (window),
3399 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3404 * gdk_x11_window_set_theme_variant:
3405 * @window: (type GdkX11Window): a #GdkWindow
3406 * @variant: the theme variant to export
3408 * GTK+ applications can request a dark theme variant. In order to
3409 * make other applications - namely window managers using GTK+ for
3410 * themeing - aware of this choice, GTK+ uses this function to
3411 * export the requested theme variant as _GTK_THEME_VARIANT property
3412 * on toplevel windows.
3414 * Note that this property is automatically updated by GTK+, so this
3415 * function should only be used by applications which do not use GTK+
3416 * to create toplevel windows.
3421 gdk_x11_window_set_theme_variant (GdkWindow *window,
3424 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3427 #define GDK_SELECTION_MAX_SIZE(display) \
3429 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3430 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3431 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3434 gdk_window_update_icon (GdkWindow *window,
3437 GdkToplevelX11 *toplevel;
3438 GdkPixbuf *best_icon;
3442 toplevel = _gdk_x11_window_get_toplevel (window);
3444 if (toplevel->icon_pixmap != NULL)
3446 cairo_surface_destroy (toplevel->icon_pixmap);
3447 toplevel->icon_pixmap = NULL;
3450 if (toplevel->icon_mask != NULL)
3452 cairo_surface_destroy (toplevel->icon_mask);
3453 toplevel->icon_mask = NULL;
3456 #define IDEAL_SIZE 48
3458 best_size = G_MAXINT;
3460 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3462 GdkPixbuf *pixbuf = tmp_list->data;
3465 /* average width and height - if someone passes in a rectangular
3466 * icon they deserve what they get.
3468 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3471 if (best_icon == NULL)
3478 /* icon is better if it's 32 pixels or larger, and closer to
3479 * the ideal size than the current best.
3482 (ABS (best_size - IDEAL_SIZE) <
3483 ABS (this - IDEAL_SIZE)))
3493 int width = gdk_pixbuf_get_width (best_icon);
3494 int height = gdk_pixbuf_get_height (best_icon);
3497 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3501 cr = cairo_create (toplevel->icon_pixmap);
3502 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3503 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3504 if (gdk_pixbuf_get_has_alpha (best_icon))
3506 /* Saturate the image, so it has bilevel alpha */
3507 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3509 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3511 cairo_pop_group_to_source (cr);
3516 if (gdk_pixbuf_get_has_alpha (best_icon))
3518 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3522 cr = cairo_create (toplevel->icon_mask);
3523 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3524 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3530 update_wm_hints (window, FALSE);
3534 gdk_x11_window_set_icon_list (GdkWindow *window,
3543 gint width, height, stride;
3546 GdkDisplay *display;
3549 if (GDK_WINDOW_DESTROYED (window) ||
3550 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3553 display = gdk_window_get_display (window);
3561 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3563 width = gdk_pixbuf_get_width (pixbuf);
3564 height = gdk_pixbuf_get_height (pixbuf);
3566 /* silently ignore overlarge icons */
3567 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3569 g_warning ("gdk_window_set_icon_list: icons too large");
3574 size += 2 + width * height;
3576 l = g_list_next (l);
3579 data = g_malloc (size * sizeof (gulong));
3587 width = gdk_pixbuf_get_width (pixbuf);
3588 height = gdk_pixbuf_get_height (pixbuf);
3589 stride = gdk_pixbuf_get_rowstride (pixbuf);
3590 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3595 pixels = gdk_pixbuf_get_pixels (pixbuf);
3597 for (y = 0; y < height; y++)
3599 for (x = 0; x < width; x++)
3603 r = pixels[y*stride + x*n_channels + 0];
3604 g = pixels[y*stride + x*n_channels + 1];
3605 b = pixels[y*stride + x*n_channels + 2];
3606 if (n_channels >= 4)
3607 a = pixels[y*stride + x*n_channels + 3];
3611 *p++ = a << 24 | r << 16 | g << 8 | b ;
3615 l = g_list_next (l);
3621 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3622 GDK_WINDOW_XID (window),
3623 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3626 (guchar*) data, size);
3630 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3631 GDK_WINDOW_XID (window),
3632 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3637 gdk_window_update_icon (window, pixbufs);
3641 gdk_window_icon_name_set (GdkWindow *window)
3643 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3644 g_quark_from_static_string ("gdk-icon-name-set")));
3648 gdk_x11_window_set_icon_name (GdkWindow *window,
3651 GdkDisplay *display;
3653 if (GDK_WINDOW_DESTROYED (window) ||
3654 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3657 display = gdk_window_get_display (window);
3659 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3660 GUINT_TO_POINTER (name != NULL));
3664 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3665 GDK_WINDOW_XID (window),
3666 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3667 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3668 PropModeReplace, (guchar *)name, strlen (name));
3670 set_text_property (display, GDK_WINDOW_XID (window),
3671 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3676 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3677 GDK_WINDOW_XID (window),
3678 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3679 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3680 GDK_WINDOW_XID (window),
3681 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3686 gdk_x11_window_iconify (GdkWindow *window)
3688 if (GDK_WINDOW_DESTROYED (window) ||
3689 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3692 if (GDK_WINDOW_IS_MAPPED (window))
3694 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3695 GDK_WINDOW_XID (window),
3696 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3700 /* Flip our client side flag, the real work happens on map. */
3701 gdk_synthesize_window_state (window,
3703 GDK_WINDOW_STATE_ICONIFIED);
3704 gdk_wmspec_change_state (TRUE, window,
3705 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3711 gdk_x11_window_deiconify (GdkWindow *window)
3713 if (GDK_WINDOW_DESTROYED (window) ||
3714 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3717 if (GDK_WINDOW_IS_MAPPED (window))
3719 gdk_window_show (window);
3720 gdk_wmspec_change_state (FALSE, window,
3721 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3726 /* Flip our client side flag, the real work happens on map. */
3727 gdk_synthesize_window_state (window,
3728 GDK_WINDOW_STATE_ICONIFIED,
3730 gdk_wmspec_change_state (FALSE, window,
3731 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3737 gdk_x11_window_stick (GdkWindow *window)
3739 if (GDK_WINDOW_DESTROYED (window) ||
3740 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3743 if (GDK_WINDOW_IS_MAPPED (window))
3745 /* "stick" means stick to all desktops _and_ do not scroll with the
3746 * viewport. i.e. glue to the monitor glass in all cases.
3749 XClientMessageEvent xclient;
3751 /* Request stick during viewport scroll */
3752 gdk_wmspec_change_state (TRUE, window,
3753 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3756 /* Request desktop 0xFFFFFFFF */
3757 memset (&xclient, 0, sizeof (xclient));
3758 xclient.type = ClientMessage;
3759 xclient.window = GDK_WINDOW_XID (window);
3760 xclient.display = GDK_WINDOW_XDISPLAY (window);
3761 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3763 xclient.format = 32;
3765 xclient.data.l[0] = 0xFFFFFFFF;
3766 xclient.data.l[1] = 0;
3767 xclient.data.l[2] = 0;
3768 xclient.data.l[3] = 0;
3769 xclient.data.l[4] = 0;
3771 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3772 SubstructureRedirectMask | SubstructureNotifyMask,
3773 (XEvent *)&xclient);
3777 /* Flip our client side flag, the real work happens on map. */
3778 gdk_synthesize_window_state (window,
3780 GDK_WINDOW_STATE_STICKY);
3785 gdk_x11_window_unstick (GdkWindow *window)
3787 if (GDK_WINDOW_DESTROYED (window) ||
3788 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3791 if (GDK_WINDOW_IS_MAPPED (window))
3793 /* Request unstick from viewport */
3794 gdk_wmspec_change_state (FALSE, window,
3795 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3798 move_to_current_desktop (window);
3802 /* Flip our client side flag, the real work happens on map. */
3803 gdk_synthesize_window_state (window,
3804 GDK_WINDOW_STATE_STICKY,
3811 gdk_x11_window_maximize (GdkWindow *window)
3813 if (GDK_WINDOW_DESTROYED (window) ||
3814 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3817 if (GDK_WINDOW_IS_MAPPED (window))
3818 gdk_wmspec_change_state (TRUE, window,
3819 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3820 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3822 gdk_synthesize_window_state (window,
3824 GDK_WINDOW_STATE_MAXIMIZED);
3828 gdk_x11_window_unmaximize (GdkWindow *window)
3830 if (GDK_WINDOW_DESTROYED (window) ||
3831 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3834 if (GDK_WINDOW_IS_MAPPED (window))
3835 gdk_wmspec_change_state (FALSE, window,
3836 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3837 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3839 gdk_synthesize_window_state (window,
3840 GDK_WINDOW_STATE_MAXIMIZED,
3845 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3847 if (GDK_WINDOW_DESTROYED (window) ||
3848 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3851 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3852 * to which monitors so span across when the window is fullscreen, but it's
3853 * not a state in itself so this would have no effect if the window is not
3857 if (GDK_WINDOW_IS_MAPPED (window))
3859 XClientMessageEvent xclient;
3860 gint gdk_monitors[4];
3863 memset (&xclient, 0, sizeof (xclient));
3864 xclient.type = ClientMessage;
3865 xclient.window = GDK_WINDOW_XID (window);
3866 xclient.display = GDK_WINDOW_XDISPLAY (window);
3867 xclient.format = 32;
3869 switch (window->fullscreen_mode)
3871 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3873 /* FIXME: This is not part of the EWMH spec!
3875 * There is no documented mechanism to remove the property
3876 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3877 * invalid, largest possible value.
3879 * When given values larger than actual possible monitor values, most
3880 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3881 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3884 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3886 * Note, this (non documented) mechanism is unlikely to be an issue
3887 * as it's used only for transitionning back from "all monitors" to
3888 * "current monitor" mode.
3890 * Applications who don't change the default mode won't trigger this
3893 for (i = 0; i < 4; ++i)
3894 xclient.data.l[i] = G_MAXLONG;
3898 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3900 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3905 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3906 for (i = 0; i < 4; ++i)
3908 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3910 /* Sanity check, if XINERAMA is not available, we could have invalid
3911 * negative values for the XINERAMA indices.
3913 if (xclient.data.l[i] < 0)
3915 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3922 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3923 window->fullscreen_mode);
3927 /* Send fullscreen monitors client message */
3928 xclient.data.l[4] = 1; /* source indication */
3929 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3930 "_NET_WM_FULLSCREEN_MONITORS");
3931 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3932 SubstructureRedirectMask | SubstructureNotifyMask,
3933 (XEvent *)&xclient);
3938 gdk_x11_window_fullscreen (GdkWindow *window)
3940 if (GDK_WINDOW_DESTROYED (window) ||
3941 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3944 if (GDK_WINDOW_IS_MAPPED (window))
3946 gdk_wmspec_change_state (TRUE, window,
3947 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3949 /* Actual XRandR layout may have change since we computed the fullscreen
3950 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
3952 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
3953 gdk_x11_window_apply_fullscreen_mode (window);
3956 gdk_synthesize_window_state (window,
3958 GDK_WINDOW_STATE_FULLSCREEN);
3962 gdk_x11_window_unfullscreen (GdkWindow *window)
3964 if (GDK_WINDOW_DESTROYED (window) ||
3965 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3968 if (GDK_WINDOW_IS_MAPPED (window))
3969 gdk_wmspec_change_state (FALSE, window,
3970 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3974 gdk_synthesize_window_state (window,
3975 GDK_WINDOW_STATE_FULLSCREEN,
3980 gdk_x11_window_set_keep_above (GdkWindow *window,
3983 g_return_if_fail (GDK_IS_WINDOW (window));
3985 if (GDK_WINDOW_DESTROYED (window) ||
3986 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3989 if (GDK_WINDOW_IS_MAPPED (window))
3992 gdk_wmspec_change_state (FALSE, window,
3993 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3995 gdk_wmspec_change_state (setting, window,
3996 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4000 gdk_synthesize_window_state (window,
4001 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4002 setting ? GDK_WINDOW_STATE_ABOVE : 0);
4006 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
4008 g_return_if_fail (GDK_IS_WINDOW (window));
4010 if (GDK_WINDOW_DESTROYED (window) ||
4011 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4014 if (GDK_WINDOW_IS_MAPPED (window))
4017 gdk_wmspec_change_state (FALSE, window,
4018 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4020 gdk_wmspec_change_state (setting, window,
4021 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4025 gdk_synthesize_window_state (window,
4026 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4027 setting ? GDK_WINDOW_STATE_BELOW : 0);
4031 gdk_x11_window_get_group (GdkWindow *window)
4033 GdkToplevelX11 *toplevel;
4035 if (GDK_WINDOW_DESTROYED (window) ||
4036 !WINDOW_IS_TOPLEVEL (window))
4039 toplevel = _gdk_x11_window_get_toplevel (window);
4041 return toplevel->group_leader;
4045 gdk_x11_window_set_group (GdkWindow *window,
4048 GdkToplevelX11 *toplevel;
4050 g_return_if_fail (GDK_IS_WINDOW (window));
4051 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4052 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4054 if (GDK_WINDOW_DESTROYED (window) ||
4055 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4056 !WINDOW_IS_TOPLEVEL (window))
4059 toplevel = _gdk_x11_window_get_toplevel (window);
4062 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4064 if (toplevel->group_leader != leader)
4066 if (toplevel->group_leader)
4067 g_object_unref (toplevel->group_leader);
4068 toplevel->group_leader = g_object_ref (leader);
4069 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4072 update_wm_hints (window, FALSE);
4075 static MotifWmHints *
4076 gdk_window_get_mwm_hints (GdkWindow *window)
4078 GdkDisplay *display;
4079 Atom hints_atom = None;
4086 if (GDK_WINDOW_DESTROYED (window))
4089 display = gdk_window_get_display (window);
4091 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4093 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4094 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4095 False, AnyPropertyType, &type, &format, &nitems,
4096 &bytes_after, &data);
4101 return (MotifWmHints *)data;
4105 gdk_window_set_mwm_hints (GdkWindow *window,
4106 MotifWmHints *new_hints)
4108 GdkDisplay *display;
4109 Atom hints_atom = None;
4111 MotifWmHints *hints;
4117 if (GDK_WINDOW_DESTROYED (window))
4120 display = gdk_window_get_display (window);
4122 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4124 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4125 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4126 False, AnyPropertyType, &type, &format, &nitems,
4127 &bytes_after, &data);
4133 hints = (MotifWmHints *)data;
4135 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4137 hints->flags |= MWM_HINTS_FUNCTIONS;
4138 hints->functions = new_hints->functions;
4140 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4142 hints->flags |= MWM_HINTS_DECORATIONS;
4143 hints->decorations = new_hints->decorations;
4147 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4148 hints_atom, hints_atom, 32, PropModeReplace,
4149 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4151 if (hints != new_hints)
4156 gdk_x11_window_set_decorations (GdkWindow *window,
4157 GdkWMDecoration decorations)
4161 if (GDK_WINDOW_DESTROYED (window) ||
4162 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4165 /* initialize to zero to avoid writing uninitialized data to socket */
4166 memset(&hints, 0, sizeof(hints));
4167 hints.flags = MWM_HINTS_DECORATIONS;
4168 hints.decorations = decorations;
4170 gdk_window_set_mwm_hints (window, &hints);
4174 gdk_x11_window_get_decorations(GdkWindow *window,
4175 GdkWMDecoration *decorations)
4177 MotifWmHints *hints;
4178 gboolean result = FALSE;
4180 if (GDK_WINDOW_DESTROYED (window) ||
4181 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4184 hints = gdk_window_get_mwm_hints (window);
4188 if (hints->flags & MWM_HINTS_DECORATIONS)
4191 *decorations = hints->decorations;
4202 gdk_x11_window_set_functions (GdkWindow *window,
4203 GdkWMFunction functions)
4207 g_return_if_fail (GDK_IS_WINDOW (window));
4209 if (GDK_WINDOW_DESTROYED (window) ||
4210 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4213 /* initialize to zero to avoid writing uninitialized data to socket */
4214 memset(&hints, 0, sizeof(hints));
4215 hints.flags = MWM_HINTS_FUNCTIONS;
4216 hints.functions = functions;
4218 gdk_window_set_mwm_hints (window, &hints);
4222 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4226 cairo_region_t *shape;
4234 /* Note that XShapeGetRectangles returns NULL in two situations:
4235 * - the server doesn't support the SHAPE extension
4236 * - the shape is empty
4238 * Since we can't discriminate these here, we always return
4239 * an empty shape. It is the callers responsibility to check
4240 * whether the server supports the SHAPE extensions beforehand.
4242 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4245 return cairo_region_create (); /* Empty */
4247 if (ord != YXBanded)
4249 /* This really shouldn't happen with any xserver, as they
4250 * generally convert regions to YXBanded internally
4252 g_warning ("non YXBanded shape masks not supported");
4257 rl = g_new (GdkRectangle, rn);
4258 for (i = 0; i < rn; i++)
4262 rl[i].width = xrl[i].width;
4263 rl[i].height = xrl[i].height;
4267 shape = cairo_region_create_rectangles (rl, rn);
4274 static cairo_region_t *
4275 gdk_x11_window_get_shape (GdkWindow *window)
4277 if (!GDK_WINDOW_DESTROYED (window) &&
4278 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4279 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4280 GDK_WINDOW_XID (window),
4286 static cairo_region_t *
4287 gdk_x11_window_get_input_shape (GdkWindow *window)
4289 #if defined(ShapeInput)
4290 if (!GDK_WINDOW_DESTROYED (window) &&
4291 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4292 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4293 GDK_WINDOW_XID (window),
4301 gdk_window_set_static_bit_gravity (GdkWindow *window,
4304 XSetWindowAttributes xattributes;
4305 guint xattributes_mask = 0;
4307 g_return_if_fail (GDK_IS_WINDOW (window));
4309 if (window->input_only)
4312 xattributes.bit_gravity = StaticGravity;
4313 xattributes_mask |= CWBitGravity;
4314 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4315 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4316 GDK_WINDOW_XID (window),
4317 CWBitGravity, &xattributes);
4321 gdk_window_set_static_win_gravity (GdkWindow *window,
4324 XSetWindowAttributes xattributes;
4326 g_return_if_fail (GDK_IS_WINDOW (window));
4328 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4330 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4331 GDK_WINDOW_XID (window),
4332 CWWinGravity, &xattributes);
4336 gdk_window_x11_set_static_gravities (GdkWindow *window,
4337 gboolean use_static)
4341 if (!use_static == !window->guffaw_gravity)
4344 window->guffaw_gravity = use_static;
4346 if (!GDK_WINDOW_DESTROYED (window))
4348 gdk_window_set_static_bit_gravity (window, use_static);
4350 tmp_list = window->children;
4353 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4355 tmp_list = tmp_list->next;
4362 /* From the WM spec */
4363 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4364 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4365 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4366 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4367 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4368 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4369 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4370 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4371 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4372 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4373 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4374 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4377 wmspec_send_message (GdkDisplay *display,
4384 XClientMessageEvent xclient;
4386 memset (&xclient, 0, sizeof (xclient));
4387 xclient.type = ClientMessage;
4388 xclient.window = GDK_WINDOW_XID (window);
4389 xclient.message_type =
4390 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4391 xclient.format = 32;
4392 xclient.data.l[0] = root_x;
4393 xclient.data.l[1] = root_y;
4394 xclient.data.l[2] = action;
4395 xclient.data.l[3] = button;
4396 xclient.data.l[4] = 1; /* source indication */
4398 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4399 SubstructureRedirectMask | SubstructureNotifyMask,
4400 (XEvent *)&xclient);
4404 handle_wmspec_button_release (GdkDisplay *display,
4407 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4410 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4411 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4412 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4414 if (xevent->xany.type == GenericEvent)
4415 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4418 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4420 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4422 if ((xevent->xany.type == ButtonRelease &&
4423 xevent->xbutton.button == display_x11->wm_moveresize_button)
4424 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4426 (xevent->xany.type == GenericEvent &&
4427 xiev->evtype == XI_ButtonRelease &&
4428 xidev->detail == display_x11->wm_moveresize_button)
4432 display_x11->wm_moveresize_button = 0;
4433 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4439 wmspec_moveresize (GdkWindow *window,
4447 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4449 /* Release passive grab */
4450 gdk_device_ungrab (device, timestamp);
4451 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4453 wmspec_send_message (display, window, root_x, root_y, direction, button);
4457 wmspec_resize_drag (GdkWindow *window,
4467 /* Let the compiler turn a switch into a table, instead
4468 * of doing the table manually, this way is easier to verify.
4472 case GDK_WINDOW_EDGE_NORTH_WEST:
4473 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4476 case GDK_WINDOW_EDGE_NORTH:
4477 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4480 case GDK_WINDOW_EDGE_NORTH_EAST:
4481 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4484 case GDK_WINDOW_EDGE_WEST:
4485 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4488 case GDK_WINDOW_EDGE_EAST:
4489 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4492 case GDK_WINDOW_EDGE_SOUTH_WEST:
4493 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4496 case GDK_WINDOW_EDGE_SOUTH:
4497 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4500 case GDK_WINDOW_EDGE_SOUTH_EAST:
4501 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4505 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4510 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4513 typedef struct _MoveResizeData MoveResizeData;
4515 struct _MoveResizeData
4517 GdkDisplay *display;
4519 GdkWindow *moveresize_window;
4520 GdkWindow *moveresize_emulation_window;
4522 GdkWindowEdge resize_edge;
4524 gint moveresize_button;
4527 gint moveresize_orig_x;
4528 gint moveresize_orig_y;
4529 gint moveresize_orig_width;
4530 gint moveresize_orig_height;
4531 GdkWindowHints moveresize_geom_mask;
4532 GdkGeometry moveresize_geometry;
4533 Time moveresize_process_time;
4534 XEvent *moveresize_pending_event;
4537 static MoveResizeData *
4538 get_move_resize_data (GdkDisplay *display,
4541 MoveResizeData *mv_resize;
4542 static GQuark move_resize_quark = 0;
4544 if (!move_resize_quark)
4545 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4547 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4549 if (!mv_resize && create)
4551 mv_resize = g_new0 (MoveResizeData, 1);
4552 mv_resize->display = display;
4554 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4561 update_pos (MoveResizeData *mv_resize,
4567 dx = new_root_x - mv_resize->moveresize_x;
4568 dy = new_root_y - mv_resize->moveresize_y;
4570 if (mv_resize->is_resize)
4574 x = mv_resize->moveresize_orig_x;
4575 y = mv_resize->moveresize_orig_y;
4577 w = mv_resize->moveresize_orig_width;
4578 h = mv_resize->moveresize_orig_height;
4580 switch (mv_resize->resize_edge)
4582 case GDK_WINDOW_EDGE_NORTH_WEST:
4588 case GDK_WINDOW_EDGE_NORTH:
4592 case GDK_WINDOW_EDGE_NORTH_EAST:
4597 case GDK_WINDOW_EDGE_SOUTH_WEST:
4602 case GDK_WINDOW_EDGE_SOUTH_EAST:
4606 case GDK_WINDOW_EDGE_SOUTH:
4609 case GDK_WINDOW_EDGE_EAST:
4612 case GDK_WINDOW_EDGE_WEST:
4623 if (mv_resize->moveresize_geom_mask)
4625 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4626 mv_resize->moveresize_geom_mask,
4630 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4636 x = mv_resize->moveresize_orig_x + dx;
4637 y = mv_resize->moveresize_orig_y + dy;
4639 gdk_window_move (mv_resize->moveresize_window, x, y);
4644 finish_drag (MoveResizeData *mv_resize)
4646 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4647 mv_resize->moveresize_emulation_window = NULL;
4648 g_object_unref (mv_resize->moveresize_window);
4649 mv_resize->moveresize_window = NULL;
4651 if (mv_resize->moveresize_pending_event)
4653 g_free (mv_resize->moveresize_pending_event);
4654 mv_resize->moveresize_pending_event = NULL;
4659 lookahead_motion_predicate (Display *xdisplay,
4663 gboolean *seen_release = (gboolean *)arg;
4664 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4665 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4670 switch (event->xany.type)
4673 *seen_release = TRUE;
4676 mv_resize->moveresize_process_time = event->xmotion.time;
4686 moveresize_lookahead (MoveResizeData *mv_resize,
4690 gboolean seen_release = FALSE;
4692 if (mv_resize->moveresize_process_time)
4694 if (event->xmotion.time == mv_resize->moveresize_process_time)
4696 mv_resize->moveresize_process_time = 0;
4703 XCheckIfEvent (event->xany.display, &tmp_event,
4704 lookahead_motion_predicate, (XPointer) & seen_release);
4706 return mv_resize->moveresize_process_time == 0;
4710 _gdk_x11_moveresize_handle_event (XEvent *event)
4712 guint button_mask = 0;
4713 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4714 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4716 if (!mv_resize || !mv_resize->moveresize_window)
4718 handle_wmspec_button_release (display, event);
4722 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4724 switch (event->xany.type)
4727 if (mv_resize->moveresize_window->resize_count > 0)
4729 if (mv_resize->moveresize_pending_event)
4730 *mv_resize->moveresize_pending_event = *event;
4732 mv_resize->moveresize_pending_event =
4733 g_memdup (event, sizeof (XEvent));
4737 if (!moveresize_lookahead (mv_resize, event))
4740 update_pos (mv_resize,
4741 event->xmotion.x_root,
4742 event->xmotion.y_root);
4744 /* This should never be triggered in normal cases, but in the
4745 * case where the drag started without an implicit grab being
4746 * in effect, we could miss the release if it occurs before
4747 * we grab the pointer; this ensures that we will never
4748 * get a permanently stuck grab.
4750 if ((event->xmotion.state & button_mask) == 0)
4751 finish_drag (mv_resize);
4755 update_pos (mv_resize,
4756 event->xbutton.x_root,
4757 event->xbutton.y_root);
4759 if (event->xbutton.button == mv_resize->moveresize_button)
4760 finish_drag (mv_resize);
4763 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4766 /* we just assume this is an XI2 event */
4767 XIEvent *ev = (XIEvent *) event->xcookie.data;
4768 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4773 update_pos (mv_resize, xev->root_x, xev->root_y);
4774 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4775 if ((state & button_mask) == 0)
4776 finish_drag (mv_resize);
4779 case XI_ButtonRelease:
4780 update_pos (mv_resize, xev->root_x, xev->root_y);
4781 if (xev->detail == mv_resize->moveresize_button)
4782 finish_drag (mv_resize);
4794 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4798 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4800 if (!mv_resize || window != mv_resize->moveresize_window)
4803 if (mv_resize->moveresize_pending_event)
4805 tmp_event = mv_resize->moveresize_pending_event;
4806 mv_resize->moveresize_pending_event = NULL;
4807 _gdk_x11_moveresize_handle_event (tmp_event);
4815 create_moveresize_window (MoveResizeData *mv_resize,
4818 GdkWindowAttr attributes;
4819 gint attributes_mask;
4820 GdkGrabStatus status;
4822 g_assert (mv_resize->moveresize_emulation_window == NULL);
4824 attributes.x = -100;
4825 attributes.y = -100;
4826 attributes.width = 10;
4827 attributes.height = 10;
4828 attributes.window_type = GDK_WINDOW_TEMP;
4829 attributes.wclass = GDK_INPUT_ONLY;
4830 attributes.override_redirect = TRUE;
4831 attributes.event_mask = 0;
4833 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4835 mv_resize->moveresize_emulation_window =
4836 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4840 gdk_window_show (mv_resize->moveresize_emulation_window);
4842 status = gdk_device_grab (mv_resize->device,
4843 mv_resize->moveresize_emulation_window,
4846 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4850 if (status != GDK_GRAB_SUCCESS)
4852 /* If this fails, some other client has grabbed the window
4855 finish_drag (mv_resize);
4858 mv_resize->moveresize_process_time = 0;
4862 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4863 so that calling XMoveWindow with these coordinates will not move the
4865 Note that this depends on the WM to implement ICCCM-compliant reference
4869 calculate_unmoving_origin (MoveResizeData *mv_resize)
4874 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4875 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4877 gdk_window_get_origin (mv_resize->moveresize_window,
4878 &mv_resize->moveresize_orig_x,
4879 &mv_resize->moveresize_orig_y);
4883 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4884 gdk_window_get_geometry (mv_resize->moveresize_window,
4885 NULL, NULL, &width, &height);
4887 switch (mv_resize->moveresize_geometry.win_gravity)
4889 case GDK_GRAVITY_NORTH_WEST:
4890 mv_resize->moveresize_orig_x = rect.x;
4891 mv_resize->moveresize_orig_y = rect.y;
4893 case GDK_GRAVITY_NORTH:
4894 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4895 mv_resize->moveresize_orig_y = rect.y;
4897 case GDK_GRAVITY_NORTH_EAST:
4898 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4899 mv_resize->moveresize_orig_y = rect.y;
4901 case GDK_GRAVITY_WEST:
4902 mv_resize->moveresize_orig_x = rect.x;
4903 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4905 case GDK_GRAVITY_CENTER:
4906 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4907 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4909 case GDK_GRAVITY_EAST:
4910 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4911 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4913 case GDK_GRAVITY_SOUTH_WEST:
4914 mv_resize->moveresize_orig_x = rect.x;
4915 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4917 case GDK_GRAVITY_SOUTH:
4918 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4919 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4921 case GDK_GRAVITY_SOUTH_EAST:
4922 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4923 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4926 mv_resize->moveresize_orig_x = rect.x;
4927 mv_resize->moveresize_orig_y = rect.y;
4934 emulate_resize_drag (GdkWindow *window,
4942 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4944 mv_resize->is_resize = TRUE;
4945 mv_resize->moveresize_button = button;
4946 mv_resize->resize_edge = edge;
4947 mv_resize->device = device;
4948 mv_resize->moveresize_x = root_x;
4949 mv_resize->moveresize_y = root_y;
4950 mv_resize->moveresize_window = g_object_ref (window);
4952 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
4953 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
4955 mv_resize->moveresize_geom_mask = 0;
4956 gdk_window_get_geometry_hints (window,
4957 &mv_resize->moveresize_geometry,
4958 &mv_resize->moveresize_geom_mask);
4960 calculate_unmoving_origin (mv_resize);
4962 create_moveresize_window (mv_resize, timestamp);
4966 emulate_move_drag (GdkWindow *window,
4973 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4975 mv_resize->is_resize = FALSE;
4976 mv_resize->device = device;
4977 mv_resize->moveresize_button = button;
4978 mv_resize->moveresize_x = root_x;
4979 mv_resize->moveresize_y = root_y;
4981 mv_resize->moveresize_window = g_object_ref (window);
4983 calculate_unmoving_origin (mv_resize);
4985 create_moveresize_window (mv_resize, timestamp);
4989 gdk_x11_window_begin_resize_drag (GdkWindow *window,
4997 if (GDK_WINDOW_DESTROYED (window) ||
4998 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5001 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5002 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5003 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5005 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5009 gdk_x11_window_begin_move_drag (GdkWindow *window,
5016 if (GDK_WINDOW_DESTROYED (window) ||
5017 !WINDOW_IS_TOPLEVEL (window))
5020 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5021 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5022 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5023 device, button, root_x, root_y, timestamp);
5025 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5029 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
5031 GdkWindowImplX11 *impl;
5033 if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
5036 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5038 if (!impl->use_synchronized_configure)
5040 /* This basically means you want to do fancy X specific stuff, so
5041 ensure we have a native window */
5042 gdk_window_ensure_native (window);
5044 impl->use_synchronized_configure = TRUE;
5045 ensure_sync_counter (window);
5050 gdk_x11_window_configure_finished (GdkWindow *window)
5052 GdkWindowImplX11 *impl;
5054 if (!WINDOW_IS_TOPLEVEL (window))
5057 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5058 if (!impl->use_synchronized_configure)
5062 if (!GDK_WINDOW_DESTROYED (window))
5064 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5065 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5067 if (toplevel && toplevel->update_counter != None &&
5068 GDK_X11_DISPLAY (display)->use_sync &&
5069 toplevel->configure_counter_value != 0)
5071 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5072 toplevel->update_counter,
5073 toplevel->configure_counter_value);
5075 toplevel->current_counter_value = toplevel->configure_counter_value;
5076 if ((toplevel->current_counter_value % 2) == 1)
5077 toplevel->current_counter_value += 1;
5079 toplevel->configure_counter_value = 0;
5081 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5082 toplevel->extended_update_counter,
5083 toplevel->current_counter_value);
5090 gdk_x11_window_beep (GdkWindow *window)
5092 GdkDisplay *display;
5094 display = GDK_WINDOW_DISPLAY (window);
5097 if (GDK_X11_DISPLAY (display)->use_xkb)
5099 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5100 GDK_WINDOW_XID (window),
5111 gdk_x11_window_set_opacity (GdkWindow *window,
5114 GdkDisplay *display;
5117 g_return_if_fail (GDK_IS_WINDOW (window));
5119 if (GDK_WINDOW_DESTROYED (window) ||
5120 !WINDOW_IS_TOPLEVEL (window))
5123 display = gdk_window_get_display (window);
5127 else if (opacity > 1)
5130 cardinal = opacity * 0xffffffff;
5132 if (cardinal == 0xffffffff)
5133 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5134 GDK_WINDOW_XID (window),
5135 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5137 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5138 GDK_WINDOW_XID (window),
5139 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5142 (guchar *) &cardinal, 1);
5146 gdk_x11_window_set_composited (GdkWindow *window,
5147 gboolean composited)
5149 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5150 GdkWindowImplX11 *impl;
5151 GdkDisplay *display;
5155 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5157 display = gdk_window_get_display (window);
5158 dpy = GDK_DISPLAY_XDISPLAY (display);
5159 xid = GDK_WINDOW_XID (window);
5163 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5164 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5168 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5169 XDamageDestroy (dpy, impl->damage);
5170 impl->damage = None;
5176 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5177 cairo_region_t *region)
5179 _gdk_window_process_updates_recurse (window, region);
5183 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5188 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5190 /* Sync after all drawing, otherwise the client can get "ahead" of
5191 the server rendering during animations, such that we fill up
5192 the Xserver pipes with sync rendering ops not letting other
5193 clients (including the VM) do anything. */
5194 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5198 timestamp_predicate (Display *display,
5202 Window xwindow = GPOINTER_TO_UINT (arg);
5203 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5205 if (xevent->type == PropertyNotify &&
5206 xevent->xproperty.window == xwindow &&
5207 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5208 "GDK_TIMESTAMP_PROP"))
5215 * gdk_x11_get_server_time:
5216 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5217 * with the server. The window must have
5218 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5221 * Routine to get the current X server time stamp.
5223 * Return value: the time stamp.
5226 gdk_x11_get_server_time (GdkWindow *window)
5232 Atom timestamp_prop_atom;
5234 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5235 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5237 xdisplay = GDK_WINDOW_XDISPLAY (window);
5238 xwindow = GDK_WINDOW_XID (window);
5239 timestamp_prop_atom =
5240 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5241 "GDK_TIMESTAMP_PROP");
5243 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5244 timestamp_prop_atom,
5245 8, PropModeReplace, &c, 1);
5247 XIfEvent (xdisplay, &xevent,
5248 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5250 return xevent.xproperty.time;
5254 * gdk_x11_window_get_xid:
5255 * @window: (type GdkX11Window): a native #GdkWindow.
5257 * Returns the X resource (window) belonging to a #GdkWindow.
5259 * Return value: the ID of @drawable's X resource.
5262 gdk_x11_window_get_xid (GdkWindow *window)
5264 /* Try to ensure the window has a native window */
5265 if (!_gdk_window_has_impl (window))
5267 gdk_window_ensure_native (window);
5269 /* We sync here to ensure the window is created in the Xserver when
5270 * this function returns. This is required because the returned XID
5271 * for this window must be valid immediately, even with another
5272 * connection to the Xserver */
5273 gdk_display_sync (gdk_window_get_display (window));
5276 if (!GDK_WINDOW_IS_X11 (window))
5278 g_warning (G_STRLOC " drawable is not a native X11 window");
5282 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5286 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5288 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5289 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5291 object_class->finalize = gdk_window_impl_x11_finalize;
5293 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5294 impl_class->show = gdk_window_x11_show;
5295 impl_class->hide = gdk_window_x11_hide;
5296 impl_class->withdraw = gdk_window_x11_withdraw;
5297 impl_class->set_events = gdk_window_x11_set_events;
5298 impl_class->get_events = gdk_window_x11_get_events;
5299 impl_class->raise = gdk_window_x11_raise;
5300 impl_class->lower = gdk_window_x11_lower;
5301 impl_class->restack_under = gdk_window_x11_restack_under;
5302 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5303 impl_class->move_resize = gdk_window_x11_move_resize;
5304 impl_class->set_background = gdk_window_x11_set_background;
5305 impl_class->reparent = gdk_window_x11_reparent;
5306 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5307 impl_class->get_geometry = gdk_window_x11_get_geometry;
5308 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5309 impl_class->get_device_state = gdk_window_x11_get_device_state;
5310 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5311 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5312 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5313 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5314 impl_class->translate = _gdk_x11_window_translate;
5315 impl_class->destroy = gdk_x11_window_destroy;
5316 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5317 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5318 impl_class->get_shape = gdk_x11_window_get_shape;
5319 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5320 impl_class->beep = gdk_x11_window_beep;
5322 impl_class->focus = gdk_x11_window_focus;
5323 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5324 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5325 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5326 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5327 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5328 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5329 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5330 impl_class->set_title = gdk_x11_window_set_title;
5331 impl_class->set_role = gdk_x11_window_set_role;
5332 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5333 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5334 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5335 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5336 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5337 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5338 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5339 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5340 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5341 impl_class->iconify = gdk_x11_window_iconify;
5342 impl_class->deiconify = gdk_x11_window_deiconify;
5343 impl_class->stick = gdk_x11_window_stick;
5344 impl_class->unstick = gdk_x11_window_unstick;
5345 impl_class->maximize = gdk_x11_window_maximize;
5346 impl_class->unmaximize = gdk_x11_window_unmaximize;
5347 impl_class->fullscreen = gdk_x11_window_fullscreen;
5348 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5349 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5350 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5351 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5352 impl_class->get_group = gdk_x11_window_get_group;
5353 impl_class->set_group = gdk_x11_window_set_group;
5354 impl_class->set_decorations = gdk_x11_window_set_decorations;
5355 impl_class->get_decorations = gdk_x11_window_get_decorations;
5356 impl_class->set_functions = gdk_x11_window_set_functions;
5357 impl_class->set_functions = gdk_x11_window_set_functions;
5358 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5359 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5360 impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
5361 impl_class->configure_finished = gdk_x11_window_configure_finished;
5362 impl_class->set_opacity = gdk_x11_window_set_opacity;
5363 impl_class->set_composited = gdk_x11_window_set_composited;
5364 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5365 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5366 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5367 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5368 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5369 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5370 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5371 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5372 impl_class->get_property = _gdk_x11_window_get_property;
5373 impl_class->change_property = _gdk_x11_window_change_property;
5374 impl_class->delete_property = _gdk_x11_window_delete_property;