1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gdkwindow-x11.h"
30 #include "gdkwindow.h"
31 #include "gdkwindowimpl.h"
32 #include "gdkvisualprivate.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
36 #include "gdkeventsource.h"
37 #include "gdkdisplay-x11.h"
38 #include "gdkframeclockidle.h"
39 #include "gdkprivate-x11.h"
44 #include <netinet/in.h>
47 #include <cairo-xlib.h>
52 #include <X11/Xutil.h>
53 #include <X11/Xatom.h>
55 #include <X11/extensions/shape.h>
58 #include <X11/XKBlib.h>
61 #ifdef HAVE_XCOMPOSITE
62 #include <X11/extensions/Xcomposite.h>
66 #include <X11/extensions/Xfixes.h>
70 #include <X11/extensions/Xdamage.h>
73 const int _gdk_x11_event_mask_table[21] =
77 PointerMotionHintMask,
94 SubstructureNotifyMask,
95 ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
98 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
100 /* Forward declarations */
101 static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
102 static void gdk_window_set_static_win_gravity (GdkWindow *window,
104 static gboolean gdk_window_icon_name_set (GdkWindow *window);
105 static void set_wm_name (GdkDisplay *display,
108 static void move_to_current_desktop (GdkWindow *window);
109 static void gdk_window_x11_set_background (GdkWindow *window,
110 cairo_pattern_t *pattern);
112 static void gdk_window_impl_x11_finalize (GObject *object);
114 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
115 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
116 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
118 #define WINDOW_IS_TOPLEVEL(window) \
119 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
120 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
121 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
123 /* Return whether time1 is considered later than time2 as far as xserver
124 * time is concerned. Accounts for wraparound.
126 #define XSERVER_TIME_IS_LATER(time1, time2) \
127 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
128 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
131 struct _GdkX11Window {
135 struct _GdkX11WindowClass {
136 GdkWindowClass parent_class;
139 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
142 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
147 gdk_x11_window_init (GdkX11Window *x11_window)
152 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
155 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
157 impl->toplevel_window_type = -1;
158 impl->device_cursor = g_hash_table_new_full (NULL, NULL,
159 NULL, g_object_unref);
163 _gdk_x11_window_get_toplevel (GdkWindow *window)
165 GdkWindowImplX11 *impl;
167 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
169 if (!WINDOW_IS_TOPLEVEL (window))
172 impl = GDK_WINDOW_IMPL_X11 (window->impl);
176 impl->toplevel = g_new0 (GdkToplevelX11, 1);
177 impl->toplevel->have_focused = TRUE;
180 return impl->toplevel;
183 static const cairo_user_data_key_t gdk_x11_cairo_key;
186 * _gdk_x11_window_update_size:
187 * @impl: a #GdkWindowImplX11.
189 * Updates the state of the window (in particular the drawable's
190 * cairo surface) when its size has changed.
193 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
195 if (impl->cairo_surface)
197 cairo_xlib_surface_set_size (impl->cairo_surface,
198 gdk_window_get_width (impl->wrapper),
199 gdk_window_get_height (impl->wrapper));
204 set_sync_counter(Display *display,
205 XSyncCounter counter,
208 XSyncValue sync_value;
210 XSyncIntsToValue(&sync_value,
211 value & G_GINT64_CONSTANT(0xFFFFFFFF),
213 XSyncSetCounter(display, counter, sync_value);
217 window_pre_damage (GdkWindow *window)
219 GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
220 GdkWindowImplX11 *impl;
222 if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
225 impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
227 if (impl->toplevel->in_frame &&
228 impl->toplevel->current_counter_value % 2 == 0)
230 impl->toplevel->current_counter_value += 1;
231 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
232 impl->toplevel->extended_update_counter,
233 impl->toplevel->current_counter_value);
238 on_surface_changed (void *data)
240 GdkWindow *window = data;
242 window_pre_damage (window);
245 /* We want to know when cairo drawing causes damage to the window,
246 * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
247 * window only when there actually is drawing. To do that we use
248 * a technique (hack) suggested by Uli Schlachter - if we set
249 * a dummy "mime data" on the cairo surface (this facility is
250 * used to attach JPEG data to an imager), then cairo wil flush
251 * and remove the mime data before making any changes to the window.
255 hook_surface_changed (GdkWindow *window)
257 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
259 if (impl->cairo_surface)
260 cairo_surface_set_mime_data (impl->cairo_surface,
261 "x-gdk/change-notify",
262 (unsigned char *)"X",
269 unhook_surface_changed (GdkWindow *window)
271 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
273 if (impl->cairo_surface)
274 cairo_surface_set_mime_data (impl->cairo_surface,
275 "x-gdk/change-notify",
281 gdk_x11_window_predict_presentation_time (GdkWindow *window)
283 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
284 GdkFrameClock *clock;
285 GdkFrameTimings *timings;
287 gint64 presentation_time;
288 gint64 refresh_interval;
289 gboolean slept_before;
291 if (!WINDOW_IS_TOPLEVEL (window))
294 clock = gdk_window_get_frame_clock (window);
296 timings = gdk_frame_clock_get_current_frame_timings (clock);
297 frame_time = gdk_frame_timings_get_frame_time (timings);
298 slept_before = gdk_frame_timings_get_slept_before (timings);
300 gdk_frame_clock_get_refresh_info (clock,
302 &refresh_interval, &presentation_time);
304 if (presentation_time != 0)
308 presentation_time += refresh_interval;
312 if (presentation_time < frame_time + refresh_interval / 2)
313 presentation_time += refresh_interval;
319 presentation_time = frame_time + refresh_interval + refresh_interval / 2;
321 presentation_time = frame_time + refresh_interval;
324 if (presentation_time < impl->toplevel->throttled_presentation_time)
325 presentation_time = impl->toplevel->throttled_presentation_time;
327 gdk_frame_timings_set_predicted_presentation_time (timings,
333 gdk_x11_window_begin_frame (GdkWindow *window)
335 GdkWindowImplX11 *impl;
337 g_return_if_fail (GDK_IS_WINDOW (window));
339 impl = GDK_WINDOW_IMPL_X11 (window->impl);
341 if (!WINDOW_IS_TOPLEVEL (window) ||
342 impl->toplevel->extended_update_counter == None)
345 impl->toplevel->in_frame = TRUE;
347 if (impl->toplevel->configure_counter_value != 0 &&
348 impl->toplevel->configure_counter_value_is_extended)
350 impl->toplevel->current_counter_value = impl->toplevel->configure_counter_value;
351 if ((impl->toplevel->current_counter_value % 2) == 1)
352 impl->toplevel->current_counter_value += 1;
354 impl->toplevel->configure_counter_value = 0;
356 window_pre_damage (window);
360 hook_surface_changed (window);
365 gdk_x11_window_end_frame (GdkWindow *window)
367 GdkFrameClock *clock;
368 GdkFrameTimings *timings;
369 GdkWindowImplX11 *impl;
371 g_return_if_fail (GDK_IS_WINDOW (window));
373 impl = GDK_WINDOW_IMPL_X11 (window->impl);
375 if (!WINDOW_IS_TOPLEVEL (window) ||
376 impl->toplevel->extended_update_counter == None ||
377 !impl->toplevel->in_frame)
380 clock = gdk_window_get_frame_clock (window);
381 timings = gdk_frame_clock_get_current_frame_timings (clock);
383 impl->toplevel->in_frame = FALSE;
385 if (impl->toplevel->current_counter_value % 2 == 1)
387 #ifdef G_ENABLE_DEBUG
388 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
390 XImage *image = XGetImage (GDK_WINDOW_XDISPLAY (window),
391 GDK_WINDOW_XID (window),
395 XDestroyImage (image);
397 #endif /* G_ENABLE_DEBUG */
399 /* An increment of 3 means that the frame was not drawn as fast as possible,
400 * but rather at a particular time. This can trigger different handling from
403 if (gdk_frame_timings_get_slept_before (timings))
404 impl->toplevel->current_counter_value += 3;
406 impl->toplevel->current_counter_value += 1;
408 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
409 impl->toplevel->extended_update_counter,
410 impl->toplevel->current_counter_value);
412 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
413 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
415 impl->toplevel->frame_pending = TRUE;
416 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
417 gdk_frame_timings_set_cookie (timings,
418 impl->toplevel->current_counter_value);
422 unhook_surface_changed (window);
424 if (impl->toplevel->configure_counter_value != 0 &&
425 !impl->toplevel->configure_counter_value_is_extended)
427 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
428 impl->toplevel->update_counter,
429 impl->toplevel->configure_counter_value);
431 impl->toplevel->configure_counter_value = 0;
434 if (!impl->toplevel->frame_pending)
435 gdk_frame_timings_set_complete (timings, TRUE);
438 /*****************************************************
439 * X11 specific implementations of generic functions *
440 *****************************************************/
443 gdk_x11_cairo_surface_destroy (void *data)
445 GdkWindowImplX11 *impl = data;
447 impl->cairo_surface = NULL;
450 static cairo_surface_t *
451 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
457 visual = gdk_window_get_visual (impl->wrapper);
458 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
459 GDK_WINDOW_IMPL_X11 (impl)->xid,
460 GDK_VISUAL_XVISUAL (visual),
464 static cairo_surface_t *
465 gdk_x11_ref_cairo_surface (GdkWindow *window)
467 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
469 if (GDK_WINDOW_DESTROYED (window))
472 if (!impl->cairo_surface)
474 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
475 gdk_window_get_width (window),
476 gdk_window_get_height (window));
478 if (impl->cairo_surface)
479 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
480 impl, gdk_x11_cairo_surface_destroy);
482 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
483 hook_surface_changed (window);
486 cairo_surface_reference (impl->cairo_surface);
488 return impl->cairo_surface;
492 gdk_window_impl_x11_finalize (GObject *object)
495 GdkWindowImplX11 *impl;
497 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
499 impl = GDK_WINDOW_IMPL_X11 (object);
501 wrapper = impl->wrapper;
503 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
504 unhook_surface_changed (wrapper);
506 _gdk_x11_window_grab_check_destroy (wrapper);
508 if (!GDK_WINDOW_DESTROYED (wrapper))
510 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
512 _gdk_x11_display_remove_window (display, impl->xid);
513 if (impl->toplevel && impl->toplevel->focus_window)
514 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
517 g_free (impl->toplevel);
520 g_object_unref (impl->cursor);
522 g_hash_table_destroy (impl->device_cursor);
524 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
533 free_pixmap (gpointer datap)
535 FreePixmapData *data = datap;
537 if (!gdk_display_is_closed (data->display))
539 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
543 g_object_unref (data->display);
544 g_slice_free (FreePixmapData, data);
548 attach_free_pixmap_handler (cairo_surface_t *surface,
552 static const cairo_user_data_key_t key;
553 FreePixmapData *data;
555 data = g_slice_new (FreePixmapData);
556 data->display = g_object_ref (display);
557 data->pixmap = pixmap;
559 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
562 /* Cairo does not guarantee we get an xlib surface if we call
563 * cairo_surface_create_similar(). In some cases however, we must use a
564 * pixmap or bitmap in the X11 API.
565 * These functions ensure an Xlib surface.
568 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
572 cairo_surface_t *surface;
575 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
576 GDK_WINDOW_XID (window),
578 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
580 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
582 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
587 /* Create a surface backed with a pixmap without alpha on the same screen as window */
588 static cairo_surface_t *
589 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
593 GdkScreen *screen = gdk_window_get_screen (window);
594 GdkVisual *visual = gdk_screen_get_system_visual (screen);
595 cairo_surface_t *surface;
598 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
599 GDK_WINDOW_XID (window),
601 gdk_visual_get_depth (visual));
602 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
604 GDK_VISUAL_XVISUAL (visual),
606 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
612 tmp_unset_bg (GdkWindow *window)
614 GdkWindowImplX11 *impl;
616 impl = GDK_WINDOW_IMPL_X11 (window->impl);
620 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
621 GDK_WINDOW_XID (window), None);
625 tmp_reset_bg (GdkWindow *window)
627 GdkWindowImplX11 *impl;
629 impl = GDK_WINDOW_IMPL_X11 (window->impl);
633 gdk_window_x11_set_background (window, window->background);
636 /* Unsetting and resetting window backgrounds.
638 * In many cases it is possible to avoid flicker by unsetting the
639 * background of windows. For example if the background of the
640 * parent window is unset when a window is unmapped, a brief flicker
641 * of background painting is avoided.
644 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
647 g_return_if_fail (GDK_IS_WINDOW (window));
649 if (window->input_only || window->destroyed ||
650 (window->window_type != GDK_WINDOW_ROOT &&
651 !GDK_WINDOW_IS_MAPPED (window)))
654 if (_gdk_window_has_impl (window) &&
655 GDK_WINDOW_IS_X11 (window) &&
656 window->window_type != GDK_WINDOW_ROOT &&
657 window->window_type != GDK_WINDOW_FOREIGN)
658 tmp_unset_bg (window);
664 for (l = window->children; l != NULL; l = l->next)
665 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
670 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
672 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
675 window = _gdk_window_get_impl_window (window->parent);
676 _gdk_x11_window_tmp_unset_bg (window, FALSE);
680 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
683 g_return_if_fail (GDK_IS_WINDOW (window));
685 if (window->input_only || window->destroyed ||
686 (window->window_type != GDK_WINDOW_ROOT &&
687 !GDK_WINDOW_IS_MAPPED (window)))
691 if (_gdk_window_has_impl (window) &&
692 GDK_WINDOW_IS_X11 (window) &&
693 window->window_type != GDK_WINDOW_ROOT &&
694 window->window_type != GDK_WINDOW_FOREIGN)
695 tmp_reset_bg (window);
701 for (l = window->children; l != NULL; l = l->next)
702 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
707 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
709 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
712 window = _gdk_window_get_impl_window (window->parent);
714 _gdk_x11_window_tmp_reset_bg (window, FALSE);
718 _gdk_x11_screen_init_root_window (GdkScreen *screen)
721 GdkWindowImplX11 *impl;
722 GdkX11Screen *x11_screen;
724 x11_screen = GDK_X11_SCREEN (screen);
726 g_assert (x11_screen->root_window == NULL);
728 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
730 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
731 window->impl_window = window;
732 window->visual = gdk_screen_get_system_visual (screen);
734 impl = GDK_WINDOW_IMPL_X11 (window->impl);
736 impl->xid = x11_screen->xroot_window;
737 impl->wrapper = window;
739 window->window_type = GDK_WINDOW_ROOT;
740 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
746 window->width = WidthOfScreen (x11_screen->xscreen);
747 window->height = HeightOfScreen (x11_screen->xscreen);
748 window->viewable = TRUE;
750 /* see init_randr_support() in gdkscreen-x11.c */
751 window->event_mask = GDK_STRUCTURE_MASK;
753 _gdk_window_update_size (x11_screen->root_window);
755 _gdk_x11_display_add_window (x11_screen->display,
756 &x11_screen->xroot_window,
757 x11_screen->root_window);
761 set_wm_protocols (GdkWindow *window)
763 GdkDisplay *display = gdk_window_get_display (window);
767 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
768 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
769 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
772 if (GDK_X11_DISPLAY (display)->use_sync)
773 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
776 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
780 get_default_title (void)
784 title = g_get_application_name ();
786 title = g_get_prgname ();
794 check_leader_window_title (GdkDisplay *display)
796 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
798 if (display_x11->leader_window && !display_x11->leader_window_title_set)
800 set_wm_name (display,
801 display_x11->leader_window,
802 get_default_title ());
804 display_x11->leader_window_title_set = TRUE;
809 create_focus_window (GdkDisplay *display,
812 GdkX11Display *display_x11;
813 GdkEventMask event_mask;
817 xdisplay = GDK_DISPLAY_XDISPLAY (display);
818 display_x11 = GDK_X11_DISPLAY (display);
820 focus_window = XCreateSimpleWindow (xdisplay, parent,
824 /* FIXME: probably better to actually track the requested event mask for the toplevel
826 event_mask = (GDK_KEY_PRESS_MASK |
827 GDK_KEY_RELEASE_MASK |
828 GDK_FOCUS_CHANGE_MASK);
830 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
834 XMapWindow (xdisplay, focus_window);
840 ensure_sync_counter (GdkWindow *window)
843 if (!GDK_WINDOW_DESTROYED (window))
845 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
846 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
849 toplevel->update_counter == None &&
850 GDK_X11_DISPLAY (display)->use_sync)
852 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
857 XSyncIntToValue (&value, 0);
859 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
860 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
862 atom = gdk_x11_get_xatom_by_name_for_display (display,
863 "_NET_WM_SYNC_REQUEST_COUNTER");
865 counters[0] = toplevel->update_counter;
866 counters[1] = toplevel->extended_update_counter;
867 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
870 (guchar *)counters, 2);
872 toplevel->current_counter_value = 0;
879 setup_toplevel_window (GdkWindow *window,
882 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
883 GdkDisplay *display = gdk_window_get_display (window);
884 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
885 XID xid = GDK_WINDOW_XID (window);
886 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
887 XSizeHints size_hints;
889 Window leader_window;
891 set_wm_protocols (window);
893 if (!window->input_only)
895 /* The focus window is off the visible area, and serves to receive key
896 * press events so they don't get sent to child windows.
898 toplevel->focus_window = create_focus_window (display, xid);
899 _gdk_x11_display_add_window (x11_screen->display,
900 &toplevel->focus_window,
904 check_leader_window_title (x11_screen->display);
906 /* FIXME: Is there any point in doing this? Do any WM's pay
907 * attention to PSize, and even if they do, is this the
910 size_hints.flags = PSize;
911 size_hints.width = window->width;
912 size_hints.height = window->height;
914 XSetWMNormalHints (xdisplay, xid, &size_hints);
916 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
917 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
920 XChangeProperty (xdisplay, xid,
921 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
926 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
929 XChangeProperty (xdisplay, xid,
930 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
931 XA_WINDOW, 32, PropModeReplace,
932 (guchar *) &leader_window, 1);
934 if (toplevel->focus_window != None)
935 XChangeProperty (xdisplay, xid,
936 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
937 XA_WINDOW, 32, PropModeReplace,
938 (guchar *) &toplevel->focus_window, 1);
940 if (!window->focus_on_map)
941 gdk_x11_window_set_user_time (window, 0);
942 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
943 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
945 ensure_sync_counter (window);
947 /* Start off in a frozen state - we'll finish this when we first paint */
948 gdk_x11_window_begin_frame (window);
952 on_frame_clock_before_paint (GdkFrameClock *clock,
955 gdk_x11_window_predict_presentation_time (window);
956 gdk_x11_window_begin_frame (window);
960 on_frame_clock_after_paint (GdkFrameClock *clock,
963 gdk_x11_window_end_frame (window);
968 _gdk_x11_display_create_window_impl (GdkDisplay *display,
970 GdkWindow *real_parent,
972 GdkEventMask event_mask,
973 GdkWindowAttr *attributes,
974 gint attributes_mask)
976 GdkWindowImplX11 *impl;
977 GdkX11Screen *x11_screen;
978 GdkX11Display *display_x11;
979 GdkFrameClock *clock;
985 XSetWindowAttributes xattributes;
986 long xattributes_mask;
987 XClassHint *class_hint;
992 display_x11 = GDK_X11_DISPLAY (display);
993 xparent = GDK_WINDOW_XID (real_parent);
994 x11_screen = GDK_X11_SCREEN (screen);
996 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
997 window->impl = GDK_WINDOW_IMPL (impl);
998 impl->wrapper = GDK_WINDOW (window);
1000 xdisplay = x11_screen->xdisplay;
1002 xattributes_mask = 0;
1004 xvisual = gdk_x11_visual_get_xvisual (window->visual);
1006 if (attributes_mask & GDK_WA_NOREDIR)
1008 xattributes.override_redirect =
1009 (attributes->override_redirect == FALSE)?False:True;
1010 xattributes_mask |= CWOverrideRedirect;
1013 xattributes.override_redirect = False;
1015 impl->override_redirect = xattributes.override_redirect;
1017 if (window->parent && window->parent->guffaw_gravity)
1019 xattributes.win_gravity = StaticGravity;
1020 xattributes_mask |= CWWinGravity;
1024 switch (window->window_type)
1026 case GDK_WINDOW_TOPLEVEL:
1027 case GDK_WINDOW_TEMP:
1028 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
1030 /* The common code warns for this case */
1031 xparent = GDK_SCREEN_XROOTWIN (screen);
1035 if (!window->input_only)
1037 class = InputOutput;
1039 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1041 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1042 xattributes_mask |= CWBorderPixel | CWBackPixel;
1044 if (window->guffaw_gravity)
1045 xattributes.bit_gravity = StaticGravity;
1047 xattributes.bit_gravity = NorthWestGravity;
1049 xattributes_mask |= CWBitGravity;
1051 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
1052 xattributes_mask |= CWColormap;
1054 if (window->window_type == GDK_WINDOW_TEMP)
1056 xattributes.save_under = True;
1057 xattributes.override_redirect = True;
1058 xattributes.cursor = None;
1059 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
1061 impl->override_redirect = TRUE;
1069 if (window->width > 65535 ||
1070 window->height > 65535)
1072 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
1074 if (window->width > 65535)
1075 window->width = 65535;
1076 if (window->height > 65535)
1077 window->height = 65535;
1080 impl->xid = XCreateWindow (xdisplay, xparent,
1081 window->x + window->parent->abs_x,
1082 window->y + window->parent->abs_y,
1083 window->width, window->height,
1084 0, window->depth, class, xvisual,
1085 xattributes_mask, &xattributes);
1087 g_object_ref (window);
1088 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1090 switch (GDK_WINDOW_TYPE (window))
1092 case GDK_WINDOW_TOPLEVEL:
1093 case GDK_WINDOW_TEMP:
1094 if (attributes_mask & GDK_WA_TITLE)
1095 title = attributes->title;
1097 title = get_default_title ();
1099 gdk_window_set_title (window, title);
1101 if (attributes_mask & GDK_WA_WMCLASS)
1103 class_hint = XAllocClassHint ();
1104 class_hint->res_name = attributes->wmclass_name;
1105 class_hint->res_class = attributes->wmclass_class;
1106 XSetClassHint (xdisplay, impl->xid, class_hint);
1110 setup_toplevel_window (window, window->parent);
1113 case GDK_WINDOW_CHILD:
1118 if (attributes_mask & GDK_WA_TYPE_HINT)
1119 gdk_window_set_type_hint (window, attributes->type_hint);
1121 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1122 GDK_WINDOW_XID (window), event_mask,
1123 StructureNotifyMask | PropertyChangeMask);
1125 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1126 gdk_window_set_frame_clock (window, clock);
1127 g_signal_connect (clock, "before-paint",
1128 G_CALLBACK (on_frame_clock_before_paint), window);
1129 g_signal_connect (clock, "after-paint",
1130 G_CALLBACK (on_frame_clock_after_paint), window);
1132 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1133 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1137 x_event_mask_to_gdk_event_mask (long mask)
1139 GdkEventMask event_mask = 0;
1142 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1144 if (mask & _gdk_x11_event_mask_table[i])
1145 event_mask |= 1 << (i + 1);
1152 * gdk_x11_window_foreign_new_for_display:
1153 * @display: the #GdkDisplay where the window handle comes from.
1154 * @window: an XLib <type>Window</type>
1156 * Wraps a native window in a #GdkWindow. The function will try to
1157 * look up the window using gdk_x11_window_lookup_for_display() first.
1158 * If it does not find it there, it will create a new window.
1160 * This may fail if the window has been destroyed. If the window
1161 * was already known to GDK, a new reference to the existing
1162 * #GdkWindow is returned.
1164 * Return value: (transfer full): a #GdkWindow wrapper for the native
1165 * window, or %NULL if the window has been destroyed. The wrapper
1166 * will be newly created, if one doesn't exist already.
1171 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1176 GdkWindowImplX11 *impl;
1177 GdkX11Display *display_x11;
1178 XWindowAttributes attrs;
1179 Window root, parent;
1180 Window *children = NULL;
1184 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1186 display_x11 = GDK_X11_DISPLAY (display);
1188 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1189 return g_object_ref (win);
1191 gdk_x11_display_error_trap_push (display);
1192 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1193 if (gdk_x11_display_error_trap_pop (display) || !result)
1196 /* FIXME: This is pretty expensive.
1197 * Maybe the caller should supply the parent
1199 gdk_x11_display_error_trap_push (display);
1200 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1201 if (gdk_x11_display_error_trap_pop (display) || !result)
1207 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1209 win = _gdk_display_create_window (display);
1210 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1211 win->impl_window = win;
1212 win->visual = gdk_x11_screen_lookup_visual (screen,
1213 XVisualIDFromVisual (attrs.visual));
1215 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1216 impl->wrapper = win;
1218 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1220 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1221 win->parent = gdk_screen_get_root_window (screen);
1223 win->parent->children = g_list_prepend (win->parent->children, win);
1229 win->width = attrs.width;
1230 win->height = attrs.height;
1231 win->window_type = GDK_WINDOW_FOREIGN;
1232 win->destroyed = FALSE;
1234 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1236 if (attrs.map_state == IsUnmapped)
1237 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1240 win->viewable = TRUE;
1242 win->depth = attrs.depth;
1245 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1247 /* Update the clip region, etc */
1248 _gdk_window_update_size (win);
1254 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1255 GdkToplevelX11 *toplevel)
1257 if (toplevel->icon_pixmap)
1259 cairo_surface_destroy (toplevel->icon_pixmap);
1260 toplevel->icon_pixmap = NULL;
1262 if (toplevel->icon_mask)
1264 cairo_surface_destroy (toplevel->icon_mask);
1265 toplevel->icon_mask = NULL;
1267 if (toplevel->group_leader)
1269 g_object_unref (toplevel->group_leader);
1270 toplevel->group_leader = NULL;
1273 if (toplevel->update_counter != None)
1275 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1276 toplevel->update_counter);
1277 toplevel->update_counter = None;
1279 toplevel->current_counter_value = 0;
1285 gdk_x11_window_destroy (GdkWindow *window,
1287 gboolean foreign_destroy)
1289 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1290 GdkToplevelX11 *toplevel;
1292 g_return_if_fail (GDK_IS_WINDOW (window));
1294 _gdk_x11_selection_window_destroyed (window);
1296 toplevel = _gdk_x11_window_get_toplevel (window);
1298 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1300 if (impl->cairo_surface)
1302 cairo_surface_finish (impl->cairo_surface);
1303 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1307 if (!recursing && !foreign_destroy)
1308 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1311 static cairo_surface_t *
1312 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1313 cairo_surface_t *surface,
1317 cairo_xlib_surface_set_size (surface, width, height);
1323 gdk_x11_window_destroy_foreign (GdkWindow *window)
1325 /* It's somebody else's window, but in our hierarchy,
1326 * so reparent it to the root window, and then send
1327 * it a delete event, as if we were a WM
1329 XClientMessageEvent xclient;
1330 GdkDisplay *display;
1332 display = GDK_WINDOW_DISPLAY (window);
1333 gdk_x11_display_error_trap_push (display);
1334 gdk_window_hide (window);
1335 gdk_window_reparent (window, NULL, 0, 0);
1337 memset (&xclient, 0, sizeof (xclient));
1338 xclient.type = ClientMessage;
1339 xclient.window = GDK_WINDOW_XID (window);
1340 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1341 xclient.format = 32;
1342 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1343 xclient.data.l[1] = CurrentTime;
1344 xclient.data.l[2] = 0;
1345 xclient.data.l[3] = 0;
1346 xclient.data.l[4] = 0;
1348 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1349 GDK_WINDOW_XID (window),
1350 False, 0, (XEvent *)&xclient);
1351 gdk_x11_display_error_trap_pop_ignored (display);
1355 get_root (GdkWindow *window)
1357 GdkScreen *screen = gdk_window_get_screen (window);
1359 return gdk_screen_get_root_window (screen);
1362 /* This function is called when the XWindow is really gone.
1365 gdk_x11_window_destroy_notify (GdkWindow *window)
1367 GdkWindowImplX11 *window_impl;
1369 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1371 if (!GDK_WINDOW_DESTROYED (window))
1373 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1374 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1376 _gdk_window_destroy (window, TRUE);
1379 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1380 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1381 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1383 _gdk_x11_window_grab_check_destroy (window);
1385 g_object_unref (window);
1388 static GdkDragProtocol
1389 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1392 GdkDragProtocol protocol;
1393 GdkDisplay *display;
1397 display = gdk_window_get_display (window);
1398 xid = _gdk_x11_display_get_drag_protocol (display,
1399 GDK_WINDOW_XID (window->impl_window),
1406 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1415 update_wm_hints (GdkWindow *window,
1418 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1419 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1423 !toplevel->is_leader &&
1424 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1427 wm_hints.flags = StateHint | InputHint;
1428 wm_hints.input = window->accept_focus ? True : False;
1429 wm_hints.initial_state = NormalState;
1431 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1433 wm_hints.flags |= StateHint;
1434 wm_hints.initial_state = IconicState;
1437 if (toplevel->icon_pixmap)
1439 wm_hints.flags |= IconPixmapHint;
1440 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1443 if (toplevel->icon_mask)
1445 wm_hints.flags |= IconMaskHint;
1446 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1449 wm_hints.flags |= WindowGroupHint;
1450 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1452 wm_hints.flags |= WindowGroupHint;
1453 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1456 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1458 if (toplevel->urgency_hint)
1459 wm_hints.flags |= XUrgencyHint;
1461 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1462 GDK_WINDOW_XID (window),
1467 set_initial_hints (GdkWindow *window)
1469 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1470 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1471 Window xwindow = GDK_WINDOW_XID (window);
1472 GdkToplevelX11 *toplevel;
1476 toplevel = _gdk_x11_window_get_toplevel (window);
1481 update_wm_hints (window, TRUE);
1483 /* We set the spec hints regardless of whether the spec is supported,
1484 * since it can't hurt and it's kind of expensive to check whether
1490 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1492 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1493 "_NET_WM_STATE_MAXIMIZED_VERT");
1495 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1496 "_NET_WM_STATE_MAXIMIZED_HORZ");
1498 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1501 if (window->state & GDK_WINDOW_STATE_ABOVE)
1503 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1504 "_NET_WM_STATE_ABOVE");
1508 if (window->state & GDK_WINDOW_STATE_BELOW)
1510 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1511 "_NET_WM_STATE_BELOW");
1515 if (window->state & GDK_WINDOW_STATE_STICKY)
1517 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1518 "_NET_WM_STATE_STICKY");
1520 toplevel->have_sticky = TRUE;
1523 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1525 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1526 "_NET_WM_STATE_FULLSCREEN");
1528 toplevel->have_fullscreen = TRUE;
1531 if (window->modal_hint)
1533 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1534 "_NET_WM_STATE_MODAL");
1538 if (toplevel->skip_taskbar_hint)
1540 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1541 "_NET_WM_STATE_SKIP_TASKBAR");
1545 if (toplevel->skip_pager_hint)
1547 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1548 "_NET_WM_STATE_SKIP_PAGER");
1552 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1554 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1555 "_NET_WM_STATE_HIDDEN");
1557 toplevel->have_hidden = TRUE;
1562 XChangeProperty (xdisplay,
1564 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1565 XA_ATOM, 32, PropModeReplace,
1566 (guchar*) atoms, i);
1570 XDeleteProperty (xdisplay,
1572 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1575 if (window->state & GDK_WINDOW_STATE_STICKY)
1577 atoms[0] = 0xFFFFFFFF;
1578 XChangeProperty (xdisplay,
1580 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1581 XA_CARDINAL, 32, PropModeReplace,
1582 (guchar*) atoms, 1);
1583 toplevel->on_all_desktops = TRUE;
1587 XDeleteProperty (xdisplay,
1589 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1592 toplevel->map_serial = NextRequest (xdisplay);
1596 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1598 GdkDisplay *display;
1599 GdkX11Display *display_x11;
1600 GdkToplevelX11 *toplevel;
1601 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1602 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1603 Window xwindow = GDK_WINDOW_XID (window);
1606 if (!already_mapped)
1607 set_initial_hints (window);
1609 if (WINDOW_IS_TOPLEVEL (window))
1611 display = gdk_window_get_display (window);
1612 display_x11 = GDK_X11_DISPLAY (display);
1613 toplevel = _gdk_x11_window_get_toplevel (window);
1615 if (toplevel->user_time != 0 &&
1616 display_x11->user_time != 0 &&
1617 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1618 gdk_x11_window_set_user_time (window, display_x11->user_time);
1621 unset_bg = !window->input_only &&
1622 (window->window_type == GDK_WINDOW_CHILD ||
1623 impl->override_redirect) &&
1624 gdk_window_is_viewable (window);
1627 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1629 XMapWindow (xdisplay, xwindow);
1632 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1634 /* Fullscreen on current monitor is the default, no need to apply this mode
1635 * when mapping a window. This also ensures that the default behavior remains
1636 * consistent with pre-fullscreen mode implementation.
1638 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1639 gdk_x11_window_apply_fullscreen_mode (window);
1643 pre_unmap (GdkWindow *window)
1645 GdkWindow *start_window = NULL;
1647 if (window->input_only)
1650 if (window->window_type == GDK_WINDOW_CHILD)
1651 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1652 else if (window->window_type == GDK_WINDOW_TEMP)
1653 start_window = get_root (window);
1656 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1660 post_unmap (GdkWindow *window)
1662 GdkWindow *start_window = NULL;
1664 if (window->input_only)
1667 if (window->window_type == GDK_WINDOW_CHILD)
1668 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1669 else if (window->window_type == GDK_WINDOW_TEMP)
1670 start_window = get_root (window);
1674 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1676 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1678 GdkRectangle invalid_rect;
1680 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1681 invalid_rect.width = gdk_window_get_width (window);
1682 invalid_rect.height = gdk_window_get_height (window);
1683 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1684 &invalid_rect, TRUE);
1690 gdk_window_x11_hide (GdkWindow *window)
1692 /* We'll get the unmap notify eventually, and handle it then,
1693 * but checking here makes things more consistent if we are
1694 * just doing stuff ourself.
1696 _gdk_x11_window_grab_check_unmap (window,
1697 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1699 /* You can't simply unmap toplevel windows. */
1700 switch (window->window_type)
1702 case GDK_WINDOW_TOPLEVEL:
1703 case GDK_WINDOW_TEMP: /* ? */
1704 gdk_window_withdraw (window);
1707 case GDK_WINDOW_FOREIGN:
1708 case GDK_WINDOW_ROOT:
1709 case GDK_WINDOW_CHILD:
1713 _gdk_window_clear_update_area (window);
1716 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1717 GDK_WINDOW_XID (window));
1718 post_unmap (window);
1722 gdk_window_x11_withdraw (GdkWindow *window)
1724 if (!window->destroyed)
1726 if (GDK_WINDOW_IS_MAPPED (window))
1727 gdk_synthesize_window_state (window,
1729 GDK_WINDOW_STATE_WITHDRAWN);
1731 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1735 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1736 GDK_WINDOW_XID (window), 0);
1738 post_unmap (window);
1743 window_x11_move (GdkWindow *window,
1747 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1749 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1751 /* The window isn't actually damaged, but it's parent is */
1752 window_pre_damage (window);
1753 _gdk_x11_window_move_resize_child (window,
1755 window->width, window->height);
1759 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1760 GDK_WINDOW_XID (window),
1763 if (impl->override_redirect)
1772 window_x11_resize (GdkWindow *window,
1782 window_pre_damage (window);
1784 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1786 _gdk_x11_window_move_resize_child (window,
1787 window->x, window->y,
1792 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1794 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1795 GDK_WINDOW_XID (window),
1798 if (impl->override_redirect)
1800 window->width = width;
1801 window->height = height;
1802 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1806 if (width != window->width || height != window->height)
1807 window->resize_count += 1;
1811 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1815 window_x11_move_resize (GdkWindow *window,
1827 window_pre_damage (window);
1829 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1831 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1832 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1836 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1838 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1839 GDK_WINDOW_XID (window),
1840 x, y, width, height);
1842 if (impl->override_redirect)
1847 window->width = width;
1848 window->height = height;
1850 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1854 if (width != window->width || height != window->height)
1855 window->resize_count += 1;
1861 gdk_window_x11_move_resize (GdkWindow *window,
1868 if (with_move && (width < 0 && height < 0))
1869 window_x11_move (window, x, y);
1873 window_x11_move_resize (window, x, y, width, height);
1875 window_x11_resize (window, width, height);
1880 gdk_window_x11_reparent (GdkWindow *window,
1881 GdkWindow *new_parent,
1885 GdkWindowImplX11 *impl;
1887 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1889 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1890 _gdk_x11_window_tmp_unset_parent_bg (window);
1891 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1892 GDK_WINDOW_XID (window),
1893 GDK_WINDOW_XID (new_parent),
1894 new_parent->abs_x + x, new_parent->abs_y + y);
1895 _gdk_x11_window_tmp_reset_parent_bg (window);
1896 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1898 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1899 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1901 window->parent = new_parent;
1903 /* Switch the window type as appropriate */
1905 switch (GDK_WINDOW_TYPE (new_parent))
1907 case GDK_WINDOW_ROOT:
1908 case GDK_WINDOW_FOREIGN:
1909 /* Reparenting to toplevel */
1911 if (!WINDOW_IS_TOPLEVEL (window) &&
1912 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1914 /* This is also done in common code at a later stage, but we
1915 need it in setup_toplevel, so do it here too */
1916 if (window->toplevel_window_type != -1)
1917 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1918 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1919 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1921 /* Wasn't a toplevel, set up */
1922 setup_toplevel_window (window, new_parent);
1927 case GDK_WINDOW_TOPLEVEL:
1928 case GDK_WINDOW_CHILD:
1929 case GDK_WINDOW_TEMP:
1930 if (WINDOW_IS_TOPLEVEL (window) &&
1933 if (impl->toplevel->focus_window)
1935 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1936 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1939 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1941 g_free (impl->toplevel);
1942 impl->toplevel = NULL;
1950 gdk_window_x11_raise (GdkWindow *window)
1952 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1956 gdk_window_x11_restack_under (GdkWindow *window,
1957 GList *native_siblings /* in requested order, first is bottom-most */)
1963 n_windows = g_list_length (native_siblings) + 1;
1964 windows = g_new (Window, n_windows);
1966 windows[0] = GDK_WINDOW_XID (window);
1967 /* Reverse order, as input order is bottom-most first */
1969 for (l = native_siblings; l != NULL; l = l->next)
1970 windows[i--] = GDK_WINDOW_XID (l->data);
1972 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1978 gdk_window_x11_restack_toplevel (GdkWindow *window,
1982 XWindowChanges changes;
1984 changes.sibling = GDK_WINDOW_XID (sibling);
1985 changes.stack_mode = above ? Above : Below;
1986 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1987 GDK_WINDOW_XID (window),
1988 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1989 CWStackMode | CWSibling, &changes);
1993 gdk_window_x11_lower (GdkWindow *window)
1995 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1999 * gdk_x11_window_move_to_current_desktop:
2000 * @window: (type GdkX11Window): a #GdkWindow
2002 * Moves the window to the correct workspace when running under a
2003 * window manager that supports multiple workspaces, as described
2004 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
2005 * Window Manager Hints</ulink>. Will not do anything if the
2006 * window is already on all workspaces.
2011 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
2013 GdkToplevelX11 *toplevel;
2015 g_return_if_fail (GDK_IS_WINDOW (window));
2016 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2018 toplevel = _gdk_x11_window_get_toplevel (window);
2020 if (toplevel->on_all_desktops)
2023 move_to_current_desktop (window);
2027 move_to_current_desktop (GdkWindow *window)
2029 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2030 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
2031 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2032 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
2039 gulong *current_desktop;
2040 GdkDisplay *display;
2042 display = gdk_window_get_display (window);
2044 /* Get current desktop, then set it; this is a race, but not
2045 * one that matters much in practice.
2047 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
2048 GDK_WINDOW_XROOTWIN (window),
2049 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
2051 False, XA_CARDINAL, &type, &format, &nitems,
2052 &bytes_after, &data);
2054 if (type == XA_CARDINAL)
2056 XClientMessageEvent xclient;
2057 current_desktop = (gulong *)data;
2059 memset (&xclient, 0, sizeof (xclient));
2060 xclient.type = ClientMessage;
2062 xclient.send_event = True;
2063 xclient.window = GDK_WINDOW_XID (window);
2064 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
2065 xclient.format = 32;
2067 xclient.data.l[0] = *current_desktop;
2068 xclient.data.l[1] = 1; /* source indication */
2069 xclient.data.l[2] = 0;
2070 xclient.data.l[3] = 0;
2071 xclient.data.l[4] = 0;
2073 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
2074 GDK_WINDOW_XROOTWIN (window),
2076 SubstructureRedirectMask | SubstructureNotifyMask,
2077 (XEvent *)&xclient);
2079 XFree (current_desktop);
2085 gdk_x11_window_focus (GdkWindow *window,
2088 GdkDisplay *display;
2090 g_return_if_fail (GDK_IS_WINDOW (window));
2092 if (GDK_WINDOW_DESTROYED (window) ||
2093 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2096 display = GDK_WINDOW_DISPLAY (window);
2098 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2099 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2101 XClientMessageEvent xclient;
2103 memset (&xclient, 0, sizeof (xclient));
2104 xclient.type = ClientMessage;
2105 xclient.window = GDK_WINDOW_XID (window);
2106 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2107 "_NET_ACTIVE_WINDOW");
2108 xclient.format = 32;
2109 xclient.data.l[0] = 1; /* requestor type; we're an app */
2110 xclient.data.l[1] = timestamp;
2111 xclient.data.l[2] = None; /* currently active window */
2112 xclient.data.l[3] = 0;
2113 xclient.data.l[4] = 0;
2115 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2116 SubstructureRedirectMask | SubstructureNotifyMask,
2117 (XEvent *)&xclient);
2121 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2123 /* There is no way of knowing reliably whether we are viewable;
2124 * so trap errors asynchronously around the XSetInputFocus call
2126 gdk_x11_display_error_trap_push (display);
2127 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2128 GDK_WINDOW_XID (window),
2131 gdk_x11_display_error_trap_pop_ignored (display);
2136 gdk_x11_window_set_type_hint (GdkWindow *window,
2137 GdkWindowTypeHint hint)
2139 GdkDisplay *display;
2142 if (GDK_WINDOW_DESTROYED (window) ||
2143 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2146 display = gdk_window_get_display (window);
2150 case GDK_WINDOW_TYPE_HINT_DIALOG:
2151 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2153 case GDK_WINDOW_TYPE_HINT_MENU:
2154 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2156 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2157 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2159 case GDK_WINDOW_TYPE_HINT_UTILITY:
2160 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2162 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2163 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2165 case GDK_WINDOW_TYPE_HINT_DOCK:
2166 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2168 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2169 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2171 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2172 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2174 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2175 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2177 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2178 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2180 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2181 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2183 case GDK_WINDOW_TYPE_HINT_COMBO:
2184 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2186 case GDK_WINDOW_TYPE_HINT_DND:
2187 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2190 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2192 case GDK_WINDOW_TYPE_HINT_NORMAL:
2193 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2197 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2198 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2199 XA_ATOM, 32, PropModeReplace,
2200 (guchar *)&atom, 1);
2203 static GdkWindowTypeHint
2204 gdk_x11_window_get_type_hint (GdkWindow *window)
2206 GdkDisplay *display;
2207 GdkWindowTypeHint type;
2210 gulong nitems_return;
2211 gulong bytes_after_return;
2212 guchar *data = NULL;
2214 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2216 if (GDK_WINDOW_DESTROYED (window) ||
2217 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2218 return GDK_WINDOW_TYPE_HINT_NORMAL;
2220 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2222 display = gdk_window_get_display (window);
2224 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2225 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2226 0, G_MAXLONG, False, XA_ATOM, &type_return,
2227 &format_return, &nitems_return, &bytes_after_return,
2230 if ((type_return == XA_ATOM) && (format_return == 32) &&
2231 (data) && (nitems_return == 1))
2233 Atom atom = *(Atom*)data;
2235 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2236 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2237 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2238 type = GDK_WINDOW_TYPE_HINT_MENU;
2239 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2240 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2241 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2242 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2243 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2244 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2245 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2246 type = GDK_WINDOW_TYPE_HINT_DOCK;
2247 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2248 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2249 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2250 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2251 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2252 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2253 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2254 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2255 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2256 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2257 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2258 type = GDK_WINDOW_TYPE_HINT_COMBO;
2259 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2260 type = GDK_WINDOW_TYPE_HINT_DND;
2263 if (type_return != None && data != NULL)
2271 gdk_wmspec_change_state (gboolean add,
2276 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2277 XClientMessageEvent xclient;
2279 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2280 #define _NET_WM_STATE_ADD 1 /* add/set property */
2281 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2283 memset (&xclient, 0, sizeof (xclient));
2284 xclient.type = ClientMessage;
2285 xclient.window = GDK_WINDOW_XID (window);
2286 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2287 xclient.format = 32;
2288 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2289 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2290 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2291 xclient.data.l[3] = 1; /* source indication */
2292 xclient.data.l[4] = 0;
2294 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2295 SubstructureRedirectMask | SubstructureNotifyMask,
2296 (XEvent *)&xclient);
2300 gdk_x11_window_set_modal_hint (GdkWindow *window,
2303 if (GDK_WINDOW_DESTROYED (window) ||
2304 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2307 window->modal_hint = modal;
2309 if (GDK_WINDOW_IS_MAPPED (window))
2310 gdk_wmspec_change_state (modal, window,
2311 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2316 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2317 gboolean skips_taskbar)
2319 GdkToplevelX11 *toplevel;
2321 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2323 if (GDK_WINDOW_DESTROYED (window) ||
2324 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2327 toplevel = _gdk_x11_window_get_toplevel (window);
2328 toplevel->skip_taskbar_hint = skips_taskbar;
2330 if (GDK_WINDOW_IS_MAPPED (window))
2331 gdk_wmspec_change_state (skips_taskbar, window,
2332 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2337 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2338 gboolean skips_pager)
2340 GdkToplevelX11 *toplevel;
2342 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2344 if (GDK_WINDOW_DESTROYED (window) ||
2345 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2348 toplevel = _gdk_x11_window_get_toplevel (window);
2349 toplevel->skip_pager_hint = skips_pager;
2351 if (GDK_WINDOW_IS_MAPPED (window))
2352 gdk_wmspec_change_state (skips_pager, window,
2353 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2358 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2361 GdkToplevelX11 *toplevel;
2363 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2365 if (GDK_WINDOW_DESTROYED (window) ||
2366 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2369 toplevel = _gdk_x11_window_get_toplevel (window);
2370 toplevel->urgency_hint = urgent;
2372 update_wm_hints (window, FALSE);
2376 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2377 const GdkGeometry *geometry,
2378 GdkWindowHints geom_mask)
2380 XSizeHints size_hints;
2382 if (GDK_WINDOW_DESTROYED (window) ||
2383 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2386 size_hints.flags = 0;
2388 if (geom_mask & GDK_HINT_POS)
2390 size_hints.flags |= PPosition;
2391 /* We need to initialize the following obsolete fields because KWM
2392 * apparently uses these fields if they are non-zero.
2399 if (geom_mask & GDK_HINT_USER_POS)
2401 size_hints.flags |= USPosition;
2404 if (geom_mask & GDK_HINT_USER_SIZE)
2406 size_hints.flags |= USSize;
2409 if (geom_mask & GDK_HINT_MIN_SIZE)
2411 size_hints.flags |= PMinSize;
2412 size_hints.min_width = geometry->min_width;
2413 size_hints.min_height = geometry->min_height;
2416 if (geom_mask & GDK_HINT_MAX_SIZE)
2418 size_hints.flags |= PMaxSize;
2419 size_hints.max_width = MAX (geometry->max_width, 1);
2420 size_hints.max_height = MAX (geometry->max_height, 1);
2423 if (geom_mask & GDK_HINT_BASE_SIZE)
2425 size_hints.flags |= PBaseSize;
2426 size_hints.base_width = geometry->base_width;
2427 size_hints.base_height = geometry->base_height;
2430 if (geom_mask & GDK_HINT_RESIZE_INC)
2432 size_hints.flags |= PResizeInc;
2433 size_hints.width_inc = geometry->width_inc;
2434 size_hints.height_inc = geometry->height_inc;
2437 if (geom_mask & GDK_HINT_ASPECT)
2439 size_hints.flags |= PAspect;
2440 if (geometry->min_aspect <= 1)
2442 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2443 size_hints.min_aspect.y = 65536;
2447 size_hints.min_aspect.x = 65536;
2448 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2450 if (geometry->max_aspect <= 1)
2452 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2453 size_hints.max_aspect.y = 65536;
2457 size_hints.max_aspect.x = 65536;
2458 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2462 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2464 size_hints.flags |= PWinGravity;
2465 size_hints.win_gravity = geometry->win_gravity;
2468 /* FIXME: Would it be better to delete this property if
2469 * geom_mask == 0? It would save space on the server
2471 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2472 GDK_WINDOW_XID (window),
2477 gdk_window_get_geometry_hints (GdkWindow *window,
2478 GdkGeometry *geometry,
2479 GdkWindowHints *geom_mask)
2481 XSizeHints *size_hints;
2482 glong junk_supplied_mask = 0;
2484 g_return_if_fail (GDK_IS_WINDOW (window));
2485 g_return_if_fail (geometry != NULL);
2486 g_return_if_fail (geom_mask != NULL);
2490 if (GDK_WINDOW_DESTROYED (window) ||
2491 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2494 size_hints = XAllocSizeHints ();
2498 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2499 GDK_WINDOW_XID (window),
2501 &junk_supplied_mask))
2502 size_hints->flags = 0;
2504 if (size_hints->flags & PMinSize)
2506 *geom_mask |= GDK_HINT_MIN_SIZE;
2507 geometry->min_width = size_hints->min_width;
2508 geometry->min_height = size_hints->min_height;
2511 if (size_hints->flags & PMaxSize)
2513 *geom_mask |= GDK_HINT_MAX_SIZE;
2514 geometry->max_width = MAX (size_hints->max_width, 1);
2515 geometry->max_height = MAX (size_hints->max_height, 1);
2518 if (size_hints->flags & PResizeInc)
2520 *geom_mask |= GDK_HINT_RESIZE_INC;
2521 geometry->width_inc = size_hints->width_inc;
2522 geometry->height_inc = size_hints->height_inc;
2525 if (size_hints->flags & PAspect)
2527 *geom_mask |= GDK_HINT_ASPECT;
2529 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2530 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2533 if (size_hints->flags & PWinGravity)
2535 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2536 geometry->win_gravity = size_hints->win_gravity;
2543 utf8_is_latin1 (const gchar *str)
2545 const char *p = str;
2549 gunichar ch = g_utf8_get_char (p);
2554 p = g_utf8_next_char (p);
2560 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2561 * convertable to STRING, otherwise, set it as compound text
2564 set_text_property (GdkDisplay *display,
2567 const gchar *utf8_str)
2569 gchar *prop_text = NULL;
2573 gboolean is_compound_text;
2575 if (utf8_is_latin1 (utf8_str))
2577 prop_type = XA_STRING;
2578 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2579 prop_length = prop_text ? strlen (prop_text) : 0;
2581 is_compound_text = FALSE;
2587 gdk_x11_display_utf8_to_compound_text (display,
2588 utf8_str, &gdk_type, &prop_format,
2589 (guchar **)&prop_text, &prop_length);
2590 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2591 is_compound_text = TRUE;
2596 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2599 prop_type, prop_format,
2600 PropModeReplace, (guchar *)prop_text,
2603 if (is_compound_text)
2604 gdk_x11_free_compound_text ((guchar *)prop_text);
2610 /* Set WM_NAME and _NET_WM_NAME
2613 set_wm_name (GdkDisplay *display,
2617 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2618 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2619 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2620 PropModeReplace, (guchar *)name, strlen (name));
2622 set_text_property (display, xwindow,
2623 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2628 gdk_x11_window_set_title (GdkWindow *window,
2631 GdkDisplay *display;
2635 g_return_if_fail (title != NULL);
2637 if (GDK_WINDOW_DESTROYED (window) ||
2638 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2641 display = gdk_window_get_display (window);
2642 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2643 xwindow = GDK_WINDOW_XID (window);
2645 set_wm_name (display, xwindow, title);
2647 if (!gdk_window_icon_name_set (window))
2649 XChangeProperty (xdisplay, xwindow,
2650 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2651 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2652 PropModeReplace, (guchar *)title, strlen (title));
2654 set_text_property (display, xwindow,
2655 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2661 gdk_x11_window_set_role (GdkWindow *window,
2664 GdkDisplay *display;
2666 display = gdk_window_get_display (window);
2668 if (GDK_WINDOW_DESTROYED (window) ||
2669 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2673 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2674 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2675 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2677 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2678 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2682 gdk_x11_window_set_startup_id (GdkWindow *window,
2683 const gchar *startup_id)
2685 GdkDisplay *display;
2687 g_return_if_fail (GDK_IS_WINDOW (window));
2689 display = gdk_window_get_display (window);
2691 if (GDK_WINDOW_DESTROYED (window) ||
2692 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2696 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2697 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2698 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2699 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2701 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2702 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2706 gdk_x11_window_set_transient_for (GdkWindow *window,
2709 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2710 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2711 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2712 GDK_WINDOW_XID (window),
2713 GDK_WINDOW_XID (parent));
2717 gdk_window_x11_set_back_color (GdkWindow *window,
2723 GdkVisual *visual = gdk_window_get_visual (window);
2725 /* I suppose we could handle these, but that'd require fiddling with
2726 * xrender formats... */
2730 switch (visual->type)
2732 case GDK_VISUAL_DIRECT_COLOR:
2733 case GDK_VISUAL_TRUE_COLOR:
2735 /* If bits not used for color are used for something other than padding,
2736 * it's likely alpha, so we set them to 1s.
2738 guint padding, pixel;
2740 /* Shifting by >= width-of-type isn't defined in C */
2741 if (visual->depth >= 32)
2744 padding = ((~(guint32)0)) << visual->depth;
2746 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2748 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2749 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2750 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2752 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2753 GDK_WINDOW_XID (window), pixel);
2757 /* These require fiddling with the colormap, and as they're essentially unused
2758 * we're just gonna skip them for now.
2760 case GDK_VISUAL_PSEUDO_COLOR:
2761 case GDK_VISUAL_GRAYSCALE:
2762 case GDK_VISUAL_STATIC_GRAY:
2763 case GDK_VISUAL_STATIC_COLOR:
2772 matrix_is_identity (cairo_matrix_t *matrix)
2774 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2775 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2776 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2780 gdk_window_x11_set_background (GdkWindow *window,
2781 cairo_pattern_t *pattern)
2784 cairo_surface_t *surface;
2785 cairo_matrix_t matrix;
2787 if (GDK_WINDOW_DESTROYED (window))
2790 if (pattern == NULL)
2794 /* X throws BadMatch if the parent has a different visual when
2795 * using ParentRelative */
2796 parent = gdk_window_get_parent (window);
2797 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2798 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2799 GDK_WINDOW_XID (window), ParentRelative);
2801 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2802 GDK_WINDOW_XID (window), None);
2806 switch (cairo_pattern_get_type (pattern))
2808 case CAIRO_PATTERN_TYPE_SOLID:
2809 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2810 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2813 case CAIRO_PATTERN_TYPE_SURFACE:
2814 cairo_pattern_get_matrix (pattern, &matrix);
2815 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2816 matrix_is_identity (&matrix) &&
2817 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2818 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2819 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2823 cairo_surface_get_device_offset (surface, &x, &y);
2824 /* XXX: This still bombs for non-pixmaps, but there's no way to
2825 * detect we're not a pixmap in Cairo... */
2826 if (x == 0.0 && y == 0.0)
2828 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2829 GDK_WINDOW_XID (window),
2830 cairo_xlib_surface_get_drawable (surface));
2835 case CAIRO_PATTERN_TYPE_LINEAR:
2836 case CAIRO_PATTERN_TYPE_RADIAL:
2838 /* fallback: just use black */
2842 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2843 GDK_WINDOW_XID (window), None);
2847 gdk_window_x11_set_device_cursor (GdkWindow *window,
2851 GdkWindowImplX11 *impl;
2853 g_return_if_fail (GDK_IS_WINDOW (window));
2854 g_return_if_fail (GDK_IS_DEVICE (device));
2856 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2859 g_hash_table_remove (impl->device_cursor, device);
2862 _gdk_x11_cursor_update_theme (cursor);
2863 g_hash_table_replace (impl->device_cursor,
2864 device, g_object_ref (cursor));
2867 if (!GDK_WINDOW_DESTROYED (window))
2868 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2872 _gdk_x11_window_get_cursor (GdkWindow *window)
2874 GdkWindowImplX11 *impl;
2876 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2878 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2880 return impl->cursor;
2884 gdk_window_x11_get_geometry (GdkWindow *window,
2895 guint tborder_width;
2898 if (!GDK_WINDOW_DESTROYED (window))
2900 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2901 GDK_WINDOW_XID (window),
2902 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2916 gdk_window_x11_get_root_coords (GdkWindow *window,
2927 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2928 GDK_WINDOW_XID (window),
2929 GDK_WINDOW_XROOTWIN (window),
2942 gdk_x11_window_get_root_origin (GdkWindow *window,
2948 gdk_window_get_frame_extents (window, &rect);
2958 gdk_x11_window_get_frame_extents (GdkWindow *window,
2961 GdkDisplay *display;
2962 GdkWindowImplX11 *impl;
2973 gulong nitems_return;
2974 gulong bytes_after_return;
2977 guint ww, wh, wb, wd;
2979 gboolean got_frame_extents = FALSE;
2981 g_return_if_fail (rect != NULL);
2988 while (window->parent && (window->parent)->parent)
2989 window = window->parent;
2991 /* Refine our fallback answer a bit using local information */
2992 rect->x = window->x;
2993 rect->y = window->y;
2994 rect->width = window->width;
2995 rect->height = window->height;
2997 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2998 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
3004 display = gdk_window_get_display (window);
3006 gdk_x11_display_error_trap_push (display);
3008 xwindow = GDK_WINDOW_XID (window);
3010 /* first try: use _NET_FRAME_EXTENTS */
3011 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3012 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
3013 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
3014 gdk_x11_get_xatom_by_name_for_display (display,
3015 "_NET_FRAME_EXTENTS"),
3016 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
3017 &format_return, &nitems_return, &bytes_after_return,
3021 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
3022 (nitems_return == 4) && (data))
3024 gulong *ldata = (gulong *) data;
3025 got_frame_extents = TRUE;
3027 /* try to get the real client window geometry */
3028 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3029 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
3030 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
3031 xwindow, root, 0, 0, &wx, &wy, &child))
3039 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
3040 rect->x -= ldata[0];
3041 rect->y -= ldata[2];
3042 rect->width += ldata[0] + ldata[1];
3043 rect->height += ldata[2] + ldata[3];
3050 if (got_frame_extents)
3053 /* no frame extents property available, which means we either have a WM that
3054 is not EWMH compliant or is broken - try fallback and walk up the window
3055 tree to get our window's parent which hopefully is the window frame */
3057 /* use NETWM_VIRTUAL_ROOTS if available */
3058 root = GDK_WINDOW_XROOTWIN (window);
3060 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3061 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
3062 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
3063 gdk_x11_get_xatom_by_name_for_display (display,
3064 "_NET_VIRTUAL_ROOTS"),
3065 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3066 &format_return, &nitems_return, &bytes_after_return,
3070 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
3072 nvroots = nitems_return;
3073 vroots = (Window *)data;
3077 xparent = GDK_WINDOW_XID (window);
3083 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3085 &children, &nchildren))
3091 /* check virtual roots */
3092 for (i = 0; i < nvroots; i++)
3094 if (xparent == vroots[i])
3101 while (xparent != root);
3103 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3104 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3116 gdk_x11_display_error_trap_pop_ignored (display);
3120 gdk_window_x11_get_device_state (GdkWindow *window,
3124 GdkModifierType *mask)
3128 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3130 if (GDK_WINDOW_DESTROYED (window))
3133 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3137 return child != NULL;
3141 gdk_window_x11_get_events (GdkWindow *window)
3143 XWindowAttributes attrs;
3144 GdkEventMask event_mask;
3145 GdkEventMask filtered;
3147 if (GDK_WINDOW_DESTROYED (window))
3151 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3152 GDK_WINDOW_XID (window),
3154 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3155 /* if property change was filtered out before, keep it filtered out */
3156 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3157 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3163 gdk_window_x11_set_events (GdkWindow *window,
3164 GdkEventMask event_mask)
3166 long xevent_mask = 0;
3168 if (!GDK_WINDOW_DESTROYED (window))
3170 GdkX11Display *display_x11;
3172 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3173 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3175 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3176 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3177 GDK_WINDOW_XID (window), event_mask,
3183 do_shape_combine_region (GdkWindow *window,
3184 const cairo_region_t *shape_region,
3189 if (GDK_WINDOW_DESTROYED (window))
3192 if (shape_region == NULL)
3194 /* Use NULL mask to unset the shape */
3195 if (shape == ShapeBounding
3196 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3197 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3199 if (shape == ShapeBounding)
3201 _gdk_x11_window_tmp_unset_parent_bg (window);
3202 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3204 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3205 GDK_WINDOW_XID (window),
3210 if (shape == ShapeBounding)
3212 _gdk_x11_window_tmp_reset_parent_bg (window);
3213 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3219 if (shape == ShapeBounding
3220 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3221 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3224 XRectangle *xrects = NULL;
3226 _gdk_x11_region_get_xrectangles (shape_region,
3230 if (shape == ShapeBounding)
3232 _gdk_x11_window_tmp_unset_parent_bg (window);
3233 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3235 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3236 GDK_WINDOW_XID (window),
3243 if (shape == ShapeBounding)
3245 _gdk_x11_window_tmp_reset_parent_bg (window);
3246 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3254 gdk_window_x11_shape_combine_region (GdkWindow *window,
3255 const cairo_region_t *shape_region,
3259 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3263 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3264 const cairo_region_t *shape_region,
3269 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3275 gdk_x11_window_set_override_redirect (GdkWindow *window,
3276 gboolean override_redirect)
3278 XSetWindowAttributes attr;
3280 if (!GDK_WINDOW_DESTROYED (window) &&
3281 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3283 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3285 attr.override_redirect = (override_redirect? True : False);
3286 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3287 GDK_WINDOW_XID (window),
3291 impl->override_redirect = attr.override_redirect;
3296 gdk_x11_window_set_accept_focus (GdkWindow *window,
3297 gboolean accept_focus)
3299 accept_focus = accept_focus != FALSE;
3301 if (window->accept_focus != accept_focus)
3303 window->accept_focus = accept_focus;
3305 if (!GDK_WINDOW_DESTROYED (window) &&
3306 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3307 update_wm_hints (window, FALSE);
3312 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3313 gboolean focus_on_map)
3315 focus_on_map = focus_on_map != FALSE;
3317 if (window->focus_on_map != focus_on_map)
3319 window->focus_on_map = focus_on_map;
3321 if ((!GDK_WINDOW_DESTROYED (window)) &&
3322 (!window->focus_on_map) &&
3323 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3324 gdk_x11_window_set_user_time (window, 0);
3329 * gdk_x11_window_set_user_time:
3330 * @window: (type GdkX11Window): A toplevel #GdkWindow
3331 * @timestamp: An XServer timestamp to which the property should be set
3333 * The application can use this call to update the _NET_WM_USER_TIME
3334 * property on a toplevel window. This property stores an Xserver
3335 * time which represents the time of the last user input event
3336 * received for this window. This property may be used by the window
3337 * manager to alter the focus, stacking, and/or placement behavior of
3338 * windows when they are mapped depending on whether the new window
3339 * was created by a user action or is a "pop-up" window activated by a
3340 * timer or some other event.
3342 * Note that this property is automatically updated by GDK, so this
3343 * function should only be used by applications which handle input
3344 * events bypassing GDK.
3349 gdk_x11_window_set_user_time (GdkWindow *window,
3352 GdkDisplay *display;
3353 GdkX11Display *display_x11;
3354 GdkToplevelX11 *toplevel;
3355 glong timestamp_long = (glong)timestamp;
3358 if (GDK_WINDOW_DESTROYED (window) ||
3359 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3362 display = gdk_window_get_display (window);
3363 display_x11 = GDK_X11_DISPLAY (display);
3364 toplevel = _gdk_x11_window_get_toplevel (window);
3368 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3372 if (toplevel->focus_window != None &&
3373 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3374 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3375 xid = toplevel->focus_window;
3377 xid = GDK_WINDOW_XID (window);
3379 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3380 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3381 XA_CARDINAL, 32, PropModeReplace,
3382 (guchar *)×tamp_long, 1);
3384 if (timestamp_long != GDK_CURRENT_TIME &&
3385 (display_x11->user_time == GDK_CURRENT_TIME ||
3386 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3387 display_x11->user_time = timestamp_long;
3390 toplevel->user_time = timestamp_long;
3394 * gdk_x11_window_set_utf8_property:
3395 * @window: (type GdkX11Window): a #GdkWindow
3396 * @name: Property name, will be interned as an X atom
3397 * @value: (allow-none): Property value, or %NULL to delete
3399 * This function modifies or removes an arbitrary X11 window
3400 * property of type UTF8_STRING. If the given @window is
3401 * not a toplevel window, it is ignored.
3406 gdk_x11_window_set_utf8_property (GdkWindow *window,
3410 GdkDisplay *display;
3412 if (!WINDOW_IS_TOPLEVEL (window))
3415 display = gdk_window_get_display (window);
3419 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3420 GDK_WINDOW_XID (window),
3421 gdk_x11_get_xatom_by_name_for_display (display, name),
3422 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3423 PropModeReplace, (guchar *)value, strlen (value));
3427 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3428 GDK_WINDOW_XID (window),
3429 gdk_x11_get_xatom_by_name_for_display (display, name));
3434 * gdk_x11_window_set_hide_titlebar_when_maximized:
3435 * @window: (type GdkX11Window): a #GdkWindow
3436 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3439 * Set a hint for the window manager, requesting that the titlebar
3440 * should be hidden when the window is maximized.
3442 * Note that this property is automatically updated by GTK+, so this
3443 * function should only be used by applications which do not use GTK+
3444 * to create toplevel windows.
3449 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3450 gboolean hide_titlebar_when_maximized)
3452 GdkDisplay *display;
3454 if (!WINDOW_IS_TOPLEVEL (window))
3457 display = gdk_window_get_display (window);
3459 if (hide_titlebar_when_maximized)
3462 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3463 GDK_WINDOW_XID (window),
3464 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3466 PropModeReplace, (guchar *)&hide, 1);
3470 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3471 GDK_WINDOW_XID (window),
3472 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3477 * gdk_x11_window_set_theme_variant:
3478 * @window: (type GdkX11Window): a #GdkWindow
3479 * @variant: the theme variant to export
3481 * GTK+ applications can request a dark theme variant. In order to
3482 * make other applications - namely window managers using GTK+ for
3483 * themeing - aware of this choice, GTK+ uses this function to
3484 * export the requested theme variant as _GTK_THEME_VARIANT property
3485 * on toplevel windows.
3487 * Note that this property is automatically updated by GTK+, so this
3488 * function should only be used by applications which do not use GTK+
3489 * to create toplevel windows.
3494 gdk_x11_window_set_theme_variant (GdkWindow *window,
3497 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3500 #define GDK_SELECTION_MAX_SIZE(display) \
3502 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3503 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3504 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3507 gdk_window_update_icon (GdkWindow *window,
3510 GdkToplevelX11 *toplevel;
3511 GdkPixbuf *best_icon;
3515 toplevel = _gdk_x11_window_get_toplevel (window);
3517 if (toplevel->icon_pixmap != NULL)
3519 cairo_surface_destroy (toplevel->icon_pixmap);
3520 toplevel->icon_pixmap = NULL;
3523 if (toplevel->icon_mask != NULL)
3525 cairo_surface_destroy (toplevel->icon_mask);
3526 toplevel->icon_mask = NULL;
3529 #define IDEAL_SIZE 48
3531 best_size = G_MAXINT;
3533 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3535 GdkPixbuf *pixbuf = tmp_list->data;
3538 /* average width and height - if someone passes in a rectangular
3539 * icon they deserve what they get.
3541 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3544 if (best_icon == NULL)
3551 /* icon is better if it's 32 pixels or larger, and closer to
3552 * the ideal size than the current best.
3555 (ABS (best_size - IDEAL_SIZE) <
3556 ABS (this - IDEAL_SIZE)))
3566 int width = gdk_pixbuf_get_width (best_icon);
3567 int height = gdk_pixbuf_get_height (best_icon);
3570 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3574 cr = cairo_create (toplevel->icon_pixmap);
3575 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3576 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3577 if (gdk_pixbuf_get_has_alpha (best_icon))
3579 /* Saturate the image, so it has bilevel alpha */
3580 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3582 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3584 cairo_pop_group_to_source (cr);
3589 if (gdk_pixbuf_get_has_alpha (best_icon))
3591 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3595 cr = cairo_create (toplevel->icon_mask);
3596 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3597 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3603 update_wm_hints (window, FALSE);
3607 gdk_x11_window_set_icon_list (GdkWindow *window,
3616 gint width, height, stride;
3619 GdkDisplay *display;
3622 if (GDK_WINDOW_DESTROYED (window) ||
3623 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3626 display = gdk_window_get_display (window);
3634 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3636 width = gdk_pixbuf_get_width (pixbuf);
3637 height = gdk_pixbuf_get_height (pixbuf);
3639 /* silently ignore overlarge icons */
3640 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3642 g_warning ("gdk_window_set_icon_list: icons too large");
3647 size += 2 + width * height;
3649 l = g_list_next (l);
3652 data = g_malloc (size * sizeof (gulong));
3660 width = gdk_pixbuf_get_width (pixbuf);
3661 height = gdk_pixbuf_get_height (pixbuf);
3662 stride = gdk_pixbuf_get_rowstride (pixbuf);
3663 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3668 pixels = gdk_pixbuf_get_pixels (pixbuf);
3670 for (y = 0; y < height; y++)
3672 for (x = 0; x < width; x++)
3676 r = pixels[y*stride + x*n_channels + 0];
3677 g = pixels[y*stride + x*n_channels + 1];
3678 b = pixels[y*stride + x*n_channels + 2];
3679 if (n_channels >= 4)
3680 a = pixels[y*stride + x*n_channels + 3];
3684 *p++ = a << 24 | r << 16 | g << 8 | b ;
3688 l = g_list_next (l);
3694 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3695 GDK_WINDOW_XID (window),
3696 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3699 (guchar*) data, size);
3703 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3704 GDK_WINDOW_XID (window),
3705 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3710 gdk_window_update_icon (window, pixbufs);
3714 gdk_window_icon_name_set (GdkWindow *window)
3716 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3717 g_quark_from_static_string ("gdk-icon-name-set")));
3721 gdk_x11_window_set_icon_name (GdkWindow *window,
3724 GdkDisplay *display;
3726 if (GDK_WINDOW_DESTROYED (window) ||
3727 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3730 display = gdk_window_get_display (window);
3732 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3733 GUINT_TO_POINTER (name != NULL));
3737 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3738 GDK_WINDOW_XID (window),
3739 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3740 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3741 PropModeReplace, (guchar *)name, strlen (name));
3743 set_text_property (display, GDK_WINDOW_XID (window),
3744 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3749 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3750 GDK_WINDOW_XID (window),
3751 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3752 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3753 GDK_WINDOW_XID (window),
3754 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3759 gdk_x11_window_iconify (GdkWindow *window)
3761 if (GDK_WINDOW_DESTROYED (window) ||
3762 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3765 if (GDK_WINDOW_IS_MAPPED (window))
3767 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3768 GDK_WINDOW_XID (window),
3769 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3773 /* Flip our client side flag, the real work happens on map. */
3774 gdk_synthesize_window_state (window,
3776 GDK_WINDOW_STATE_ICONIFIED);
3777 gdk_wmspec_change_state (TRUE, window,
3778 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3784 gdk_x11_window_deiconify (GdkWindow *window)
3786 if (GDK_WINDOW_DESTROYED (window) ||
3787 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3790 if (GDK_WINDOW_IS_MAPPED (window))
3792 gdk_window_show (window);
3793 gdk_wmspec_change_state (FALSE, window,
3794 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3799 /* Flip our client side flag, the real work happens on map. */
3800 gdk_synthesize_window_state (window,
3801 GDK_WINDOW_STATE_ICONIFIED,
3803 gdk_wmspec_change_state (FALSE, window,
3804 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3810 gdk_x11_window_stick (GdkWindow *window)
3812 if (GDK_WINDOW_DESTROYED (window) ||
3813 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3816 if (GDK_WINDOW_IS_MAPPED (window))
3818 /* "stick" means stick to all desktops _and_ do not scroll with the
3819 * viewport. i.e. glue to the monitor glass in all cases.
3822 XClientMessageEvent xclient;
3824 /* Request stick during viewport scroll */
3825 gdk_wmspec_change_state (TRUE, window,
3826 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3829 /* Request desktop 0xFFFFFFFF */
3830 memset (&xclient, 0, sizeof (xclient));
3831 xclient.type = ClientMessage;
3832 xclient.window = GDK_WINDOW_XID (window);
3833 xclient.display = GDK_WINDOW_XDISPLAY (window);
3834 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3836 xclient.format = 32;
3838 xclient.data.l[0] = 0xFFFFFFFF;
3839 xclient.data.l[1] = 0;
3840 xclient.data.l[2] = 0;
3841 xclient.data.l[3] = 0;
3842 xclient.data.l[4] = 0;
3844 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3845 SubstructureRedirectMask | SubstructureNotifyMask,
3846 (XEvent *)&xclient);
3850 /* Flip our client side flag, the real work happens on map. */
3851 gdk_synthesize_window_state (window,
3853 GDK_WINDOW_STATE_STICKY);
3858 gdk_x11_window_unstick (GdkWindow *window)
3860 if (GDK_WINDOW_DESTROYED (window) ||
3861 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3864 if (GDK_WINDOW_IS_MAPPED (window))
3866 /* Request unstick from viewport */
3867 gdk_wmspec_change_state (FALSE, window,
3868 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3871 move_to_current_desktop (window);
3875 /* Flip our client side flag, the real work happens on map. */
3876 gdk_synthesize_window_state (window,
3877 GDK_WINDOW_STATE_STICKY,
3884 gdk_x11_window_maximize (GdkWindow *window)
3886 if (GDK_WINDOW_DESTROYED (window) ||
3887 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3890 if (GDK_WINDOW_IS_MAPPED (window))
3891 gdk_wmspec_change_state (TRUE, window,
3892 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3893 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3895 gdk_synthesize_window_state (window,
3897 GDK_WINDOW_STATE_MAXIMIZED);
3901 gdk_x11_window_unmaximize (GdkWindow *window)
3903 if (GDK_WINDOW_DESTROYED (window) ||
3904 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3907 if (GDK_WINDOW_IS_MAPPED (window))
3908 gdk_wmspec_change_state (FALSE, window,
3909 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3910 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3912 gdk_synthesize_window_state (window,
3913 GDK_WINDOW_STATE_MAXIMIZED,
3918 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3920 if (GDK_WINDOW_DESTROYED (window) ||
3921 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3924 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3925 * to which monitors so span across when the window is fullscreen, but it's
3926 * not a state in itself so this would have no effect if the window is not
3930 if (GDK_WINDOW_IS_MAPPED (window))
3932 XClientMessageEvent xclient;
3933 gint gdk_monitors[4];
3936 memset (&xclient, 0, sizeof (xclient));
3937 xclient.type = ClientMessage;
3938 xclient.window = GDK_WINDOW_XID (window);
3939 xclient.display = GDK_WINDOW_XDISPLAY (window);
3940 xclient.format = 32;
3942 switch (window->fullscreen_mode)
3944 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3946 /* FIXME: This is not part of the EWMH spec!
3948 * There is no documented mechanism to remove the property
3949 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3950 * invalid, largest possible value.
3952 * When given values larger than actual possible monitor values, most
3953 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3954 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3957 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3959 * Note, this (non documented) mechanism is unlikely to be an issue
3960 * as it's used only for transitionning back from "all monitors" to
3961 * "current monitor" mode.
3963 * Applications who don't change the default mode won't trigger this
3966 for (i = 0; i < 4; ++i)
3967 xclient.data.l[i] = G_MAXLONG;
3971 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3973 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3978 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3979 for (i = 0; i < 4; ++i)
3981 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3983 /* Sanity check, if XINERAMA is not available, we could have invalid
3984 * negative values for the XINERAMA indices.
3986 if (xclient.data.l[i] < 0)
3988 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3995 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3996 window->fullscreen_mode);
4000 /* Send fullscreen monitors client message */
4001 xclient.data.l[4] = 1; /* source indication */
4002 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
4003 "_NET_WM_FULLSCREEN_MONITORS");
4004 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
4005 SubstructureRedirectMask | SubstructureNotifyMask,
4006 (XEvent *)&xclient);
4011 gdk_x11_window_fullscreen (GdkWindow *window)
4013 if (GDK_WINDOW_DESTROYED (window) ||
4014 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4017 if (GDK_WINDOW_IS_MAPPED (window))
4019 gdk_wmspec_change_state (TRUE, window,
4020 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4022 /* Actual XRandR layout may have change since we computed the fullscreen
4023 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
4025 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
4026 gdk_x11_window_apply_fullscreen_mode (window);
4029 gdk_synthesize_window_state (window,
4031 GDK_WINDOW_STATE_FULLSCREEN);
4035 gdk_x11_window_unfullscreen (GdkWindow *window)
4037 if (GDK_WINDOW_DESTROYED (window) ||
4038 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4041 if (GDK_WINDOW_IS_MAPPED (window))
4042 gdk_wmspec_change_state (FALSE, window,
4043 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4047 gdk_synthesize_window_state (window,
4048 GDK_WINDOW_STATE_FULLSCREEN,
4053 gdk_x11_window_set_keep_above (GdkWindow *window,
4056 g_return_if_fail (GDK_IS_WINDOW (window));
4058 if (GDK_WINDOW_DESTROYED (window) ||
4059 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4062 if (GDK_WINDOW_IS_MAPPED (window))
4065 gdk_wmspec_change_state (FALSE, window,
4066 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4068 gdk_wmspec_change_state (setting, window,
4069 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4073 gdk_synthesize_window_state (window,
4074 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4075 setting ? GDK_WINDOW_STATE_ABOVE : 0);
4079 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
4081 g_return_if_fail (GDK_IS_WINDOW (window));
4083 if (GDK_WINDOW_DESTROYED (window) ||
4084 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4087 if (GDK_WINDOW_IS_MAPPED (window))
4090 gdk_wmspec_change_state (FALSE, window,
4091 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4093 gdk_wmspec_change_state (setting, window,
4094 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4098 gdk_synthesize_window_state (window,
4099 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4100 setting ? GDK_WINDOW_STATE_BELOW : 0);
4104 gdk_x11_window_get_group (GdkWindow *window)
4106 GdkToplevelX11 *toplevel;
4108 if (GDK_WINDOW_DESTROYED (window) ||
4109 !WINDOW_IS_TOPLEVEL (window))
4112 toplevel = _gdk_x11_window_get_toplevel (window);
4114 return toplevel->group_leader;
4118 gdk_x11_window_set_group (GdkWindow *window,
4121 GdkToplevelX11 *toplevel;
4123 g_return_if_fail (GDK_IS_WINDOW (window));
4124 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4125 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4127 if (GDK_WINDOW_DESTROYED (window) ||
4128 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4129 !WINDOW_IS_TOPLEVEL (window))
4132 toplevel = _gdk_x11_window_get_toplevel (window);
4135 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4137 if (toplevel->group_leader != leader)
4139 if (toplevel->group_leader)
4140 g_object_unref (toplevel->group_leader);
4141 toplevel->group_leader = g_object_ref (leader);
4142 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4145 update_wm_hints (window, FALSE);
4148 static MotifWmHints *
4149 gdk_window_get_mwm_hints (GdkWindow *window)
4151 GdkDisplay *display;
4152 Atom hints_atom = None;
4159 if (GDK_WINDOW_DESTROYED (window))
4162 display = gdk_window_get_display (window);
4164 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4166 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4167 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4168 False, AnyPropertyType, &type, &format, &nitems,
4169 &bytes_after, &data);
4174 return (MotifWmHints *)data;
4178 gdk_window_set_mwm_hints (GdkWindow *window,
4179 MotifWmHints *new_hints)
4181 GdkDisplay *display;
4182 Atom hints_atom = None;
4184 MotifWmHints *hints;
4190 if (GDK_WINDOW_DESTROYED (window))
4193 display = gdk_window_get_display (window);
4195 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4197 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4198 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4199 False, AnyPropertyType, &type, &format, &nitems,
4200 &bytes_after, &data);
4206 hints = (MotifWmHints *)data;
4208 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4210 hints->flags |= MWM_HINTS_FUNCTIONS;
4211 hints->functions = new_hints->functions;
4213 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4215 hints->flags |= MWM_HINTS_DECORATIONS;
4216 hints->decorations = new_hints->decorations;
4220 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4221 hints_atom, hints_atom, 32, PropModeReplace,
4222 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4224 if (hints != new_hints)
4229 gdk_x11_window_set_decorations (GdkWindow *window,
4230 GdkWMDecoration decorations)
4234 if (GDK_WINDOW_DESTROYED (window) ||
4235 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4238 /* initialize to zero to avoid writing uninitialized data to socket */
4239 memset(&hints, 0, sizeof(hints));
4240 hints.flags = MWM_HINTS_DECORATIONS;
4241 hints.decorations = decorations;
4243 gdk_window_set_mwm_hints (window, &hints);
4247 gdk_x11_window_get_decorations(GdkWindow *window,
4248 GdkWMDecoration *decorations)
4250 MotifWmHints *hints;
4251 gboolean result = FALSE;
4253 if (GDK_WINDOW_DESTROYED (window) ||
4254 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4257 hints = gdk_window_get_mwm_hints (window);
4261 if (hints->flags & MWM_HINTS_DECORATIONS)
4264 *decorations = hints->decorations;
4275 gdk_x11_window_set_functions (GdkWindow *window,
4276 GdkWMFunction functions)
4280 g_return_if_fail (GDK_IS_WINDOW (window));
4282 if (GDK_WINDOW_DESTROYED (window) ||
4283 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4286 /* initialize to zero to avoid writing uninitialized data to socket */
4287 memset(&hints, 0, sizeof(hints));
4288 hints.flags = MWM_HINTS_FUNCTIONS;
4289 hints.functions = functions;
4291 gdk_window_set_mwm_hints (window, &hints);
4295 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4299 cairo_region_t *shape;
4307 /* Note that XShapeGetRectangles returns NULL in two situations:
4308 * - the server doesn't support the SHAPE extension
4309 * - the shape is empty
4311 * Since we can't discriminate these here, we always return
4312 * an empty shape. It is the callers responsibility to check
4313 * whether the server supports the SHAPE extensions beforehand.
4315 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4318 return cairo_region_create (); /* Empty */
4320 if (ord != YXBanded)
4322 /* This really shouldn't happen with any xserver, as they
4323 * generally convert regions to YXBanded internally
4325 g_warning ("non YXBanded shape masks not supported");
4330 rl = g_new (GdkRectangle, rn);
4331 for (i = 0; i < rn; i++)
4335 rl[i].width = xrl[i].width;
4336 rl[i].height = xrl[i].height;
4340 shape = cairo_region_create_rectangles (rl, rn);
4347 static cairo_region_t *
4348 gdk_x11_window_get_shape (GdkWindow *window)
4350 if (!GDK_WINDOW_DESTROYED (window) &&
4351 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4352 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4353 GDK_WINDOW_XID (window),
4359 static cairo_region_t *
4360 gdk_x11_window_get_input_shape (GdkWindow *window)
4362 #if defined(ShapeInput)
4363 if (!GDK_WINDOW_DESTROYED (window) &&
4364 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4365 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4366 GDK_WINDOW_XID (window),
4374 gdk_window_set_static_bit_gravity (GdkWindow *window,
4377 XSetWindowAttributes xattributes;
4378 guint xattributes_mask = 0;
4380 g_return_if_fail (GDK_IS_WINDOW (window));
4382 if (window->input_only)
4385 xattributes.bit_gravity = StaticGravity;
4386 xattributes_mask |= CWBitGravity;
4387 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4388 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4389 GDK_WINDOW_XID (window),
4390 CWBitGravity, &xattributes);
4394 gdk_window_set_static_win_gravity (GdkWindow *window,
4397 XSetWindowAttributes xattributes;
4399 g_return_if_fail (GDK_IS_WINDOW (window));
4401 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4403 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4404 GDK_WINDOW_XID (window),
4405 CWWinGravity, &xattributes);
4409 gdk_window_x11_set_static_gravities (GdkWindow *window,
4410 gboolean use_static)
4414 if (!use_static == !window->guffaw_gravity)
4417 window->guffaw_gravity = use_static;
4419 if (!GDK_WINDOW_DESTROYED (window))
4421 gdk_window_set_static_bit_gravity (window, use_static);
4423 tmp_list = window->children;
4426 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4428 tmp_list = tmp_list->next;
4435 /* From the WM spec */
4436 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4437 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4438 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4439 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4440 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4441 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4442 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4443 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4444 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4445 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4446 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4447 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4450 wmspec_send_message (GdkDisplay *display,
4457 XClientMessageEvent xclient;
4459 memset (&xclient, 0, sizeof (xclient));
4460 xclient.type = ClientMessage;
4461 xclient.window = GDK_WINDOW_XID (window);
4462 xclient.message_type =
4463 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4464 xclient.format = 32;
4465 xclient.data.l[0] = root_x;
4466 xclient.data.l[1] = root_y;
4467 xclient.data.l[2] = action;
4468 xclient.data.l[3] = button;
4469 xclient.data.l[4] = 1; /* source indication */
4471 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4472 SubstructureRedirectMask | SubstructureNotifyMask,
4473 (XEvent *)&xclient);
4477 handle_wmspec_button_release (GdkDisplay *display,
4480 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4483 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4484 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4485 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4487 if (xevent->xany.type == GenericEvent)
4488 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4491 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4493 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4495 if ((xevent->xany.type == ButtonRelease &&
4496 xevent->xbutton.button == display_x11->wm_moveresize_button)
4497 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4499 (xevent->xany.type == GenericEvent &&
4500 xiev->evtype == XI_ButtonRelease &&
4501 xidev->detail == display_x11->wm_moveresize_button)
4505 display_x11->wm_moveresize_button = 0;
4506 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4512 wmspec_moveresize (GdkWindow *window,
4520 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4522 /* Release passive grab */
4523 gdk_device_ungrab (device, timestamp);
4524 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4526 wmspec_send_message (display, window, root_x, root_y, direction, button);
4530 wmspec_resize_drag (GdkWindow *window,
4540 /* Let the compiler turn a switch into a table, instead
4541 * of doing the table manually, this way is easier to verify.
4545 case GDK_WINDOW_EDGE_NORTH_WEST:
4546 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4549 case GDK_WINDOW_EDGE_NORTH:
4550 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4553 case GDK_WINDOW_EDGE_NORTH_EAST:
4554 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4557 case GDK_WINDOW_EDGE_WEST:
4558 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4561 case GDK_WINDOW_EDGE_EAST:
4562 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4565 case GDK_WINDOW_EDGE_SOUTH_WEST:
4566 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4569 case GDK_WINDOW_EDGE_SOUTH:
4570 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4573 case GDK_WINDOW_EDGE_SOUTH_EAST:
4574 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4578 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4583 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4586 typedef struct _MoveResizeData MoveResizeData;
4588 struct _MoveResizeData
4590 GdkDisplay *display;
4592 GdkWindow *moveresize_window;
4593 GdkWindow *moveresize_emulation_window;
4595 GdkWindowEdge resize_edge;
4597 gint moveresize_button;
4600 gint moveresize_orig_x;
4601 gint moveresize_orig_y;
4602 gint moveresize_orig_width;
4603 gint moveresize_orig_height;
4604 GdkWindowHints moveresize_geom_mask;
4605 GdkGeometry moveresize_geometry;
4606 Time moveresize_process_time;
4607 XEvent *moveresize_pending_event;
4610 static MoveResizeData *
4611 get_move_resize_data (GdkDisplay *display,
4614 MoveResizeData *mv_resize;
4615 static GQuark move_resize_quark = 0;
4617 if (!move_resize_quark)
4618 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4620 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4622 if (!mv_resize && create)
4624 mv_resize = g_new0 (MoveResizeData, 1);
4625 mv_resize->display = display;
4627 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4634 update_pos (MoveResizeData *mv_resize,
4640 dx = new_root_x - mv_resize->moveresize_x;
4641 dy = new_root_y - mv_resize->moveresize_y;
4643 if (mv_resize->is_resize)
4647 x = mv_resize->moveresize_orig_x;
4648 y = mv_resize->moveresize_orig_y;
4650 w = mv_resize->moveresize_orig_width;
4651 h = mv_resize->moveresize_orig_height;
4653 switch (mv_resize->resize_edge)
4655 case GDK_WINDOW_EDGE_NORTH_WEST:
4661 case GDK_WINDOW_EDGE_NORTH:
4665 case GDK_WINDOW_EDGE_NORTH_EAST:
4670 case GDK_WINDOW_EDGE_SOUTH_WEST:
4675 case GDK_WINDOW_EDGE_SOUTH_EAST:
4679 case GDK_WINDOW_EDGE_SOUTH:
4682 case GDK_WINDOW_EDGE_EAST:
4685 case GDK_WINDOW_EDGE_WEST:
4696 if (mv_resize->moveresize_geom_mask)
4698 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4699 mv_resize->moveresize_geom_mask,
4703 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4709 x = mv_resize->moveresize_orig_x + dx;
4710 y = mv_resize->moveresize_orig_y + dy;
4712 gdk_window_move (mv_resize->moveresize_window, x, y);
4717 finish_drag (MoveResizeData *mv_resize)
4719 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4720 mv_resize->moveresize_emulation_window = NULL;
4721 g_object_unref (mv_resize->moveresize_window);
4722 mv_resize->moveresize_window = NULL;
4724 if (mv_resize->moveresize_pending_event)
4726 g_free (mv_resize->moveresize_pending_event);
4727 mv_resize->moveresize_pending_event = NULL;
4732 lookahead_motion_predicate (Display *xdisplay,
4736 gboolean *seen_release = (gboolean *)arg;
4737 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4738 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4743 switch (event->xany.type)
4746 *seen_release = TRUE;
4749 mv_resize->moveresize_process_time = event->xmotion.time;
4759 moveresize_lookahead (MoveResizeData *mv_resize,
4763 gboolean seen_release = FALSE;
4765 if (mv_resize->moveresize_process_time)
4767 if (event->xmotion.time == mv_resize->moveresize_process_time)
4769 mv_resize->moveresize_process_time = 0;
4776 XCheckIfEvent (event->xany.display, &tmp_event,
4777 lookahead_motion_predicate, (XPointer) & seen_release);
4779 return mv_resize->moveresize_process_time == 0;
4783 _gdk_x11_moveresize_handle_event (XEvent *event)
4785 guint button_mask = 0;
4786 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4787 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4789 if (!mv_resize || !mv_resize->moveresize_window)
4791 handle_wmspec_button_release (display, event);
4795 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4797 switch (event->xany.type)
4800 if (mv_resize->moveresize_window->resize_count > 0)
4802 if (mv_resize->moveresize_pending_event)
4803 *mv_resize->moveresize_pending_event = *event;
4805 mv_resize->moveresize_pending_event =
4806 g_memdup (event, sizeof (XEvent));
4810 if (!moveresize_lookahead (mv_resize, event))
4813 update_pos (mv_resize,
4814 event->xmotion.x_root,
4815 event->xmotion.y_root);
4817 /* This should never be triggered in normal cases, but in the
4818 * case where the drag started without an implicit grab being
4819 * in effect, we could miss the release if it occurs before
4820 * we grab the pointer; this ensures that we will never
4821 * get a permanently stuck grab.
4823 if ((event->xmotion.state & button_mask) == 0)
4824 finish_drag (mv_resize);
4828 update_pos (mv_resize,
4829 event->xbutton.x_root,
4830 event->xbutton.y_root);
4832 if (event->xbutton.button == mv_resize->moveresize_button)
4833 finish_drag (mv_resize);
4836 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4839 /* we just assume this is an XI2 event */
4840 XIEvent *ev = (XIEvent *) event->xcookie.data;
4841 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4846 update_pos (mv_resize, xev->root_x, xev->root_y);
4847 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4848 if ((state & button_mask) == 0)
4849 finish_drag (mv_resize);
4852 case XI_ButtonRelease:
4853 update_pos (mv_resize, xev->root_x, xev->root_y);
4854 if (xev->detail == mv_resize->moveresize_button)
4855 finish_drag (mv_resize);
4867 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4871 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4873 if (!mv_resize || window != mv_resize->moveresize_window)
4876 if (mv_resize->moveresize_pending_event)
4878 tmp_event = mv_resize->moveresize_pending_event;
4879 mv_resize->moveresize_pending_event = NULL;
4880 _gdk_x11_moveresize_handle_event (tmp_event);
4888 create_moveresize_window (MoveResizeData *mv_resize,
4891 GdkWindowAttr attributes;
4892 gint attributes_mask;
4893 GdkGrabStatus status;
4895 g_assert (mv_resize->moveresize_emulation_window == NULL);
4897 attributes.x = -100;
4898 attributes.y = -100;
4899 attributes.width = 10;
4900 attributes.height = 10;
4901 attributes.window_type = GDK_WINDOW_TEMP;
4902 attributes.wclass = GDK_INPUT_ONLY;
4903 attributes.override_redirect = TRUE;
4904 attributes.event_mask = 0;
4906 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4908 mv_resize->moveresize_emulation_window =
4909 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4913 gdk_window_show (mv_resize->moveresize_emulation_window);
4915 status = gdk_device_grab (mv_resize->device,
4916 mv_resize->moveresize_emulation_window,
4919 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4923 if (status != GDK_GRAB_SUCCESS)
4925 /* If this fails, some other client has grabbed the window
4928 finish_drag (mv_resize);
4931 mv_resize->moveresize_process_time = 0;
4935 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4936 so that calling XMoveWindow with these coordinates will not move the
4938 Note that this depends on the WM to implement ICCCM-compliant reference
4942 calculate_unmoving_origin (MoveResizeData *mv_resize)
4947 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4948 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4950 gdk_window_get_origin (mv_resize->moveresize_window,
4951 &mv_resize->moveresize_orig_x,
4952 &mv_resize->moveresize_orig_y);
4956 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4957 gdk_window_get_geometry (mv_resize->moveresize_window,
4958 NULL, NULL, &width, &height);
4960 switch (mv_resize->moveresize_geometry.win_gravity)
4962 case GDK_GRAVITY_NORTH_WEST:
4963 mv_resize->moveresize_orig_x = rect.x;
4964 mv_resize->moveresize_orig_y = rect.y;
4966 case GDK_GRAVITY_NORTH:
4967 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4968 mv_resize->moveresize_orig_y = rect.y;
4970 case GDK_GRAVITY_NORTH_EAST:
4971 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4972 mv_resize->moveresize_orig_y = rect.y;
4974 case GDK_GRAVITY_WEST:
4975 mv_resize->moveresize_orig_x = rect.x;
4976 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4978 case GDK_GRAVITY_CENTER:
4979 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4980 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4982 case GDK_GRAVITY_EAST:
4983 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4984 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4986 case GDK_GRAVITY_SOUTH_WEST:
4987 mv_resize->moveresize_orig_x = rect.x;
4988 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4990 case GDK_GRAVITY_SOUTH:
4991 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4992 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4994 case GDK_GRAVITY_SOUTH_EAST:
4995 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4996 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4999 mv_resize->moveresize_orig_x = rect.x;
5000 mv_resize->moveresize_orig_y = rect.y;
5007 emulate_resize_drag (GdkWindow *window,
5015 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5017 mv_resize->is_resize = TRUE;
5018 mv_resize->moveresize_button = button;
5019 mv_resize->resize_edge = edge;
5020 mv_resize->device = device;
5021 mv_resize->moveresize_x = root_x;
5022 mv_resize->moveresize_y = root_y;
5023 mv_resize->moveresize_window = g_object_ref (window);
5025 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
5026 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
5028 mv_resize->moveresize_geom_mask = 0;
5029 gdk_window_get_geometry_hints (window,
5030 &mv_resize->moveresize_geometry,
5031 &mv_resize->moveresize_geom_mask);
5033 calculate_unmoving_origin (mv_resize);
5035 create_moveresize_window (mv_resize, timestamp);
5039 emulate_move_drag (GdkWindow *window,
5046 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5048 mv_resize->is_resize = FALSE;
5049 mv_resize->device = device;
5050 mv_resize->moveresize_button = button;
5051 mv_resize->moveresize_x = root_x;
5052 mv_resize->moveresize_y = root_y;
5054 mv_resize->moveresize_window = g_object_ref (window);
5056 calculate_unmoving_origin (mv_resize);
5058 create_moveresize_window (mv_resize, timestamp);
5062 gdk_x11_window_begin_resize_drag (GdkWindow *window,
5070 if (GDK_WINDOW_DESTROYED (window) ||
5071 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5074 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5075 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5076 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5078 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5082 gdk_x11_window_begin_move_drag (GdkWindow *window,
5089 if (GDK_WINDOW_DESTROYED (window) ||
5090 !WINDOW_IS_TOPLEVEL (window))
5093 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5094 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5095 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5096 device, button, root_x, root_y, timestamp);
5098 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5102 gdk_x11_window_beep (GdkWindow *window)
5104 GdkDisplay *display;
5106 display = GDK_WINDOW_DISPLAY (window);
5109 if (GDK_X11_DISPLAY (display)->use_xkb)
5111 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5112 GDK_WINDOW_XID (window),
5123 gdk_x11_window_set_opacity (GdkWindow *window,
5126 GdkDisplay *display;
5129 g_return_if_fail (GDK_IS_WINDOW (window));
5131 if (GDK_WINDOW_DESTROYED (window) ||
5132 !WINDOW_IS_TOPLEVEL (window))
5135 display = gdk_window_get_display (window);
5139 else if (opacity > 1)
5142 cardinal = opacity * 0xffffffff;
5144 if (cardinal == 0xffffffff)
5145 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5146 GDK_WINDOW_XID (window),
5147 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5149 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5150 GDK_WINDOW_XID (window),
5151 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5154 (guchar *) &cardinal, 1);
5158 gdk_x11_window_set_composited (GdkWindow *window,
5159 gboolean composited)
5161 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5162 GdkWindowImplX11 *impl;
5163 GdkDisplay *display;
5167 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5169 display = gdk_window_get_display (window);
5170 dpy = GDK_DISPLAY_XDISPLAY (display);
5171 xid = GDK_WINDOW_XID (window);
5175 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5176 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5180 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5181 XDamageDestroy (dpy, impl->damage);
5182 impl->damage = None;
5188 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5189 cairo_region_t *region)
5191 _gdk_window_process_updates_recurse (window, region);
5195 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5200 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5202 /* Sync after all drawing, otherwise the client can get "ahead" of
5203 the server rendering during animations, such that we fill up
5204 the Xserver pipes with sync rendering ops not letting other
5205 clients (including the VM) do anything. */
5206 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5210 timestamp_predicate (Display *display,
5214 Window xwindow = GPOINTER_TO_UINT (arg);
5215 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5217 if (xevent->type == PropertyNotify &&
5218 xevent->xproperty.window == xwindow &&
5219 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5220 "GDK_TIMESTAMP_PROP"))
5227 * gdk_x11_get_server_time:
5228 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5229 * with the server. The window must have
5230 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5233 * Routine to get the current X server time stamp.
5235 * Return value: the time stamp.
5238 gdk_x11_get_server_time (GdkWindow *window)
5244 Atom timestamp_prop_atom;
5246 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5247 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5249 xdisplay = GDK_WINDOW_XDISPLAY (window);
5250 xwindow = GDK_WINDOW_XID (window);
5251 timestamp_prop_atom =
5252 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5253 "GDK_TIMESTAMP_PROP");
5255 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5256 timestamp_prop_atom,
5257 8, PropModeReplace, &c, 1);
5259 XIfEvent (xdisplay, &xevent,
5260 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5262 return xevent.xproperty.time;
5266 * gdk_x11_window_get_xid:
5267 * @window: (type GdkX11Window): a native #GdkWindow.
5269 * Returns the X resource (window) belonging to a #GdkWindow.
5271 * Return value: the ID of @drawable's X resource.
5274 gdk_x11_window_get_xid (GdkWindow *window)
5276 /* Try to ensure the window has a native window */
5277 if (!_gdk_window_has_impl (window))
5279 gdk_window_ensure_native (window);
5281 /* We sync here to ensure the window is created in the Xserver when
5282 * this function returns. This is required because the returned XID
5283 * for this window must be valid immediately, even with another
5284 * connection to the Xserver */
5285 gdk_display_sync (gdk_window_get_display (window));
5288 if (!GDK_WINDOW_IS_X11 (window))
5290 g_warning (G_STRLOC " drawable is not a native X11 window");
5294 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5298 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5300 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5301 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5303 object_class->finalize = gdk_window_impl_x11_finalize;
5305 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5306 impl_class->show = gdk_window_x11_show;
5307 impl_class->hide = gdk_window_x11_hide;
5308 impl_class->withdraw = gdk_window_x11_withdraw;
5309 impl_class->set_events = gdk_window_x11_set_events;
5310 impl_class->get_events = gdk_window_x11_get_events;
5311 impl_class->raise = gdk_window_x11_raise;
5312 impl_class->lower = gdk_window_x11_lower;
5313 impl_class->restack_under = gdk_window_x11_restack_under;
5314 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5315 impl_class->move_resize = gdk_window_x11_move_resize;
5316 impl_class->set_background = gdk_window_x11_set_background;
5317 impl_class->reparent = gdk_window_x11_reparent;
5318 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5319 impl_class->get_geometry = gdk_window_x11_get_geometry;
5320 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5321 impl_class->get_device_state = gdk_window_x11_get_device_state;
5322 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5323 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5324 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5325 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5326 impl_class->translate = _gdk_x11_window_translate;
5327 impl_class->destroy = gdk_x11_window_destroy;
5328 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5329 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5330 impl_class->get_shape = gdk_x11_window_get_shape;
5331 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5332 impl_class->beep = gdk_x11_window_beep;
5334 impl_class->focus = gdk_x11_window_focus;
5335 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5336 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5337 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5338 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5339 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5340 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5341 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5342 impl_class->set_title = gdk_x11_window_set_title;
5343 impl_class->set_role = gdk_x11_window_set_role;
5344 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5345 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5346 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5347 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5348 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5349 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5350 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5351 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5352 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5353 impl_class->iconify = gdk_x11_window_iconify;
5354 impl_class->deiconify = gdk_x11_window_deiconify;
5355 impl_class->stick = gdk_x11_window_stick;
5356 impl_class->unstick = gdk_x11_window_unstick;
5357 impl_class->maximize = gdk_x11_window_maximize;
5358 impl_class->unmaximize = gdk_x11_window_unmaximize;
5359 impl_class->fullscreen = gdk_x11_window_fullscreen;
5360 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5361 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5362 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5363 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5364 impl_class->get_group = gdk_x11_window_get_group;
5365 impl_class->set_group = gdk_x11_window_set_group;
5366 impl_class->set_decorations = gdk_x11_window_set_decorations;
5367 impl_class->get_decorations = gdk_x11_window_get_decorations;
5368 impl_class->set_functions = gdk_x11_window_set_functions;
5369 impl_class->set_functions = gdk_x11_window_set_functions;
5370 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5371 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5372 impl_class->set_opacity = gdk_x11_window_set_opacity;
5373 impl_class->set_composited = gdk_x11_window_set_composited;
5374 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5375 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5376 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5377 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5378 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5379 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5380 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5381 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5382 impl_class->get_property = _gdk_x11_window_get_property;
5383 impl_class->change_property = _gdk_x11_window_change_property;
5384 impl_class->delete_property = _gdk_x11_window_delete_property;