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 "gdkprivate-x11.h"
43 #include <netinet/in.h>
46 #include <cairo-xlib.h>
51 #include <X11/Xutil.h>
52 #include <X11/Xatom.h>
54 #include <X11/extensions/shape.h>
57 #include <X11/XKBlib.h>
60 #ifdef HAVE_XCOMPOSITE
61 #include <X11/extensions/Xcomposite.h>
65 #include <X11/extensions/Xfixes.h>
69 #include <X11/extensions/Xdamage.h>
72 const int _gdk_x11_event_mask_table[21] =
76 PointerMotionHintMask,
93 SubstructureNotifyMask,
94 ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
97 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
99 /* Forward declarations */
100 static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
101 static void gdk_window_set_static_win_gravity (GdkWindow *window,
103 static gboolean gdk_window_icon_name_set (GdkWindow *window);
104 static void set_wm_name (GdkDisplay *display,
107 static void move_to_current_desktop (GdkWindow *window);
108 static void gdk_window_x11_set_background (GdkWindow *window,
109 cairo_pattern_t *pattern);
111 static void gdk_window_impl_x11_finalize (GObject *object);
113 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
114 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
115 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
117 #define WINDOW_IS_TOPLEVEL(window) \
118 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
119 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
120 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
122 /* Return whether time1 is considered later than time2 as far as xserver
123 * time is concerned. Accounts for wraparound.
125 #define XSERVER_TIME_IS_LATER(time1, time2) \
126 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
127 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
130 struct _GdkX11Window {
134 struct _GdkX11WindowClass {
135 GdkWindowClass parent_class;
138 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
141 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
146 gdk_x11_window_init (GdkX11Window *x11_window)
151 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
154 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
156 impl->toplevel_window_type = -1;
157 impl->device_cursor = g_hash_table_new_full (NULL, NULL,
158 NULL, g_object_unref);
162 _gdk_x11_window_get_toplevel (GdkWindow *window)
164 GdkWindowImplX11 *impl;
166 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
168 if (!WINDOW_IS_TOPLEVEL (window))
171 impl = GDK_WINDOW_IMPL_X11 (window->impl);
175 impl->toplevel = g_new0 (GdkToplevelX11, 1);
176 impl->toplevel->have_focused = TRUE;
179 return impl->toplevel;
182 static const cairo_user_data_key_t gdk_x11_cairo_key;
185 * _gdk_x11_window_update_size:
186 * @impl: a #GdkWindowImplX11.
188 * Updates the state of the window (in particular the drawable's
189 * cairo surface) when its size has changed.
192 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
194 if (impl->cairo_surface)
196 cairo_xlib_surface_set_size (impl->cairo_surface,
197 gdk_window_get_width (impl->wrapper),
198 gdk_window_get_height (impl->wrapper));
203 set_sync_counter(Display *display,
204 XSyncCounter counter,
207 XSyncValue sync_value;
209 XSyncIntsToValue(&sync_value,
210 value & G_GINT64_CONSTANT(0xFFFFFFFF),
212 XSyncSetCounter(display, counter, sync_value);
216 window_pre_damage (GdkWindow *window)
218 GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
219 GdkWindowImplX11 *impl;
221 if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
224 impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
226 if (impl->toplevel->in_frame &&
227 impl->toplevel->current_counter_value % 2 == 0)
229 impl->toplevel->current_counter_value += 1;
230 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
231 impl->toplevel->extended_update_counter,
232 impl->toplevel->current_counter_value);
237 on_surface_changed (void *data)
239 GdkWindow *window = data;
241 window_pre_damage (window);
244 /* We want to know when cairo drawing causes damage to the window,
245 * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
246 * window only when there actually is drawing. To do that we use
247 * a technique (hack) suggested by Uli Schlachter - if we set
248 * a dummy "mime data" on the cairo surface (this facility is
249 * used to attach JPEG data to an imager), then cairo wil flush
250 * and remove the mime data before making any changes to the window.
254 hook_surface_changed (GdkWindow *window)
256 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
258 if (impl->cairo_surface)
259 cairo_surface_set_mime_data (impl->cairo_surface,
260 "x-gdk/change-notify",
261 (unsigned char *)"X",
268 unhook_surface_changed (GdkWindow *window)
270 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
272 if (impl->cairo_surface)
273 cairo_surface_set_mime_data (impl->cairo_surface,
274 "x-gdk/change-notify",
280 gdk_x11_window_predict_presentation_time (GdkWindow *window)
282 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
283 GdkFrameClock *clock;
284 GdkFrameTimings *timings;
286 gint64 presentation_time;
287 gint64 refresh_interval;
288 gboolean slept_before;
290 if (!WINDOW_IS_TOPLEVEL (window))
293 clock = gdk_window_get_frame_clock (window);
295 timings = gdk_frame_clock_get_current_frame_timings (clock);
296 frame_time = gdk_frame_timings_get_frame_time (timings);
297 slept_before = gdk_frame_timings_get_slept_before (timings);
299 gdk_frame_clock_get_refresh_info (clock,
301 &refresh_interval, &presentation_time);
303 if (presentation_time != 0)
307 presentation_time += refresh_interval;
311 if (presentation_time < frame_time + refresh_interval / 2)
312 presentation_time += refresh_interval;
318 presentation_time = frame_time + refresh_interval + refresh_interval / 2;
320 presentation_time = frame_time + refresh_interval;
323 if (presentation_time < impl->toplevel->throttled_presentation_time)
324 presentation_time = impl->toplevel->throttled_presentation_time;
326 gdk_frame_timings_set_predicted_presentation_time (timings,
332 gdk_x11_window_begin_frame (GdkWindow *window)
334 GdkWindowImplX11 *impl;
336 g_return_if_fail (GDK_IS_WINDOW (window));
338 impl = GDK_WINDOW_IMPL_X11 (window->impl);
340 if (!WINDOW_IS_TOPLEVEL (window) ||
341 impl->toplevel->extended_update_counter == None)
344 impl->toplevel->in_frame = TRUE;
346 if (impl->toplevel->configure_counter_value != 0 &&
347 impl->toplevel->configure_counter_value_is_extended)
349 impl->toplevel->current_counter_value = impl->toplevel->configure_counter_value;
350 if ((impl->toplevel->current_counter_value % 2) == 1)
351 impl->toplevel->current_counter_value += 1;
353 impl->toplevel->configure_counter_value = 0;
355 window_pre_damage (window);
359 hook_surface_changed (window);
364 gdk_x11_window_end_frame (GdkWindow *window)
366 GdkFrameClock *clock;
367 GdkFrameTimings *timings;
368 GdkWindowImplX11 *impl;
370 g_return_if_fail (GDK_IS_WINDOW (window));
372 impl = GDK_WINDOW_IMPL_X11 (window->impl);
374 if (!WINDOW_IS_TOPLEVEL (window) ||
375 impl->toplevel->extended_update_counter == None ||
376 !impl->toplevel->in_frame)
379 clock = gdk_window_get_frame_clock (window);
380 timings = gdk_frame_clock_get_current_frame_timings (clock);
382 impl->toplevel->in_frame = FALSE;
384 if (impl->toplevel->current_counter_value % 2 == 1)
386 #ifdef G_ENABLE_DEBUG
387 if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
389 XImage *image = XGetImage (GDK_WINDOW_XDISPLAY (window),
390 GDK_WINDOW_XID (window),
394 XDestroyImage (image);
396 #endif /* G_ENABLE_DEBUG */
398 /* An increment of 3 means that the frame was not drawn as fast as possible,
399 * but rather at a particular time. This can trigger different handling from
402 if (gdk_frame_timings_get_slept_before (timings))
403 impl->toplevel->current_counter_value += 3;
405 impl->toplevel->current_counter_value += 1;
407 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
408 impl->toplevel->extended_update_counter,
409 impl->toplevel->current_counter_value);
411 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
412 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
414 impl->toplevel->frame_pending = TRUE;
415 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
416 gdk_frame_timings_set_cookie (timings,
417 impl->toplevel->current_counter_value);
421 unhook_surface_changed (window);
423 if (impl->toplevel->configure_counter_value != 0 &&
424 !impl->toplevel->configure_counter_value_is_extended)
426 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
427 impl->toplevel->update_counter,
428 impl->toplevel->configure_counter_value);
430 impl->toplevel->configure_counter_value = 0;
433 if (!impl->toplevel->frame_pending)
434 gdk_frame_timings_set_complete (timings, TRUE);
437 /*****************************************************
438 * X11 specific implementations of generic functions *
439 *****************************************************/
442 gdk_x11_cairo_surface_destroy (void *data)
444 GdkWindowImplX11 *impl = data;
446 impl->cairo_surface = NULL;
449 static cairo_surface_t *
450 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
456 visual = gdk_window_get_visual (impl->wrapper);
457 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
458 GDK_WINDOW_IMPL_X11 (impl)->xid,
459 GDK_VISUAL_XVISUAL (visual),
463 static cairo_surface_t *
464 gdk_x11_ref_cairo_surface (GdkWindow *window)
466 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
468 if (GDK_WINDOW_DESTROYED (window))
471 if (!impl->cairo_surface)
473 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
474 gdk_window_get_width (window),
475 gdk_window_get_height (window));
477 if (impl->cairo_surface)
478 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
479 impl, gdk_x11_cairo_surface_destroy);
481 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
482 hook_surface_changed (window);
485 cairo_surface_reference (impl->cairo_surface);
487 return impl->cairo_surface;
491 gdk_window_impl_x11_finalize (GObject *object)
494 GdkWindowImplX11 *impl;
496 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
498 impl = GDK_WINDOW_IMPL_X11 (object);
500 wrapper = impl->wrapper;
502 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
503 unhook_surface_changed (wrapper);
505 _gdk_x11_window_grab_check_destroy (wrapper);
507 if (!GDK_WINDOW_DESTROYED (wrapper))
509 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
511 _gdk_x11_display_remove_window (display, impl->xid);
512 if (impl->toplevel && impl->toplevel->focus_window)
513 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
516 g_free (impl->toplevel);
519 g_object_unref (impl->cursor);
521 g_hash_table_destroy (impl->device_cursor);
523 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
532 free_pixmap (gpointer datap)
534 FreePixmapData *data = datap;
536 if (!gdk_display_is_closed (data->display))
538 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
542 g_object_unref (data->display);
543 g_slice_free (FreePixmapData, data);
547 attach_free_pixmap_handler (cairo_surface_t *surface,
551 static const cairo_user_data_key_t key;
552 FreePixmapData *data;
554 data = g_slice_new (FreePixmapData);
555 data->display = g_object_ref (display);
556 data->pixmap = pixmap;
558 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
561 /* Cairo does not guarantee we get an xlib surface if we call
562 * cairo_surface_create_similar(). In some cases however, we must use a
563 * pixmap or bitmap in the X11 API.
564 * These functions ensure an Xlib surface.
567 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
571 cairo_surface_t *surface;
574 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
575 GDK_WINDOW_XID (window),
577 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
579 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
581 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
586 /* Create a surface backed with a pixmap without alpha on the same screen as window */
587 static cairo_surface_t *
588 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
592 GdkScreen *screen = gdk_window_get_screen (window);
593 GdkVisual *visual = gdk_screen_get_system_visual (screen);
594 cairo_surface_t *surface;
597 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
598 GDK_WINDOW_XID (window),
600 gdk_visual_get_depth (visual));
601 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
603 GDK_VISUAL_XVISUAL (visual),
605 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
611 tmp_unset_bg (GdkWindow *window)
613 GdkWindowImplX11 *impl;
615 impl = GDK_WINDOW_IMPL_X11 (window->impl);
619 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
620 GDK_WINDOW_XID (window), None);
624 tmp_reset_bg (GdkWindow *window)
626 GdkWindowImplX11 *impl;
628 impl = GDK_WINDOW_IMPL_X11 (window->impl);
632 gdk_window_x11_set_background (window, window->background);
635 /* Unsetting and resetting window backgrounds.
637 * In many cases it is possible to avoid flicker by unsetting the
638 * background of windows. For example if the background of the
639 * parent window is unset when a window is unmapped, a brief flicker
640 * of background painting is avoided.
643 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
646 g_return_if_fail (GDK_IS_WINDOW (window));
648 if (window->input_only || window->destroyed ||
649 (window->window_type != GDK_WINDOW_ROOT &&
650 !GDK_WINDOW_IS_MAPPED (window)))
653 if (_gdk_window_has_impl (window) &&
654 GDK_WINDOW_IS_X11 (window) &&
655 window->window_type != GDK_WINDOW_ROOT &&
656 window->window_type != GDK_WINDOW_FOREIGN)
657 tmp_unset_bg (window);
663 for (l = window->children; l != NULL; l = l->next)
664 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
669 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
671 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
674 window = _gdk_window_get_impl_window (window->parent);
675 _gdk_x11_window_tmp_unset_bg (window, FALSE);
679 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
682 g_return_if_fail (GDK_IS_WINDOW (window));
684 if (window->input_only || window->destroyed ||
685 (window->window_type != GDK_WINDOW_ROOT &&
686 !GDK_WINDOW_IS_MAPPED (window)))
690 if (_gdk_window_has_impl (window) &&
691 GDK_WINDOW_IS_X11 (window) &&
692 window->window_type != GDK_WINDOW_ROOT &&
693 window->window_type != GDK_WINDOW_FOREIGN)
694 tmp_reset_bg (window);
700 for (l = window->children; l != NULL; l = l->next)
701 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
706 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
708 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
711 window = _gdk_window_get_impl_window (window->parent);
713 _gdk_x11_window_tmp_reset_bg (window, FALSE);
717 _gdk_x11_screen_init_root_window (GdkScreen *screen)
720 GdkWindowImplX11 *impl;
721 GdkX11Screen *x11_screen;
723 x11_screen = GDK_X11_SCREEN (screen);
725 g_assert (x11_screen->root_window == NULL);
727 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
729 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
730 window->impl_window = window;
731 window->visual = gdk_screen_get_system_visual (screen);
733 impl = GDK_WINDOW_IMPL_X11 (window->impl);
735 impl->xid = x11_screen->xroot_window;
736 impl->wrapper = window;
738 window->window_type = GDK_WINDOW_ROOT;
739 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
745 window->width = WidthOfScreen (x11_screen->xscreen);
746 window->height = HeightOfScreen (x11_screen->xscreen);
747 window->viewable = TRUE;
749 /* see init_randr_support() in gdkscreen-x11.c */
750 window->event_mask = GDK_STRUCTURE_MASK;
752 _gdk_window_update_size (x11_screen->root_window);
754 _gdk_x11_display_add_window (x11_screen->display,
755 &x11_screen->xroot_window,
756 x11_screen->root_window);
760 set_wm_protocols (GdkWindow *window)
762 GdkDisplay *display = gdk_window_get_display (window);
766 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
767 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
768 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
771 if (GDK_X11_DISPLAY (display)->use_sync)
772 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
775 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
779 get_default_title (void)
783 title = g_get_application_name ();
785 title = g_get_prgname ();
793 check_leader_window_title (GdkDisplay *display)
795 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
797 if (display_x11->leader_window && !display_x11->leader_window_title_set)
799 set_wm_name (display,
800 display_x11->leader_window,
801 get_default_title ());
803 display_x11->leader_window_title_set = TRUE;
808 create_focus_window (GdkDisplay *display,
811 GdkX11Display *display_x11;
812 GdkEventMask event_mask;
816 xdisplay = GDK_DISPLAY_XDISPLAY (display);
817 display_x11 = GDK_X11_DISPLAY (display);
819 focus_window = XCreateSimpleWindow (xdisplay, parent,
823 /* FIXME: probably better to actually track the requested event mask for the toplevel
825 event_mask = (GDK_KEY_PRESS_MASK |
826 GDK_KEY_RELEASE_MASK |
827 GDK_FOCUS_CHANGE_MASK);
829 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
833 XMapWindow (xdisplay, focus_window);
839 ensure_sync_counter (GdkWindow *window)
842 if (!GDK_WINDOW_DESTROYED (window))
844 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
845 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
848 toplevel->update_counter == None &&
849 GDK_X11_DISPLAY (display)->use_sync)
851 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
856 XSyncIntToValue (&value, 0);
858 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
859 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
861 atom = gdk_x11_get_xatom_by_name_for_display (display,
862 "_NET_WM_SYNC_REQUEST_COUNTER");
864 counters[0] = toplevel->update_counter;
865 counters[1] = toplevel->extended_update_counter;
866 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
869 (guchar *)counters, 2);
871 toplevel->current_counter_value = 0;
878 setup_toplevel_window (GdkWindow *window,
881 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
882 GdkDisplay *display = gdk_window_get_display (window);
883 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
884 XID xid = GDK_WINDOW_XID (window);
885 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
886 XSizeHints size_hints;
888 Window leader_window;
890 set_wm_protocols (window);
892 if (!window->input_only)
894 /* The focus window is off the visible area, and serves to receive key
895 * press events so they don't get sent to child windows.
897 toplevel->focus_window = create_focus_window (display, xid);
898 _gdk_x11_display_add_window (x11_screen->display,
899 &toplevel->focus_window,
903 check_leader_window_title (x11_screen->display);
905 /* FIXME: Is there any point in doing this? Do any WM's pay
906 * attention to PSize, and even if they do, is this the
909 size_hints.flags = PSize;
910 size_hints.width = window->width;
911 size_hints.height = window->height;
913 XSetWMNormalHints (xdisplay, xid, &size_hints);
915 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
916 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
919 XChangeProperty (xdisplay, xid,
920 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
925 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
928 XChangeProperty (xdisplay, xid,
929 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
930 XA_WINDOW, 32, PropModeReplace,
931 (guchar *) &leader_window, 1);
933 if (toplevel->focus_window != None)
934 XChangeProperty (xdisplay, xid,
935 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
936 XA_WINDOW, 32, PropModeReplace,
937 (guchar *) &toplevel->focus_window, 1);
939 if (!window->focus_on_map)
940 gdk_x11_window_set_user_time (window, 0);
941 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
942 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
944 ensure_sync_counter (window);
946 /* Start off in a frozen state - we'll finish this when we first paint */
947 gdk_x11_window_begin_frame (window);
951 on_frame_clock_before_paint (GdkFrameClock *clock,
954 gdk_x11_window_predict_presentation_time (window);
955 gdk_x11_window_begin_frame (window);
959 on_frame_clock_after_paint (GdkFrameClock *clock,
962 gdk_x11_window_end_frame (window);
967 connect_frame_clock (GdkWindow *window)
969 GdkWindowImplX11 *impl;
971 impl = GDK_WINDOW_IMPL_X11 (window->impl);
972 if (WINDOW_IS_TOPLEVEL (window) && !impl->frame_clock_connected)
974 GdkFrameClock *frame_clock = gdk_window_get_frame_clock (window);
976 g_signal_connect (frame_clock, "before-paint",
977 G_CALLBACK (on_frame_clock_before_paint), window);
978 g_signal_connect (frame_clock, "after-paint",
979 G_CALLBACK (on_frame_clock_after_paint), window);
981 impl->frame_clock_connected = TRUE;
986 _gdk_x11_display_create_window_impl (GdkDisplay *display,
988 GdkWindow *real_parent,
990 GdkEventMask event_mask,
991 GdkWindowAttr *attributes,
992 gint attributes_mask)
994 GdkWindowImplX11 *impl;
995 GdkX11Screen *x11_screen;
996 GdkX11Display *display_x11;
1002 XSetWindowAttributes xattributes;
1003 long xattributes_mask;
1004 XClassHint *class_hint;
1009 display_x11 = GDK_X11_DISPLAY (display);
1010 xparent = GDK_WINDOW_XID (real_parent);
1011 x11_screen = GDK_X11_SCREEN (screen);
1013 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1014 window->impl = GDK_WINDOW_IMPL (impl);
1015 impl->wrapper = GDK_WINDOW (window);
1017 xdisplay = x11_screen->xdisplay;
1019 xattributes_mask = 0;
1021 xvisual = gdk_x11_visual_get_xvisual (window->visual);
1023 if (attributes_mask & GDK_WA_NOREDIR)
1025 xattributes.override_redirect =
1026 (attributes->override_redirect == FALSE)?False:True;
1027 xattributes_mask |= CWOverrideRedirect;
1030 xattributes.override_redirect = False;
1032 impl->override_redirect = xattributes.override_redirect;
1034 if (window->parent && window->parent->guffaw_gravity)
1036 xattributes.win_gravity = StaticGravity;
1037 xattributes_mask |= CWWinGravity;
1041 switch (window->window_type)
1043 case GDK_WINDOW_TOPLEVEL:
1044 case GDK_WINDOW_TEMP:
1045 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
1047 /* The common code warns for this case */
1048 xparent = GDK_SCREEN_XROOTWIN (screen);
1052 if (!window->input_only)
1054 class = InputOutput;
1056 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1058 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
1059 xattributes_mask |= CWBorderPixel | CWBackPixel;
1061 if (window->guffaw_gravity)
1062 xattributes.bit_gravity = StaticGravity;
1064 xattributes.bit_gravity = NorthWestGravity;
1066 xattributes_mask |= CWBitGravity;
1068 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
1069 xattributes_mask |= CWColormap;
1071 if (window->window_type == GDK_WINDOW_TEMP)
1073 xattributes.save_under = True;
1074 xattributes.override_redirect = True;
1075 xattributes.cursor = None;
1076 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
1078 impl->override_redirect = TRUE;
1086 if (window->width > 65535 ||
1087 window->height > 65535)
1089 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
1091 if (window->width > 65535)
1092 window->width = 65535;
1093 if (window->height > 65535)
1094 window->height = 65535;
1097 impl->xid = XCreateWindow (xdisplay, xparent,
1098 window->x + window->parent->abs_x,
1099 window->y + window->parent->abs_y,
1100 window->width, window->height,
1101 0, window->depth, class, xvisual,
1102 xattributes_mask, &xattributes);
1104 g_object_ref (window);
1105 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1107 switch (GDK_WINDOW_TYPE (window))
1109 case GDK_WINDOW_TOPLEVEL:
1110 case GDK_WINDOW_TEMP:
1111 if (attributes_mask & GDK_WA_TITLE)
1112 title = attributes->title;
1114 title = get_default_title ();
1116 gdk_window_set_title (window, title);
1118 if (attributes_mask & GDK_WA_WMCLASS)
1120 class_hint = XAllocClassHint ();
1121 class_hint->res_name = attributes->wmclass_name;
1122 class_hint->res_class = attributes->wmclass_class;
1123 XSetClassHint (xdisplay, impl->xid, class_hint);
1127 setup_toplevel_window (window, window->parent);
1130 case GDK_WINDOW_CHILD:
1135 if (attributes_mask & GDK_WA_TYPE_HINT)
1136 gdk_window_set_type_hint (window, attributes->type_hint);
1138 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1139 GDK_WINDOW_XID (window), event_mask,
1140 StructureNotifyMask | PropertyChangeMask);
1142 connect_frame_clock (window);
1144 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1145 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1149 x_event_mask_to_gdk_event_mask (long mask)
1151 GdkEventMask event_mask = 0;
1154 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1156 if (mask & _gdk_x11_event_mask_table[i])
1157 event_mask |= 1 << (i + 1);
1164 * gdk_x11_window_foreign_new_for_display:
1165 * @display: the #GdkDisplay where the window handle comes from.
1166 * @window: an XLib <type>Window</type>
1168 * Wraps a native window in a #GdkWindow. The function will try to
1169 * look up the window using gdk_x11_window_lookup_for_display() first.
1170 * If it does not find it there, it will create a new window.
1172 * This may fail if the window has been destroyed. If the window
1173 * was already known to GDK, a new reference to the existing
1174 * #GdkWindow is returned.
1176 * Return value: (transfer full): a #GdkWindow wrapper for the native
1177 * window, or %NULL if the window has been destroyed. The wrapper
1178 * will be newly created, if one doesn't exist already.
1183 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1188 GdkWindowImplX11 *impl;
1189 GdkX11Display *display_x11;
1190 XWindowAttributes attrs;
1191 Window root, parent;
1192 Window *children = NULL;
1196 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1198 display_x11 = GDK_X11_DISPLAY (display);
1200 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1201 return g_object_ref (win);
1203 gdk_x11_display_error_trap_push (display);
1204 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1205 if (gdk_x11_display_error_trap_pop (display) || !result)
1208 /* FIXME: This is pretty expensive.
1209 * Maybe the caller should supply the parent
1211 gdk_x11_display_error_trap_push (display);
1212 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1213 if (gdk_x11_display_error_trap_pop (display) || !result)
1219 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1221 win = _gdk_display_create_window (display);
1222 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1223 win->impl_window = win;
1224 win->visual = gdk_x11_screen_lookup_visual (screen,
1225 XVisualIDFromVisual (attrs.visual));
1227 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1228 impl->wrapper = win;
1230 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1232 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1233 win->parent = gdk_screen_get_root_window (screen);
1235 win->parent->children = g_list_prepend (win->parent->children, win);
1241 win->width = attrs.width;
1242 win->height = attrs.height;
1243 win->window_type = GDK_WINDOW_FOREIGN;
1244 win->destroyed = FALSE;
1246 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1248 if (attrs.map_state == IsUnmapped)
1249 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1252 win->viewable = TRUE;
1254 win->depth = attrs.depth;
1257 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1259 /* Update the clip region, etc */
1260 _gdk_window_update_size (win);
1266 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1267 GdkToplevelX11 *toplevel)
1269 if (toplevel->icon_pixmap)
1271 cairo_surface_destroy (toplevel->icon_pixmap);
1272 toplevel->icon_pixmap = NULL;
1274 if (toplevel->icon_mask)
1276 cairo_surface_destroy (toplevel->icon_mask);
1277 toplevel->icon_mask = NULL;
1279 if (toplevel->group_leader)
1281 g_object_unref (toplevel->group_leader);
1282 toplevel->group_leader = NULL;
1285 if (toplevel->update_counter != None)
1287 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1288 toplevel->update_counter);
1289 toplevel->update_counter = None;
1291 toplevel->current_counter_value = 0;
1297 gdk_x11_window_destroy (GdkWindow *window,
1299 gboolean foreign_destroy)
1301 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1302 GdkToplevelX11 *toplevel;
1304 g_return_if_fail (GDK_IS_WINDOW (window));
1306 _gdk_x11_selection_window_destroyed (window);
1308 toplevel = _gdk_x11_window_get_toplevel (window);
1310 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1312 if (impl->cairo_surface)
1314 cairo_surface_finish (impl->cairo_surface);
1315 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1319 if (!recursing && !foreign_destroy)
1320 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1323 static cairo_surface_t *
1324 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1325 cairo_surface_t *surface,
1329 cairo_xlib_surface_set_size (surface, width, height);
1335 gdk_x11_window_destroy_foreign (GdkWindow *window)
1337 /* It's somebody else's window, but in our hierarchy,
1338 * so reparent it to the root window, and then send
1339 * it a delete event, as if we were a WM
1341 XClientMessageEvent xclient;
1342 GdkDisplay *display;
1344 display = GDK_WINDOW_DISPLAY (window);
1345 gdk_x11_display_error_trap_push (display);
1346 gdk_window_hide (window);
1347 gdk_window_reparent (window, NULL, 0, 0);
1349 memset (&xclient, 0, sizeof (xclient));
1350 xclient.type = ClientMessage;
1351 xclient.window = GDK_WINDOW_XID (window);
1352 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1353 xclient.format = 32;
1354 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1355 xclient.data.l[1] = CurrentTime;
1356 xclient.data.l[2] = 0;
1357 xclient.data.l[3] = 0;
1358 xclient.data.l[4] = 0;
1360 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1361 GDK_WINDOW_XID (window),
1362 False, 0, (XEvent *)&xclient);
1363 gdk_x11_display_error_trap_pop_ignored (display);
1367 get_root (GdkWindow *window)
1369 GdkScreen *screen = gdk_window_get_screen (window);
1371 return gdk_screen_get_root_window (screen);
1374 /* This function is called when the XWindow is really gone.
1377 gdk_x11_window_destroy_notify (GdkWindow *window)
1379 GdkWindowImplX11 *window_impl;
1381 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1383 if (!GDK_WINDOW_DESTROYED (window))
1385 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1386 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1388 _gdk_window_destroy (window, TRUE);
1391 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1392 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1393 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1395 _gdk_x11_window_grab_check_destroy (window);
1397 g_object_unref (window);
1400 static GdkDragProtocol
1401 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1404 GdkDragProtocol protocol;
1405 GdkDisplay *display;
1409 display = gdk_window_get_display (window);
1410 xid = _gdk_x11_display_get_drag_protocol (display,
1411 GDK_WINDOW_XID (window->impl_window),
1418 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1427 update_wm_hints (GdkWindow *window,
1430 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1431 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1435 !toplevel->is_leader &&
1436 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1439 wm_hints.flags = StateHint | InputHint;
1440 wm_hints.input = window->accept_focus ? True : False;
1441 wm_hints.initial_state = NormalState;
1443 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1445 wm_hints.flags |= StateHint;
1446 wm_hints.initial_state = IconicState;
1449 if (toplevel->icon_pixmap)
1451 wm_hints.flags |= IconPixmapHint;
1452 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1455 if (toplevel->icon_mask)
1457 wm_hints.flags |= IconMaskHint;
1458 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1461 wm_hints.flags |= WindowGroupHint;
1462 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1464 wm_hints.flags |= WindowGroupHint;
1465 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1468 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1470 if (toplevel->urgency_hint)
1471 wm_hints.flags |= XUrgencyHint;
1473 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1474 GDK_WINDOW_XID (window),
1479 set_initial_hints (GdkWindow *window)
1481 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1482 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1483 Window xwindow = GDK_WINDOW_XID (window);
1484 GdkToplevelX11 *toplevel;
1488 toplevel = _gdk_x11_window_get_toplevel (window);
1493 update_wm_hints (window, TRUE);
1495 /* We set the spec hints regardless of whether the spec is supported,
1496 * since it can't hurt and it's kind of expensive to check whether
1502 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1504 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1505 "_NET_WM_STATE_MAXIMIZED_VERT");
1507 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1508 "_NET_WM_STATE_MAXIMIZED_HORZ");
1510 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1513 if (window->state & GDK_WINDOW_STATE_ABOVE)
1515 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1516 "_NET_WM_STATE_ABOVE");
1520 if (window->state & GDK_WINDOW_STATE_BELOW)
1522 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1523 "_NET_WM_STATE_BELOW");
1527 if (window->state & GDK_WINDOW_STATE_STICKY)
1529 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1530 "_NET_WM_STATE_STICKY");
1532 toplevel->have_sticky = TRUE;
1535 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1537 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1538 "_NET_WM_STATE_FULLSCREEN");
1540 toplevel->have_fullscreen = TRUE;
1543 if (window->modal_hint)
1545 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1546 "_NET_WM_STATE_MODAL");
1550 if (toplevel->skip_taskbar_hint)
1552 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1553 "_NET_WM_STATE_SKIP_TASKBAR");
1557 if (toplevel->skip_pager_hint)
1559 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1560 "_NET_WM_STATE_SKIP_PAGER");
1564 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1566 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1567 "_NET_WM_STATE_HIDDEN");
1569 toplevel->have_hidden = TRUE;
1574 XChangeProperty (xdisplay,
1576 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1577 XA_ATOM, 32, PropModeReplace,
1578 (guchar*) atoms, i);
1582 XDeleteProperty (xdisplay,
1584 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1587 if (window->state & GDK_WINDOW_STATE_STICKY)
1589 atoms[0] = 0xFFFFFFFF;
1590 XChangeProperty (xdisplay,
1592 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1593 XA_CARDINAL, 32, PropModeReplace,
1594 (guchar*) atoms, 1);
1595 toplevel->on_all_desktops = TRUE;
1599 XDeleteProperty (xdisplay,
1601 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1604 toplevel->map_serial = NextRequest (xdisplay);
1608 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1610 GdkDisplay *display;
1611 GdkX11Display *display_x11;
1612 GdkToplevelX11 *toplevel;
1613 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1614 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1615 Window xwindow = GDK_WINDOW_XID (window);
1618 if (!already_mapped)
1619 set_initial_hints (window);
1621 if (WINDOW_IS_TOPLEVEL (window))
1623 display = gdk_window_get_display (window);
1624 display_x11 = GDK_X11_DISPLAY (display);
1625 toplevel = _gdk_x11_window_get_toplevel (window);
1627 if (toplevel->user_time != 0 &&
1628 display_x11->user_time != 0 &&
1629 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1630 gdk_x11_window_set_user_time (window, display_x11->user_time);
1633 unset_bg = !window->input_only &&
1634 (window->window_type == GDK_WINDOW_CHILD ||
1635 impl->override_redirect) &&
1636 gdk_window_is_viewable (window);
1639 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1641 XMapWindow (xdisplay, xwindow);
1644 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1646 /* Fullscreen on current monitor is the default, no need to apply this mode
1647 * when mapping a window. This also ensures that the default behavior remains
1648 * consistent with pre-fullscreen mode implementation.
1650 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1651 gdk_x11_window_apply_fullscreen_mode (window);
1655 pre_unmap (GdkWindow *window)
1657 GdkWindow *start_window = NULL;
1659 if (window->input_only)
1662 if (window->window_type == GDK_WINDOW_CHILD)
1663 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1664 else if (window->window_type == GDK_WINDOW_TEMP)
1665 start_window = get_root (window);
1668 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1672 post_unmap (GdkWindow *window)
1674 GdkWindow *start_window = NULL;
1676 if (window->input_only)
1679 if (window->window_type == GDK_WINDOW_CHILD)
1680 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1681 else if (window->window_type == GDK_WINDOW_TEMP)
1682 start_window = get_root (window);
1686 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1688 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1690 GdkRectangle invalid_rect;
1692 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1693 invalid_rect.width = gdk_window_get_width (window);
1694 invalid_rect.height = gdk_window_get_height (window);
1695 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1696 &invalid_rect, TRUE);
1702 gdk_window_x11_hide (GdkWindow *window)
1704 /* We'll get the unmap notify eventually, and handle it then,
1705 * but checking here makes things more consistent if we are
1706 * just doing stuff ourself.
1708 _gdk_x11_window_grab_check_unmap (window,
1709 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1711 /* You can't simply unmap toplevel windows. */
1712 switch (window->window_type)
1714 case GDK_WINDOW_TOPLEVEL:
1715 case GDK_WINDOW_TEMP: /* ? */
1716 gdk_window_withdraw (window);
1719 case GDK_WINDOW_FOREIGN:
1720 case GDK_WINDOW_ROOT:
1721 case GDK_WINDOW_CHILD:
1725 _gdk_window_clear_update_area (window);
1728 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1729 GDK_WINDOW_XID (window));
1730 post_unmap (window);
1734 gdk_window_x11_withdraw (GdkWindow *window)
1736 if (!window->destroyed)
1738 if (GDK_WINDOW_IS_MAPPED (window))
1739 gdk_synthesize_window_state (window,
1741 GDK_WINDOW_STATE_WITHDRAWN);
1743 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1747 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1748 GDK_WINDOW_XID (window), 0);
1750 post_unmap (window);
1755 window_x11_move (GdkWindow *window,
1759 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1761 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1763 /* The window isn't actually damaged, but it's parent is */
1764 window_pre_damage (window);
1765 _gdk_x11_window_move_resize_child (window,
1767 window->width, window->height);
1771 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1772 GDK_WINDOW_XID (window),
1775 if (impl->override_redirect)
1784 window_x11_resize (GdkWindow *window,
1794 window_pre_damage (window);
1796 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1798 _gdk_x11_window_move_resize_child (window,
1799 window->x, window->y,
1804 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1806 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1807 GDK_WINDOW_XID (window),
1810 if (impl->override_redirect)
1812 window->width = width;
1813 window->height = height;
1814 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1818 if (width != window->width || height != window->height)
1819 window->resize_count += 1;
1823 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1827 window_x11_move_resize (GdkWindow *window,
1839 window_pre_damage (window);
1841 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1843 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1844 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1848 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1850 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1851 GDK_WINDOW_XID (window),
1852 x, y, width, height);
1854 if (impl->override_redirect)
1859 window->width = width;
1860 window->height = height;
1862 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1866 if (width != window->width || height != window->height)
1867 window->resize_count += 1;
1873 gdk_window_x11_move_resize (GdkWindow *window,
1880 if (with_move && (width < 0 && height < 0))
1881 window_x11_move (window, x, y);
1885 window_x11_move_resize (window, x, y, width, height);
1887 window_x11_resize (window, width, height);
1892 gdk_window_x11_reparent (GdkWindow *window,
1893 GdkWindow *new_parent,
1897 GdkWindowImplX11 *impl;
1899 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1901 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1902 _gdk_x11_window_tmp_unset_parent_bg (window);
1903 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1904 GDK_WINDOW_XID (window),
1905 GDK_WINDOW_XID (new_parent),
1906 new_parent->abs_x + x, new_parent->abs_y + y);
1907 _gdk_x11_window_tmp_reset_parent_bg (window);
1908 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1910 if (WINDOW_IS_TOPLEVEL (window))
1911 connect_frame_clock (window);
1913 /* old frame clock was disposed, our signal handlers removed */
1914 impl->frame_clock_connected = FALSE;
1916 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1917 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1919 window->parent = new_parent;
1921 /* Switch the window type as appropriate */
1923 switch (GDK_WINDOW_TYPE (new_parent))
1925 case GDK_WINDOW_ROOT:
1926 case GDK_WINDOW_FOREIGN:
1927 /* Reparenting to toplevel */
1929 if (!WINDOW_IS_TOPLEVEL (window) &&
1930 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1932 /* This is also done in common code at a later stage, but we
1933 need it in setup_toplevel, so do it here too */
1934 if (window->toplevel_window_type != -1)
1935 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1936 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1937 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1939 /* Wasn't a toplevel, set up */
1940 setup_toplevel_window (window, new_parent);
1945 case GDK_WINDOW_TOPLEVEL:
1946 case GDK_WINDOW_CHILD:
1947 case GDK_WINDOW_TEMP:
1948 if (WINDOW_IS_TOPLEVEL (window) &&
1951 if (impl->toplevel->focus_window)
1953 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1954 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1957 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1959 g_free (impl->toplevel);
1960 impl->toplevel = NULL;
1968 gdk_window_x11_raise (GdkWindow *window)
1970 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1974 gdk_window_x11_restack_under (GdkWindow *window,
1975 GList *native_siblings /* in requested order, first is bottom-most */)
1981 n_windows = g_list_length (native_siblings) + 1;
1982 windows = g_new (Window, n_windows);
1984 windows[0] = GDK_WINDOW_XID (window);
1985 /* Reverse order, as input order is bottom-most first */
1987 for (l = native_siblings; l != NULL; l = l->next)
1988 windows[i--] = GDK_WINDOW_XID (l->data);
1990 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1996 gdk_window_x11_restack_toplevel (GdkWindow *window,
2000 XWindowChanges changes;
2002 changes.sibling = GDK_WINDOW_XID (sibling);
2003 changes.stack_mode = above ? Above : Below;
2004 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
2005 GDK_WINDOW_XID (window),
2006 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
2007 CWStackMode | CWSibling, &changes);
2011 gdk_window_x11_lower (GdkWindow *window)
2013 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
2017 * gdk_x11_window_move_to_current_desktop:
2018 * @window: (type GdkX11Window): a #GdkWindow
2020 * Moves the window to the correct workspace when running under a
2021 * window manager that supports multiple workspaces, as described
2022 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
2023 * Window Manager Hints</ulink>. Will not do anything if the
2024 * window is already on all workspaces.
2029 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
2031 GdkToplevelX11 *toplevel;
2033 g_return_if_fail (GDK_IS_WINDOW (window));
2034 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2036 toplevel = _gdk_x11_window_get_toplevel (window);
2038 if (toplevel->on_all_desktops)
2041 move_to_current_desktop (window);
2045 move_to_current_desktop (GdkWindow *window)
2047 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2048 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
2049 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2050 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
2057 gulong *current_desktop;
2058 GdkDisplay *display;
2060 display = gdk_window_get_display (window);
2062 /* Get current desktop, then set it; this is a race, but not
2063 * one that matters much in practice.
2065 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
2066 GDK_WINDOW_XROOTWIN (window),
2067 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
2069 False, XA_CARDINAL, &type, &format, &nitems,
2070 &bytes_after, &data);
2072 if (type == XA_CARDINAL)
2074 XClientMessageEvent xclient;
2075 current_desktop = (gulong *)data;
2077 memset (&xclient, 0, sizeof (xclient));
2078 xclient.type = ClientMessage;
2080 xclient.send_event = True;
2081 xclient.window = GDK_WINDOW_XID (window);
2082 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
2083 xclient.format = 32;
2085 xclient.data.l[0] = *current_desktop;
2086 xclient.data.l[1] = 1; /* source indication */
2087 xclient.data.l[2] = 0;
2088 xclient.data.l[3] = 0;
2089 xclient.data.l[4] = 0;
2091 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
2092 GDK_WINDOW_XROOTWIN (window),
2094 SubstructureRedirectMask | SubstructureNotifyMask,
2095 (XEvent *)&xclient);
2097 XFree (current_desktop);
2103 gdk_x11_window_focus (GdkWindow *window,
2106 GdkDisplay *display;
2108 g_return_if_fail (GDK_IS_WINDOW (window));
2110 if (GDK_WINDOW_DESTROYED (window) ||
2111 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2114 display = GDK_WINDOW_DISPLAY (window);
2116 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2117 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2119 XClientMessageEvent xclient;
2121 memset (&xclient, 0, sizeof (xclient));
2122 xclient.type = ClientMessage;
2123 xclient.window = GDK_WINDOW_XID (window);
2124 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2125 "_NET_ACTIVE_WINDOW");
2126 xclient.format = 32;
2127 xclient.data.l[0] = 1; /* requestor type; we're an app */
2128 xclient.data.l[1] = timestamp;
2129 xclient.data.l[2] = None; /* currently active window */
2130 xclient.data.l[3] = 0;
2131 xclient.data.l[4] = 0;
2133 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2134 SubstructureRedirectMask | SubstructureNotifyMask,
2135 (XEvent *)&xclient);
2139 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2141 /* There is no way of knowing reliably whether we are viewable;
2142 * so trap errors asynchronously around the XSetInputFocus call
2144 gdk_x11_display_error_trap_push (display);
2145 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2146 GDK_WINDOW_XID (window),
2149 gdk_x11_display_error_trap_pop_ignored (display);
2154 gdk_x11_window_set_type_hint (GdkWindow *window,
2155 GdkWindowTypeHint hint)
2157 GdkDisplay *display;
2160 if (GDK_WINDOW_DESTROYED (window) ||
2161 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2164 display = gdk_window_get_display (window);
2168 case GDK_WINDOW_TYPE_HINT_DIALOG:
2169 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2171 case GDK_WINDOW_TYPE_HINT_MENU:
2172 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2174 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2175 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2177 case GDK_WINDOW_TYPE_HINT_UTILITY:
2178 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2180 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2181 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2183 case GDK_WINDOW_TYPE_HINT_DOCK:
2184 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2186 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2187 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2189 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2190 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2192 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2193 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2195 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2196 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2198 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2199 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2201 case GDK_WINDOW_TYPE_HINT_COMBO:
2202 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2204 case GDK_WINDOW_TYPE_HINT_DND:
2205 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2208 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2210 case GDK_WINDOW_TYPE_HINT_NORMAL:
2211 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2215 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2216 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2217 XA_ATOM, 32, PropModeReplace,
2218 (guchar *)&atom, 1);
2221 static GdkWindowTypeHint
2222 gdk_x11_window_get_type_hint (GdkWindow *window)
2224 GdkDisplay *display;
2225 GdkWindowTypeHint type;
2228 gulong nitems_return;
2229 gulong bytes_after_return;
2230 guchar *data = NULL;
2232 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2234 if (GDK_WINDOW_DESTROYED (window) ||
2235 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2236 return GDK_WINDOW_TYPE_HINT_NORMAL;
2238 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2240 display = gdk_window_get_display (window);
2242 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2243 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2244 0, G_MAXLONG, False, XA_ATOM, &type_return,
2245 &format_return, &nitems_return, &bytes_after_return,
2248 if ((type_return == XA_ATOM) && (format_return == 32) &&
2249 (data) && (nitems_return == 1))
2251 Atom atom = *(Atom*)data;
2253 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2254 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2255 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2256 type = GDK_WINDOW_TYPE_HINT_MENU;
2257 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2258 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2259 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2260 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2261 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2262 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2263 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2264 type = GDK_WINDOW_TYPE_HINT_DOCK;
2265 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2266 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2267 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2268 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2269 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2270 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2271 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2272 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2273 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2274 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2275 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2276 type = GDK_WINDOW_TYPE_HINT_COMBO;
2277 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2278 type = GDK_WINDOW_TYPE_HINT_DND;
2281 if (type_return != None && data != NULL)
2289 gdk_wmspec_change_state (gboolean add,
2294 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2295 XClientMessageEvent xclient;
2297 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2298 #define _NET_WM_STATE_ADD 1 /* add/set property */
2299 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2301 memset (&xclient, 0, sizeof (xclient));
2302 xclient.type = ClientMessage;
2303 xclient.window = GDK_WINDOW_XID (window);
2304 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2305 xclient.format = 32;
2306 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2307 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2308 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2309 xclient.data.l[3] = 1; /* source indication */
2310 xclient.data.l[4] = 0;
2312 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2313 SubstructureRedirectMask | SubstructureNotifyMask,
2314 (XEvent *)&xclient);
2318 gdk_x11_window_set_modal_hint (GdkWindow *window,
2321 if (GDK_WINDOW_DESTROYED (window) ||
2322 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2325 window->modal_hint = modal;
2327 if (GDK_WINDOW_IS_MAPPED (window))
2328 gdk_wmspec_change_state (modal, window,
2329 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2334 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2335 gboolean skips_taskbar)
2337 GdkToplevelX11 *toplevel;
2339 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2341 if (GDK_WINDOW_DESTROYED (window) ||
2342 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2345 toplevel = _gdk_x11_window_get_toplevel (window);
2346 toplevel->skip_taskbar_hint = skips_taskbar;
2348 if (GDK_WINDOW_IS_MAPPED (window))
2349 gdk_wmspec_change_state (skips_taskbar, window,
2350 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2355 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2356 gboolean skips_pager)
2358 GdkToplevelX11 *toplevel;
2360 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2362 if (GDK_WINDOW_DESTROYED (window) ||
2363 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2366 toplevel = _gdk_x11_window_get_toplevel (window);
2367 toplevel->skip_pager_hint = skips_pager;
2369 if (GDK_WINDOW_IS_MAPPED (window))
2370 gdk_wmspec_change_state (skips_pager, window,
2371 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2376 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2379 GdkToplevelX11 *toplevel;
2381 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2383 if (GDK_WINDOW_DESTROYED (window) ||
2384 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2387 toplevel = _gdk_x11_window_get_toplevel (window);
2388 toplevel->urgency_hint = urgent;
2390 update_wm_hints (window, FALSE);
2394 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2395 const GdkGeometry *geometry,
2396 GdkWindowHints geom_mask)
2398 XSizeHints size_hints;
2400 if (GDK_WINDOW_DESTROYED (window) ||
2401 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2404 size_hints.flags = 0;
2406 if (geom_mask & GDK_HINT_POS)
2408 size_hints.flags |= PPosition;
2409 /* We need to initialize the following obsolete fields because KWM
2410 * apparently uses these fields if they are non-zero.
2417 if (geom_mask & GDK_HINT_USER_POS)
2419 size_hints.flags |= USPosition;
2422 if (geom_mask & GDK_HINT_USER_SIZE)
2424 size_hints.flags |= USSize;
2427 if (geom_mask & GDK_HINT_MIN_SIZE)
2429 size_hints.flags |= PMinSize;
2430 size_hints.min_width = geometry->min_width;
2431 size_hints.min_height = geometry->min_height;
2434 if (geom_mask & GDK_HINT_MAX_SIZE)
2436 size_hints.flags |= PMaxSize;
2437 size_hints.max_width = MAX (geometry->max_width, 1);
2438 size_hints.max_height = MAX (geometry->max_height, 1);
2441 if (geom_mask & GDK_HINT_BASE_SIZE)
2443 size_hints.flags |= PBaseSize;
2444 size_hints.base_width = geometry->base_width;
2445 size_hints.base_height = geometry->base_height;
2448 if (geom_mask & GDK_HINT_RESIZE_INC)
2450 size_hints.flags |= PResizeInc;
2451 size_hints.width_inc = geometry->width_inc;
2452 size_hints.height_inc = geometry->height_inc;
2455 if (geom_mask & GDK_HINT_ASPECT)
2457 size_hints.flags |= PAspect;
2458 if (geometry->min_aspect <= 1)
2460 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2461 size_hints.min_aspect.y = 65536;
2465 size_hints.min_aspect.x = 65536;
2466 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2468 if (geometry->max_aspect <= 1)
2470 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2471 size_hints.max_aspect.y = 65536;
2475 size_hints.max_aspect.x = 65536;
2476 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2480 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2482 size_hints.flags |= PWinGravity;
2483 size_hints.win_gravity = geometry->win_gravity;
2486 /* FIXME: Would it be better to delete this property if
2487 * geom_mask == 0? It would save space on the server
2489 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2490 GDK_WINDOW_XID (window),
2495 gdk_window_get_geometry_hints (GdkWindow *window,
2496 GdkGeometry *geometry,
2497 GdkWindowHints *geom_mask)
2499 XSizeHints *size_hints;
2500 glong junk_supplied_mask = 0;
2502 g_return_if_fail (GDK_IS_WINDOW (window));
2503 g_return_if_fail (geometry != NULL);
2504 g_return_if_fail (geom_mask != NULL);
2508 if (GDK_WINDOW_DESTROYED (window) ||
2509 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2512 size_hints = XAllocSizeHints ();
2516 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2517 GDK_WINDOW_XID (window),
2519 &junk_supplied_mask))
2520 size_hints->flags = 0;
2522 if (size_hints->flags & PMinSize)
2524 *geom_mask |= GDK_HINT_MIN_SIZE;
2525 geometry->min_width = size_hints->min_width;
2526 geometry->min_height = size_hints->min_height;
2529 if (size_hints->flags & PMaxSize)
2531 *geom_mask |= GDK_HINT_MAX_SIZE;
2532 geometry->max_width = MAX (size_hints->max_width, 1);
2533 geometry->max_height = MAX (size_hints->max_height, 1);
2536 if (size_hints->flags & PResizeInc)
2538 *geom_mask |= GDK_HINT_RESIZE_INC;
2539 geometry->width_inc = size_hints->width_inc;
2540 geometry->height_inc = size_hints->height_inc;
2543 if (size_hints->flags & PAspect)
2545 *geom_mask |= GDK_HINT_ASPECT;
2547 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2548 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2551 if (size_hints->flags & PWinGravity)
2553 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2554 geometry->win_gravity = size_hints->win_gravity;
2561 utf8_is_latin1 (const gchar *str)
2563 const char *p = str;
2567 gunichar ch = g_utf8_get_char (p);
2572 p = g_utf8_next_char (p);
2578 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2579 * convertable to STRING, otherwise, set it as compound text
2582 set_text_property (GdkDisplay *display,
2585 const gchar *utf8_str)
2587 gchar *prop_text = NULL;
2591 gboolean is_compound_text;
2593 if (utf8_is_latin1 (utf8_str))
2595 prop_type = XA_STRING;
2596 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2597 prop_length = prop_text ? strlen (prop_text) : 0;
2599 is_compound_text = FALSE;
2605 gdk_x11_display_utf8_to_compound_text (display,
2606 utf8_str, &gdk_type, &prop_format,
2607 (guchar **)&prop_text, &prop_length);
2608 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2609 is_compound_text = TRUE;
2614 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2617 prop_type, prop_format,
2618 PropModeReplace, (guchar *)prop_text,
2621 if (is_compound_text)
2622 gdk_x11_free_compound_text ((guchar *)prop_text);
2628 /* Set WM_NAME and _NET_WM_NAME
2631 set_wm_name (GdkDisplay *display,
2635 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2636 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2637 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2638 PropModeReplace, (guchar *)name, strlen (name));
2640 set_text_property (display, xwindow,
2641 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2646 gdk_x11_window_set_title (GdkWindow *window,
2649 GdkDisplay *display;
2653 g_return_if_fail (title != NULL);
2655 if (GDK_WINDOW_DESTROYED (window) ||
2656 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2659 display = gdk_window_get_display (window);
2660 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2661 xwindow = GDK_WINDOW_XID (window);
2663 set_wm_name (display, xwindow, title);
2665 if (!gdk_window_icon_name_set (window))
2667 XChangeProperty (xdisplay, xwindow,
2668 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2669 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2670 PropModeReplace, (guchar *)title, strlen (title));
2672 set_text_property (display, xwindow,
2673 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2679 gdk_x11_window_set_role (GdkWindow *window,
2682 GdkDisplay *display;
2684 display = gdk_window_get_display (window);
2686 if (GDK_WINDOW_DESTROYED (window) ||
2687 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2691 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2692 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2693 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2695 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2696 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2700 gdk_x11_window_set_startup_id (GdkWindow *window,
2701 const gchar *startup_id)
2703 GdkDisplay *display;
2705 g_return_if_fail (GDK_IS_WINDOW (window));
2707 display = gdk_window_get_display (window);
2709 if (GDK_WINDOW_DESTROYED (window) ||
2710 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2714 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2715 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2716 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2717 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2719 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2720 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2724 gdk_x11_window_set_transient_for (GdkWindow *window,
2727 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2728 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2729 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2730 GDK_WINDOW_XID (window),
2731 GDK_WINDOW_XID (parent));
2735 gdk_window_x11_set_back_color (GdkWindow *window,
2741 GdkVisual *visual = gdk_window_get_visual (window);
2743 /* I suppose we could handle these, but that'd require fiddling with
2744 * xrender formats... */
2748 switch (visual->type)
2750 case GDK_VISUAL_DIRECT_COLOR:
2751 case GDK_VISUAL_TRUE_COLOR:
2753 /* If bits not used for color are used for something other than padding,
2754 * it's likely alpha, so we set them to 1s.
2756 guint padding, pixel;
2758 /* Shifting by >= width-of-type isn't defined in C */
2759 if (visual->depth >= 32)
2762 padding = ((~(guint32)0)) << visual->depth;
2764 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2766 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2767 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2768 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2770 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2771 GDK_WINDOW_XID (window), pixel);
2775 /* These require fiddling with the colormap, and as they're essentially unused
2776 * we're just gonna skip them for now.
2778 case GDK_VISUAL_PSEUDO_COLOR:
2779 case GDK_VISUAL_GRAYSCALE:
2780 case GDK_VISUAL_STATIC_GRAY:
2781 case GDK_VISUAL_STATIC_COLOR:
2790 matrix_is_identity (cairo_matrix_t *matrix)
2792 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2793 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2794 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2798 gdk_window_x11_set_background (GdkWindow *window,
2799 cairo_pattern_t *pattern)
2802 cairo_surface_t *surface;
2803 cairo_matrix_t matrix;
2805 if (GDK_WINDOW_DESTROYED (window))
2808 if (pattern == NULL)
2812 /* X throws BadMatch if the parent has a different visual when
2813 * using ParentRelative */
2814 parent = gdk_window_get_parent (window);
2815 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2816 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2817 GDK_WINDOW_XID (window), ParentRelative);
2819 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2820 GDK_WINDOW_XID (window), None);
2824 switch (cairo_pattern_get_type (pattern))
2826 case CAIRO_PATTERN_TYPE_SOLID:
2827 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2828 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2831 case CAIRO_PATTERN_TYPE_SURFACE:
2832 cairo_pattern_get_matrix (pattern, &matrix);
2833 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2834 matrix_is_identity (&matrix) &&
2835 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2836 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2837 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2841 cairo_surface_get_device_offset (surface, &x, &y);
2842 /* XXX: This still bombs for non-pixmaps, but there's no way to
2843 * detect we're not a pixmap in Cairo... */
2844 if (x == 0.0 && y == 0.0)
2846 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2847 GDK_WINDOW_XID (window),
2848 cairo_xlib_surface_get_drawable (surface));
2853 case CAIRO_PATTERN_TYPE_LINEAR:
2854 case CAIRO_PATTERN_TYPE_RADIAL:
2856 /* fallback: just use black */
2860 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2861 GDK_WINDOW_XID (window), None);
2865 gdk_window_x11_set_device_cursor (GdkWindow *window,
2869 GdkWindowImplX11 *impl;
2871 g_return_if_fail (GDK_IS_WINDOW (window));
2872 g_return_if_fail (GDK_IS_DEVICE (device));
2874 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2877 g_hash_table_remove (impl->device_cursor, device);
2880 _gdk_x11_cursor_update_theme (cursor);
2881 g_hash_table_replace (impl->device_cursor,
2882 device, g_object_ref (cursor));
2885 if (!GDK_WINDOW_DESTROYED (window))
2886 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2890 _gdk_x11_window_get_cursor (GdkWindow *window)
2892 GdkWindowImplX11 *impl;
2894 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2896 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2898 return impl->cursor;
2902 gdk_window_x11_get_geometry (GdkWindow *window,
2913 guint tborder_width;
2916 if (!GDK_WINDOW_DESTROYED (window))
2918 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2919 GDK_WINDOW_XID (window),
2920 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2934 gdk_window_x11_get_root_coords (GdkWindow *window,
2945 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2946 GDK_WINDOW_XID (window),
2947 GDK_WINDOW_XROOTWIN (window),
2960 gdk_x11_window_get_root_origin (GdkWindow *window,
2966 gdk_window_get_frame_extents (window, &rect);
2976 gdk_x11_window_get_frame_extents (GdkWindow *window,
2979 GdkDisplay *display;
2980 GdkWindowImplX11 *impl;
2991 gulong nitems_return;
2992 gulong bytes_after_return;
2995 guint ww, wh, wb, wd;
2997 gboolean got_frame_extents = FALSE;
2999 g_return_if_fail (rect != NULL);
3006 while (window->parent && (window->parent)->parent)
3007 window = window->parent;
3009 /* Refine our fallback answer a bit using local information */
3010 rect->x = window->x;
3011 rect->y = window->y;
3012 rect->width = window->width;
3013 rect->height = window->height;
3015 impl = GDK_WINDOW_IMPL_X11 (window->impl);
3016 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
3022 display = gdk_window_get_display (window);
3024 gdk_x11_display_error_trap_push (display);
3026 xwindow = GDK_WINDOW_XID (window);
3028 /* first try: use _NET_FRAME_EXTENTS */
3029 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3030 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
3031 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
3032 gdk_x11_get_xatom_by_name_for_display (display,
3033 "_NET_FRAME_EXTENTS"),
3034 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
3035 &format_return, &nitems_return, &bytes_after_return,
3039 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
3040 (nitems_return == 4) && (data))
3042 gulong *ldata = (gulong *) data;
3043 got_frame_extents = TRUE;
3045 /* try to get the real client window geometry */
3046 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3047 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
3048 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
3049 xwindow, root, 0, 0, &wx, &wy, &child))
3057 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
3058 rect->x -= ldata[0];
3059 rect->y -= ldata[2];
3060 rect->width += ldata[0] + ldata[1];
3061 rect->height += ldata[2] + ldata[3];
3068 if (got_frame_extents)
3071 /* no frame extents property available, which means we either have a WM that
3072 is not EWMH compliant or is broken - try fallback and walk up the window
3073 tree to get our window's parent which hopefully is the window frame */
3075 /* use NETWM_VIRTUAL_ROOTS if available */
3076 root = GDK_WINDOW_XROOTWIN (window);
3078 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3079 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
3080 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
3081 gdk_x11_get_xatom_by_name_for_display (display,
3082 "_NET_VIRTUAL_ROOTS"),
3083 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3084 &format_return, &nitems_return, &bytes_after_return,
3088 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
3090 nvroots = nitems_return;
3091 vroots = (Window *)data;
3095 xparent = GDK_WINDOW_XID (window);
3101 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3103 &children, &nchildren))
3109 /* check virtual roots */
3110 for (i = 0; i < nvroots; i++)
3112 if (xparent == vroots[i])
3119 while (xparent != root);
3121 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3122 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3134 gdk_x11_display_error_trap_pop_ignored (display);
3138 gdk_window_x11_get_device_state (GdkWindow *window,
3142 GdkModifierType *mask)
3146 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3148 if (GDK_WINDOW_DESTROYED (window))
3151 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3155 return child != NULL;
3159 gdk_window_x11_get_events (GdkWindow *window)
3161 XWindowAttributes attrs;
3162 GdkEventMask event_mask;
3163 GdkEventMask filtered;
3165 if (GDK_WINDOW_DESTROYED (window))
3169 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3170 GDK_WINDOW_XID (window),
3172 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3173 /* if property change was filtered out before, keep it filtered out */
3174 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3175 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3181 gdk_window_x11_set_events (GdkWindow *window,
3182 GdkEventMask event_mask)
3184 long xevent_mask = 0;
3186 if (!GDK_WINDOW_DESTROYED (window))
3188 GdkX11Display *display_x11;
3190 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3191 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3193 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3194 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3195 GDK_WINDOW_XID (window), event_mask,
3201 do_shape_combine_region (GdkWindow *window,
3202 const cairo_region_t *shape_region,
3207 if (GDK_WINDOW_DESTROYED (window))
3210 if (shape_region == NULL)
3212 /* Use NULL mask to unset the shape */
3213 if (shape == ShapeBounding
3214 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3215 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3217 if (shape == ShapeBounding)
3219 _gdk_x11_window_tmp_unset_parent_bg (window);
3220 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3222 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3223 GDK_WINDOW_XID (window),
3228 if (shape == ShapeBounding)
3230 _gdk_x11_window_tmp_reset_parent_bg (window);
3231 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3237 if (shape == ShapeBounding
3238 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3239 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3242 XRectangle *xrects = NULL;
3244 _gdk_x11_region_get_xrectangles (shape_region,
3248 if (shape == ShapeBounding)
3250 _gdk_x11_window_tmp_unset_parent_bg (window);
3251 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3253 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3254 GDK_WINDOW_XID (window),
3261 if (shape == ShapeBounding)
3263 _gdk_x11_window_tmp_reset_parent_bg (window);
3264 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3272 gdk_window_x11_shape_combine_region (GdkWindow *window,
3273 const cairo_region_t *shape_region,
3277 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3281 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3282 const cairo_region_t *shape_region,
3287 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3293 gdk_x11_window_set_override_redirect (GdkWindow *window,
3294 gboolean override_redirect)
3296 XSetWindowAttributes attr;
3298 if (!GDK_WINDOW_DESTROYED (window) &&
3299 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3301 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3303 attr.override_redirect = (override_redirect? True : False);
3304 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3305 GDK_WINDOW_XID (window),
3309 impl->override_redirect = attr.override_redirect;
3314 gdk_x11_window_set_accept_focus (GdkWindow *window,
3315 gboolean accept_focus)
3317 accept_focus = accept_focus != FALSE;
3319 if (window->accept_focus != accept_focus)
3321 window->accept_focus = accept_focus;
3323 if (!GDK_WINDOW_DESTROYED (window) &&
3324 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3325 update_wm_hints (window, FALSE);
3330 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3331 gboolean focus_on_map)
3333 focus_on_map = focus_on_map != FALSE;
3335 if (window->focus_on_map != focus_on_map)
3337 window->focus_on_map = focus_on_map;
3339 if ((!GDK_WINDOW_DESTROYED (window)) &&
3340 (!window->focus_on_map) &&
3341 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3342 gdk_x11_window_set_user_time (window, 0);
3347 * gdk_x11_window_set_user_time:
3348 * @window: (type GdkX11Window): A toplevel #GdkWindow
3349 * @timestamp: An XServer timestamp to which the property should be set
3351 * The application can use this call to update the _NET_WM_USER_TIME
3352 * property on a toplevel window. This property stores an Xserver
3353 * time which represents the time of the last user input event
3354 * received for this window. This property may be used by the window
3355 * manager to alter the focus, stacking, and/or placement behavior of
3356 * windows when they are mapped depending on whether the new window
3357 * was created by a user action or is a "pop-up" window activated by a
3358 * timer or some other event.
3360 * Note that this property is automatically updated by GDK, so this
3361 * function should only be used by applications which handle input
3362 * events bypassing GDK.
3367 gdk_x11_window_set_user_time (GdkWindow *window,
3370 GdkDisplay *display;
3371 GdkX11Display *display_x11;
3372 GdkToplevelX11 *toplevel;
3373 glong timestamp_long = (glong)timestamp;
3376 if (GDK_WINDOW_DESTROYED (window) ||
3377 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3380 display = gdk_window_get_display (window);
3381 display_x11 = GDK_X11_DISPLAY (display);
3382 toplevel = _gdk_x11_window_get_toplevel (window);
3386 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3390 if (toplevel->focus_window != None &&
3391 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3392 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3393 xid = toplevel->focus_window;
3395 xid = GDK_WINDOW_XID (window);
3397 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3398 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3399 XA_CARDINAL, 32, PropModeReplace,
3400 (guchar *)×tamp_long, 1);
3402 if (timestamp_long != GDK_CURRENT_TIME &&
3403 (display_x11->user_time == GDK_CURRENT_TIME ||
3404 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3405 display_x11->user_time = timestamp_long;
3408 toplevel->user_time = timestamp_long;
3412 * gdk_x11_window_set_utf8_property:
3413 * @window: (type GdkX11Window): a #GdkWindow
3414 * @name: Property name, will be interned as an X atom
3415 * @value: (allow-none): Property value, or %NULL to delete
3417 * This function modifies or removes an arbitrary X11 window
3418 * property of type UTF8_STRING. If the given @window is
3419 * not a toplevel window, it is ignored.
3424 gdk_x11_window_set_utf8_property (GdkWindow *window,
3428 GdkDisplay *display;
3430 if (!WINDOW_IS_TOPLEVEL (window))
3433 display = gdk_window_get_display (window);
3437 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3438 GDK_WINDOW_XID (window),
3439 gdk_x11_get_xatom_by_name_for_display (display, name),
3440 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3441 PropModeReplace, (guchar *)value, strlen (value));
3445 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3446 GDK_WINDOW_XID (window),
3447 gdk_x11_get_xatom_by_name_for_display (display, name));
3452 * gdk_x11_window_set_hide_titlebar_when_maximized:
3453 * @window: (type GdkX11Window): a #GdkWindow
3454 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3457 * Set a hint for the window manager, requesting that the titlebar
3458 * should be hidden when the window is maximized.
3460 * Note that this property is automatically updated by GTK+, so this
3461 * function should only be used by applications which do not use GTK+
3462 * to create toplevel windows.
3467 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3468 gboolean hide_titlebar_when_maximized)
3470 GdkDisplay *display;
3472 if (!WINDOW_IS_TOPLEVEL (window))
3475 display = gdk_window_get_display (window);
3477 if (hide_titlebar_when_maximized)
3480 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3481 GDK_WINDOW_XID (window),
3482 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3484 PropModeReplace, (guchar *)&hide, 1);
3488 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3489 GDK_WINDOW_XID (window),
3490 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3495 * gdk_x11_window_set_theme_variant:
3496 * @window: (type GdkX11Window): a #GdkWindow
3497 * @variant: the theme variant to export
3499 * GTK+ applications can request a dark theme variant. In order to
3500 * make other applications - namely window managers using GTK+ for
3501 * themeing - aware of this choice, GTK+ uses this function to
3502 * export the requested theme variant as _GTK_THEME_VARIANT property
3503 * on toplevel windows.
3505 * Note that this property is automatically updated by GTK+, so this
3506 * function should only be used by applications which do not use GTK+
3507 * to create toplevel windows.
3512 gdk_x11_window_set_theme_variant (GdkWindow *window,
3515 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3518 #define GDK_SELECTION_MAX_SIZE(display) \
3520 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3521 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3522 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3525 gdk_window_update_icon (GdkWindow *window,
3528 GdkToplevelX11 *toplevel;
3529 GdkPixbuf *best_icon;
3533 toplevel = _gdk_x11_window_get_toplevel (window);
3535 if (toplevel->icon_pixmap != NULL)
3537 cairo_surface_destroy (toplevel->icon_pixmap);
3538 toplevel->icon_pixmap = NULL;
3541 if (toplevel->icon_mask != NULL)
3543 cairo_surface_destroy (toplevel->icon_mask);
3544 toplevel->icon_mask = NULL;
3547 #define IDEAL_SIZE 48
3549 best_size = G_MAXINT;
3551 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3553 GdkPixbuf *pixbuf = tmp_list->data;
3556 /* average width and height - if someone passes in a rectangular
3557 * icon they deserve what they get.
3559 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3562 if (best_icon == NULL)
3569 /* icon is better if it's 32 pixels or larger, and closer to
3570 * the ideal size than the current best.
3573 (ABS (best_size - IDEAL_SIZE) <
3574 ABS (this - IDEAL_SIZE)))
3584 int width = gdk_pixbuf_get_width (best_icon);
3585 int height = gdk_pixbuf_get_height (best_icon);
3588 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3592 cr = cairo_create (toplevel->icon_pixmap);
3593 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3594 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3595 if (gdk_pixbuf_get_has_alpha (best_icon))
3597 /* Saturate the image, so it has bilevel alpha */
3598 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3600 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3602 cairo_pop_group_to_source (cr);
3607 if (gdk_pixbuf_get_has_alpha (best_icon))
3609 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3613 cr = cairo_create (toplevel->icon_mask);
3614 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3615 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3621 update_wm_hints (window, FALSE);
3625 gdk_x11_window_set_icon_list (GdkWindow *window,
3634 gint width, height, stride;
3637 GdkDisplay *display;
3640 if (GDK_WINDOW_DESTROYED (window) ||
3641 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3644 display = gdk_window_get_display (window);
3652 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3654 width = gdk_pixbuf_get_width (pixbuf);
3655 height = gdk_pixbuf_get_height (pixbuf);
3657 /* silently ignore overlarge icons */
3658 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3660 g_warning ("gdk_window_set_icon_list: icons too large");
3665 size += 2 + width * height;
3667 l = g_list_next (l);
3670 data = g_malloc (size * sizeof (gulong));
3678 width = gdk_pixbuf_get_width (pixbuf);
3679 height = gdk_pixbuf_get_height (pixbuf);
3680 stride = gdk_pixbuf_get_rowstride (pixbuf);
3681 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3686 pixels = gdk_pixbuf_get_pixels (pixbuf);
3688 for (y = 0; y < height; y++)
3690 for (x = 0; x < width; x++)
3694 r = pixels[y*stride + x*n_channels + 0];
3695 g = pixels[y*stride + x*n_channels + 1];
3696 b = pixels[y*stride + x*n_channels + 2];
3697 if (n_channels >= 4)
3698 a = pixels[y*stride + x*n_channels + 3];
3702 *p++ = a << 24 | r << 16 | g << 8 | b ;
3706 l = g_list_next (l);
3712 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3713 GDK_WINDOW_XID (window),
3714 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3717 (guchar*) data, size);
3721 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3722 GDK_WINDOW_XID (window),
3723 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3728 gdk_window_update_icon (window, pixbufs);
3732 gdk_window_icon_name_set (GdkWindow *window)
3734 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3735 g_quark_from_static_string ("gdk-icon-name-set")));
3739 gdk_x11_window_set_icon_name (GdkWindow *window,
3742 GdkDisplay *display;
3744 if (GDK_WINDOW_DESTROYED (window) ||
3745 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3748 display = gdk_window_get_display (window);
3750 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3751 GUINT_TO_POINTER (name != NULL));
3755 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3756 GDK_WINDOW_XID (window),
3757 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3758 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3759 PropModeReplace, (guchar *)name, strlen (name));
3761 set_text_property (display, GDK_WINDOW_XID (window),
3762 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3767 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3768 GDK_WINDOW_XID (window),
3769 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3770 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3771 GDK_WINDOW_XID (window),
3772 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3777 gdk_x11_window_iconify (GdkWindow *window)
3779 if (GDK_WINDOW_DESTROYED (window) ||
3780 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3783 if (GDK_WINDOW_IS_MAPPED (window))
3785 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3786 GDK_WINDOW_XID (window),
3787 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3791 /* Flip our client side flag, the real work happens on map. */
3792 gdk_synthesize_window_state (window,
3794 GDK_WINDOW_STATE_ICONIFIED);
3795 gdk_wmspec_change_state (TRUE, window,
3796 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3802 gdk_x11_window_deiconify (GdkWindow *window)
3804 if (GDK_WINDOW_DESTROYED (window) ||
3805 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3808 if (GDK_WINDOW_IS_MAPPED (window))
3810 gdk_window_show (window);
3811 gdk_wmspec_change_state (FALSE, window,
3812 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3817 /* Flip our client side flag, the real work happens on map. */
3818 gdk_synthesize_window_state (window,
3819 GDK_WINDOW_STATE_ICONIFIED,
3821 gdk_wmspec_change_state (FALSE, window,
3822 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3828 gdk_x11_window_stick (GdkWindow *window)
3830 if (GDK_WINDOW_DESTROYED (window) ||
3831 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3834 if (GDK_WINDOW_IS_MAPPED (window))
3836 /* "stick" means stick to all desktops _and_ do not scroll with the
3837 * viewport. i.e. glue to the monitor glass in all cases.
3840 XClientMessageEvent xclient;
3842 /* Request stick during viewport scroll */
3843 gdk_wmspec_change_state (TRUE, window,
3844 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3847 /* Request desktop 0xFFFFFFFF */
3848 memset (&xclient, 0, sizeof (xclient));
3849 xclient.type = ClientMessage;
3850 xclient.window = GDK_WINDOW_XID (window);
3851 xclient.display = GDK_WINDOW_XDISPLAY (window);
3852 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3854 xclient.format = 32;
3856 xclient.data.l[0] = 0xFFFFFFFF;
3857 xclient.data.l[1] = 0;
3858 xclient.data.l[2] = 0;
3859 xclient.data.l[3] = 0;
3860 xclient.data.l[4] = 0;
3862 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3863 SubstructureRedirectMask | SubstructureNotifyMask,
3864 (XEvent *)&xclient);
3868 /* Flip our client side flag, the real work happens on map. */
3869 gdk_synthesize_window_state (window,
3871 GDK_WINDOW_STATE_STICKY);
3876 gdk_x11_window_unstick (GdkWindow *window)
3878 if (GDK_WINDOW_DESTROYED (window) ||
3879 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3882 if (GDK_WINDOW_IS_MAPPED (window))
3884 /* Request unstick from viewport */
3885 gdk_wmspec_change_state (FALSE, window,
3886 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3889 move_to_current_desktop (window);
3893 /* Flip our client side flag, the real work happens on map. */
3894 gdk_synthesize_window_state (window,
3895 GDK_WINDOW_STATE_STICKY,
3902 gdk_x11_window_maximize (GdkWindow *window)
3904 if (GDK_WINDOW_DESTROYED (window) ||
3905 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3908 if (GDK_WINDOW_IS_MAPPED (window))
3909 gdk_wmspec_change_state (TRUE, window,
3910 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3911 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3913 gdk_synthesize_window_state (window,
3915 GDK_WINDOW_STATE_MAXIMIZED);
3919 gdk_x11_window_unmaximize (GdkWindow *window)
3921 if (GDK_WINDOW_DESTROYED (window) ||
3922 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3925 if (GDK_WINDOW_IS_MAPPED (window))
3926 gdk_wmspec_change_state (FALSE, window,
3927 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3928 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3930 gdk_synthesize_window_state (window,
3931 GDK_WINDOW_STATE_MAXIMIZED,
3936 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3938 if (GDK_WINDOW_DESTROYED (window) ||
3939 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3942 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3943 * to which monitors so span across when the window is fullscreen, but it's
3944 * not a state in itself so this would have no effect if the window is not
3948 if (GDK_WINDOW_IS_MAPPED (window))
3950 XClientMessageEvent xclient;
3951 gint gdk_monitors[4];
3954 memset (&xclient, 0, sizeof (xclient));
3955 xclient.type = ClientMessage;
3956 xclient.window = GDK_WINDOW_XID (window);
3957 xclient.display = GDK_WINDOW_XDISPLAY (window);
3958 xclient.format = 32;
3960 switch (window->fullscreen_mode)
3962 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3964 /* FIXME: This is not part of the EWMH spec!
3966 * There is no documented mechanism to remove the property
3967 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3968 * invalid, largest possible value.
3970 * When given values larger than actual possible monitor values, most
3971 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3972 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3975 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3977 * Note, this (non documented) mechanism is unlikely to be an issue
3978 * as it's used only for transitionning back from "all monitors" to
3979 * "current monitor" mode.
3981 * Applications who don't change the default mode won't trigger this
3984 for (i = 0; i < 4; ++i)
3985 xclient.data.l[i] = G_MAXLONG;
3989 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3991 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3996 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3997 for (i = 0; i < 4; ++i)
3999 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
4001 /* Sanity check, if XINERAMA is not available, we could have invalid
4002 * negative values for the XINERAMA indices.
4004 if (xclient.data.l[i] < 0)
4006 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
4013 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
4014 window->fullscreen_mode);
4018 /* Send fullscreen monitors client message */
4019 xclient.data.l[4] = 1; /* source indication */
4020 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
4021 "_NET_WM_FULLSCREEN_MONITORS");
4022 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
4023 SubstructureRedirectMask | SubstructureNotifyMask,
4024 (XEvent *)&xclient);
4029 gdk_x11_window_fullscreen (GdkWindow *window)
4031 if (GDK_WINDOW_DESTROYED (window) ||
4032 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4035 if (GDK_WINDOW_IS_MAPPED (window))
4037 gdk_wmspec_change_state (TRUE, window,
4038 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4040 /* Actual XRandR layout may have change since we computed the fullscreen
4041 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
4043 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
4044 gdk_x11_window_apply_fullscreen_mode (window);
4047 gdk_synthesize_window_state (window,
4049 GDK_WINDOW_STATE_FULLSCREEN);
4053 gdk_x11_window_unfullscreen (GdkWindow *window)
4055 if (GDK_WINDOW_DESTROYED (window) ||
4056 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4059 if (GDK_WINDOW_IS_MAPPED (window))
4060 gdk_wmspec_change_state (FALSE, window,
4061 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
4065 gdk_synthesize_window_state (window,
4066 GDK_WINDOW_STATE_FULLSCREEN,
4071 gdk_x11_window_set_keep_above (GdkWindow *window,
4074 g_return_if_fail (GDK_IS_WINDOW (window));
4076 if (GDK_WINDOW_DESTROYED (window) ||
4077 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4080 if (GDK_WINDOW_IS_MAPPED (window))
4083 gdk_wmspec_change_state (FALSE, window,
4084 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4086 gdk_wmspec_change_state (setting, window,
4087 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4091 gdk_synthesize_window_state (window,
4092 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
4093 setting ? GDK_WINDOW_STATE_ABOVE : 0);
4097 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
4099 g_return_if_fail (GDK_IS_WINDOW (window));
4101 if (GDK_WINDOW_DESTROYED (window) ||
4102 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4105 if (GDK_WINDOW_IS_MAPPED (window))
4108 gdk_wmspec_change_state (FALSE, window,
4109 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4111 gdk_wmspec_change_state (setting, window,
4112 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4116 gdk_synthesize_window_state (window,
4117 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4118 setting ? GDK_WINDOW_STATE_BELOW : 0);
4122 gdk_x11_window_get_group (GdkWindow *window)
4124 GdkToplevelX11 *toplevel;
4126 if (GDK_WINDOW_DESTROYED (window) ||
4127 !WINDOW_IS_TOPLEVEL (window))
4130 toplevel = _gdk_x11_window_get_toplevel (window);
4132 return toplevel->group_leader;
4136 gdk_x11_window_set_group (GdkWindow *window,
4139 GdkToplevelX11 *toplevel;
4141 g_return_if_fail (GDK_IS_WINDOW (window));
4142 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4143 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4145 if (GDK_WINDOW_DESTROYED (window) ||
4146 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4147 !WINDOW_IS_TOPLEVEL (window))
4150 toplevel = _gdk_x11_window_get_toplevel (window);
4153 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4155 if (toplevel->group_leader != leader)
4157 if (toplevel->group_leader)
4158 g_object_unref (toplevel->group_leader);
4159 toplevel->group_leader = g_object_ref (leader);
4160 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4163 update_wm_hints (window, FALSE);
4166 static MotifWmHints *
4167 gdk_window_get_mwm_hints (GdkWindow *window)
4169 GdkDisplay *display;
4170 Atom hints_atom = None;
4177 if (GDK_WINDOW_DESTROYED (window))
4180 display = gdk_window_get_display (window);
4182 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4184 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4185 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4186 False, AnyPropertyType, &type, &format, &nitems,
4187 &bytes_after, &data);
4192 return (MotifWmHints *)data;
4196 gdk_window_set_mwm_hints (GdkWindow *window,
4197 MotifWmHints *new_hints)
4199 GdkDisplay *display;
4200 Atom hints_atom = None;
4202 MotifWmHints *hints;
4208 if (GDK_WINDOW_DESTROYED (window))
4211 display = gdk_window_get_display (window);
4213 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4215 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4216 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4217 False, AnyPropertyType, &type, &format, &nitems,
4218 &bytes_after, &data);
4224 hints = (MotifWmHints *)data;
4226 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4228 hints->flags |= MWM_HINTS_FUNCTIONS;
4229 hints->functions = new_hints->functions;
4231 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4233 hints->flags |= MWM_HINTS_DECORATIONS;
4234 hints->decorations = new_hints->decorations;
4238 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4239 hints_atom, hints_atom, 32, PropModeReplace,
4240 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4242 if (hints != new_hints)
4247 gdk_x11_window_set_decorations (GdkWindow *window,
4248 GdkWMDecoration decorations)
4252 if (GDK_WINDOW_DESTROYED (window) ||
4253 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4256 /* initialize to zero to avoid writing uninitialized data to socket */
4257 memset(&hints, 0, sizeof(hints));
4258 hints.flags = MWM_HINTS_DECORATIONS;
4259 hints.decorations = decorations;
4261 gdk_window_set_mwm_hints (window, &hints);
4265 gdk_x11_window_get_decorations(GdkWindow *window,
4266 GdkWMDecoration *decorations)
4268 MotifWmHints *hints;
4269 gboolean result = FALSE;
4271 if (GDK_WINDOW_DESTROYED (window) ||
4272 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4275 hints = gdk_window_get_mwm_hints (window);
4279 if (hints->flags & MWM_HINTS_DECORATIONS)
4282 *decorations = hints->decorations;
4293 gdk_x11_window_set_functions (GdkWindow *window,
4294 GdkWMFunction functions)
4298 g_return_if_fail (GDK_IS_WINDOW (window));
4300 if (GDK_WINDOW_DESTROYED (window) ||
4301 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4304 /* initialize to zero to avoid writing uninitialized data to socket */
4305 memset(&hints, 0, sizeof(hints));
4306 hints.flags = MWM_HINTS_FUNCTIONS;
4307 hints.functions = functions;
4309 gdk_window_set_mwm_hints (window, &hints);
4313 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4317 cairo_region_t *shape;
4325 /* Note that XShapeGetRectangles returns NULL in two situations:
4326 * - the server doesn't support the SHAPE extension
4327 * - the shape is empty
4329 * Since we can't discriminate these here, we always return
4330 * an empty shape. It is the callers responsibility to check
4331 * whether the server supports the SHAPE extensions beforehand.
4333 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4336 return cairo_region_create (); /* Empty */
4338 if (ord != YXBanded)
4340 /* This really shouldn't happen with any xserver, as they
4341 * generally convert regions to YXBanded internally
4343 g_warning ("non YXBanded shape masks not supported");
4348 rl = g_new (GdkRectangle, rn);
4349 for (i = 0; i < rn; i++)
4353 rl[i].width = xrl[i].width;
4354 rl[i].height = xrl[i].height;
4358 shape = cairo_region_create_rectangles (rl, rn);
4365 static cairo_region_t *
4366 gdk_x11_window_get_shape (GdkWindow *window)
4368 if (!GDK_WINDOW_DESTROYED (window) &&
4369 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4370 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4371 GDK_WINDOW_XID (window),
4377 static cairo_region_t *
4378 gdk_x11_window_get_input_shape (GdkWindow *window)
4380 #if defined(ShapeInput)
4381 if (!GDK_WINDOW_DESTROYED (window) &&
4382 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4383 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4384 GDK_WINDOW_XID (window),
4392 gdk_window_set_static_bit_gravity (GdkWindow *window,
4395 XSetWindowAttributes xattributes;
4396 guint xattributes_mask = 0;
4398 g_return_if_fail (GDK_IS_WINDOW (window));
4400 if (window->input_only)
4403 xattributes.bit_gravity = StaticGravity;
4404 xattributes_mask |= CWBitGravity;
4405 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4406 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4407 GDK_WINDOW_XID (window),
4408 CWBitGravity, &xattributes);
4412 gdk_window_set_static_win_gravity (GdkWindow *window,
4415 XSetWindowAttributes xattributes;
4417 g_return_if_fail (GDK_IS_WINDOW (window));
4419 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4421 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4422 GDK_WINDOW_XID (window),
4423 CWWinGravity, &xattributes);
4427 gdk_window_x11_set_static_gravities (GdkWindow *window,
4428 gboolean use_static)
4432 if (!use_static == !window->guffaw_gravity)
4435 window->guffaw_gravity = use_static;
4437 if (!GDK_WINDOW_DESTROYED (window))
4439 gdk_window_set_static_bit_gravity (window, use_static);
4441 tmp_list = window->children;
4444 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4446 tmp_list = tmp_list->next;
4453 /* From the WM spec */
4454 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4455 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4456 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4457 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4458 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4459 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4460 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4461 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4462 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4463 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4464 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4465 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4468 wmspec_send_message (GdkDisplay *display,
4475 XClientMessageEvent xclient;
4477 memset (&xclient, 0, sizeof (xclient));
4478 xclient.type = ClientMessage;
4479 xclient.window = GDK_WINDOW_XID (window);
4480 xclient.message_type =
4481 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4482 xclient.format = 32;
4483 xclient.data.l[0] = root_x;
4484 xclient.data.l[1] = root_y;
4485 xclient.data.l[2] = action;
4486 xclient.data.l[3] = button;
4487 xclient.data.l[4] = 1; /* source indication */
4489 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4490 SubstructureRedirectMask | SubstructureNotifyMask,
4491 (XEvent *)&xclient);
4495 handle_wmspec_button_release (GdkDisplay *display,
4498 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4501 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4502 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4503 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4505 if (xevent->xany.type == GenericEvent)
4506 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4509 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4511 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4513 if ((xevent->xany.type == ButtonRelease &&
4514 xevent->xbutton.button == display_x11->wm_moveresize_button)
4515 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4517 (xevent->xany.type == GenericEvent &&
4518 xiev->evtype == XI_ButtonRelease &&
4519 xidev->detail == display_x11->wm_moveresize_button)
4523 display_x11->wm_moveresize_button = 0;
4524 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4530 wmspec_moveresize (GdkWindow *window,
4538 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4540 /* Release passive grab */
4541 gdk_device_ungrab (device, timestamp);
4542 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4544 wmspec_send_message (display, window, root_x, root_y, direction, button);
4548 wmspec_resize_drag (GdkWindow *window,
4558 /* Let the compiler turn a switch into a table, instead
4559 * of doing the table manually, this way is easier to verify.
4563 case GDK_WINDOW_EDGE_NORTH_WEST:
4564 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4567 case GDK_WINDOW_EDGE_NORTH:
4568 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4571 case GDK_WINDOW_EDGE_NORTH_EAST:
4572 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4575 case GDK_WINDOW_EDGE_WEST:
4576 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4579 case GDK_WINDOW_EDGE_EAST:
4580 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4583 case GDK_WINDOW_EDGE_SOUTH_WEST:
4584 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4587 case GDK_WINDOW_EDGE_SOUTH:
4588 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4591 case GDK_WINDOW_EDGE_SOUTH_EAST:
4592 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4596 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4601 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4604 typedef struct _MoveResizeData MoveResizeData;
4606 struct _MoveResizeData
4608 GdkDisplay *display;
4610 GdkWindow *moveresize_window;
4611 GdkWindow *moveresize_emulation_window;
4613 GdkWindowEdge resize_edge;
4615 gint moveresize_button;
4618 gint moveresize_orig_x;
4619 gint moveresize_orig_y;
4620 gint moveresize_orig_width;
4621 gint moveresize_orig_height;
4622 GdkWindowHints moveresize_geom_mask;
4623 GdkGeometry moveresize_geometry;
4624 Time moveresize_process_time;
4625 XEvent *moveresize_pending_event;
4628 static MoveResizeData *
4629 get_move_resize_data (GdkDisplay *display,
4632 MoveResizeData *mv_resize;
4633 static GQuark move_resize_quark = 0;
4635 if (!move_resize_quark)
4636 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4638 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4640 if (!mv_resize && create)
4642 mv_resize = g_new0 (MoveResizeData, 1);
4643 mv_resize->display = display;
4645 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4652 update_pos (MoveResizeData *mv_resize,
4658 dx = new_root_x - mv_resize->moveresize_x;
4659 dy = new_root_y - mv_resize->moveresize_y;
4661 if (mv_resize->is_resize)
4665 x = mv_resize->moveresize_orig_x;
4666 y = mv_resize->moveresize_orig_y;
4668 w = mv_resize->moveresize_orig_width;
4669 h = mv_resize->moveresize_orig_height;
4671 switch (mv_resize->resize_edge)
4673 case GDK_WINDOW_EDGE_NORTH_WEST:
4679 case GDK_WINDOW_EDGE_NORTH:
4683 case GDK_WINDOW_EDGE_NORTH_EAST:
4688 case GDK_WINDOW_EDGE_SOUTH_WEST:
4693 case GDK_WINDOW_EDGE_SOUTH_EAST:
4697 case GDK_WINDOW_EDGE_SOUTH:
4700 case GDK_WINDOW_EDGE_EAST:
4703 case GDK_WINDOW_EDGE_WEST:
4714 if (mv_resize->moveresize_geom_mask)
4716 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4717 mv_resize->moveresize_geom_mask,
4721 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4727 x = mv_resize->moveresize_orig_x + dx;
4728 y = mv_resize->moveresize_orig_y + dy;
4730 gdk_window_move (mv_resize->moveresize_window, x, y);
4735 finish_drag (MoveResizeData *mv_resize)
4737 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4738 mv_resize->moveresize_emulation_window = NULL;
4739 g_object_unref (mv_resize->moveresize_window);
4740 mv_resize->moveresize_window = NULL;
4742 if (mv_resize->moveresize_pending_event)
4744 g_free (mv_resize->moveresize_pending_event);
4745 mv_resize->moveresize_pending_event = NULL;
4750 lookahead_motion_predicate (Display *xdisplay,
4754 gboolean *seen_release = (gboolean *)arg;
4755 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4756 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4761 switch (event->xany.type)
4764 *seen_release = TRUE;
4767 mv_resize->moveresize_process_time = event->xmotion.time;
4777 moveresize_lookahead (MoveResizeData *mv_resize,
4781 gboolean seen_release = FALSE;
4783 if (mv_resize->moveresize_process_time)
4785 if (event->xmotion.time == mv_resize->moveresize_process_time)
4787 mv_resize->moveresize_process_time = 0;
4794 XCheckIfEvent (event->xany.display, &tmp_event,
4795 lookahead_motion_predicate, (XPointer) & seen_release);
4797 return mv_resize->moveresize_process_time == 0;
4801 _gdk_x11_moveresize_handle_event (XEvent *event)
4803 guint button_mask = 0;
4804 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4805 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4807 if (!mv_resize || !mv_resize->moveresize_window)
4809 handle_wmspec_button_release (display, event);
4813 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4815 switch (event->xany.type)
4818 if (mv_resize->moveresize_window->resize_count > 0)
4820 if (mv_resize->moveresize_pending_event)
4821 *mv_resize->moveresize_pending_event = *event;
4823 mv_resize->moveresize_pending_event =
4824 g_memdup (event, sizeof (XEvent));
4828 if (!moveresize_lookahead (mv_resize, event))
4831 update_pos (mv_resize,
4832 event->xmotion.x_root,
4833 event->xmotion.y_root);
4835 /* This should never be triggered in normal cases, but in the
4836 * case where the drag started without an implicit grab being
4837 * in effect, we could miss the release if it occurs before
4838 * we grab the pointer; this ensures that we will never
4839 * get a permanently stuck grab.
4841 if ((event->xmotion.state & button_mask) == 0)
4842 finish_drag (mv_resize);
4846 update_pos (mv_resize,
4847 event->xbutton.x_root,
4848 event->xbutton.y_root);
4850 if (event->xbutton.button == mv_resize->moveresize_button)
4851 finish_drag (mv_resize);
4854 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4857 /* we just assume this is an XI2 event */
4858 XIEvent *ev = (XIEvent *) event->xcookie.data;
4859 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4864 update_pos (mv_resize, xev->root_x, xev->root_y);
4865 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4866 if ((state & button_mask) == 0)
4867 finish_drag (mv_resize);
4870 case XI_ButtonRelease:
4871 update_pos (mv_resize, xev->root_x, xev->root_y);
4872 if (xev->detail == mv_resize->moveresize_button)
4873 finish_drag (mv_resize);
4885 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4889 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4891 if (!mv_resize || window != mv_resize->moveresize_window)
4894 if (mv_resize->moveresize_pending_event)
4896 tmp_event = mv_resize->moveresize_pending_event;
4897 mv_resize->moveresize_pending_event = NULL;
4898 _gdk_x11_moveresize_handle_event (tmp_event);
4906 create_moveresize_window (MoveResizeData *mv_resize,
4909 GdkWindowAttr attributes;
4910 gint attributes_mask;
4911 GdkGrabStatus status;
4913 g_assert (mv_resize->moveresize_emulation_window == NULL);
4915 attributes.x = -100;
4916 attributes.y = -100;
4917 attributes.width = 10;
4918 attributes.height = 10;
4919 attributes.window_type = GDK_WINDOW_TEMP;
4920 attributes.wclass = GDK_INPUT_ONLY;
4921 attributes.override_redirect = TRUE;
4922 attributes.event_mask = 0;
4924 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4926 mv_resize->moveresize_emulation_window =
4927 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4931 gdk_window_show (mv_resize->moveresize_emulation_window);
4933 status = gdk_device_grab (mv_resize->device,
4934 mv_resize->moveresize_emulation_window,
4937 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4941 if (status != GDK_GRAB_SUCCESS)
4943 /* If this fails, some other client has grabbed the window
4946 finish_drag (mv_resize);
4949 mv_resize->moveresize_process_time = 0;
4953 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4954 so that calling XMoveWindow with these coordinates will not move the
4956 Note that this depends on the WM to implement ICCCM-compliant reference
4960 calculate_unmoving_origin (MoveResizeData *mv_resize)
4965 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4966 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4968 gdk_window_get_origin (mv_resize->moveresize_window,
4969 &mv_resize->moveresize_orig_x,
4970 &mv_resize->moveresize_orig_y);
4974 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4975 gdk_window_get_geometry (mv_resize->moveresize_window,
4976 NULL, NULL, &width, &height);
4978 switch (mv_resize->moveresize_geometry.win_gravity)
4980 case GDK_GRAVITY_NORTH_WEST:
4981 mv_resize->moveresize_orig_x = rect.x;
4982 mv_resize->moveresize_orig_y = rect.y;
4984 case GDK_GRAVITY_NORTH:
4985 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4986 mv_resize->moveresize_orig_y = rect.y;
4988 case GDK_GRAVITY_NORTH_EAST:
4989 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4990 mv_resize->moveresize_orig_y = rect.y;
4992 case GDK_GRAVITY_WEST:
4993 mv_resize->moveresize_orig_x = rect.x;
4994 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4996 case GDK_GRAVITY_CENTER:
4997 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4998 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5000 case GDK_GRAVITY_EAST:
5001 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5002 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
5004 case GDK_GRAVITY_SOUTH_WEST:
5005 mv_resize->moveresize_orig_x = rect.x;
5006 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5008 case GDK_GRAVITY_SOUTH:
5009 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
5010 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5012 case GDK_GRAVITY_SOUTH_EAST:
5013 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
5014 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
5017 mv_resize->moveresize_orig_x = rect.x;
5018 mv_resize->moveresize_orig_y = rect.y;
5025 emulate_resize_drag (GdkWindow *window,
5033 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5035 mv_resize->is_resize = TRUE;
5036 mv_resize->moveresize_button = button;
5037 mv_resize->resize_edge = edge;
5038 mv_resize->device = device;
5039 mv_resize->moveresize_x = root_x;
5040 mv_resize->moveresize_y = root_y;
5041 mv_resize->moveresize_window = g_object_ref (window);
5043 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
5044 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
5046 mv_resize->moveresize_geom_mask = 0;
5047 gdk_window_get_geometry_hints (window,
5048 &mv_resize->moveresize_geometry,
5049 &mv_resize->moveresize_geom_mask);
5051 calculate_unmoving_origin (mv_resize);
5053 create_moveresize_window (mv_resize, timestamp);
5057 emulate_move_drag (GdkWindow *window,
5064 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
5066 mv_resize->is_resize = FALSE;
5067 mv_resize->device = device;
5068 mv_resize->moveresize_button = button;
5069 mv_resize->moveresize_x = root_x;
5070 mv_resize->moveresize_y = root_y;
5072 mv_resize->moveresize_window = g_object_ref (window);
5074 calculate_unmoving_origin (mv_resize);
5076 create_moveresize_window (mv_resize, timestamp);
5080 gdk_x11_window_begin_resize_drag (GdkWindow *window,
5088 if (GDK_WINDOW_DESTROYED (window) ||
5089 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
5092 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5093 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5094 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5096 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
5100 gdk_x11_window_begin_move_drag (GdkWindow *window,
5107 if (GDK_WINDOW_DESTROYED (window) ||
5108 !WINDOW_IS_TOPLEVEL (window))
5111 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5112 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5113 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5114 device, button, root_x, root_y, timestamp);
5116 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5120 gdk_x11_window_beep (GdkWindow *window)
5122 GdkDisplay *display;
5124 display = GDK_WINDOW_DISPLAY (window);
5127 if (GDK_X11_DISPLAY (display)->use_xkb)
5129 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5130 GDK_WINDOW_XID (window),
5141 gdk_x11_window_set_opacity (GdkWindow *window,
5144 GdkDisplay *display;
5147 g_return_if_fail (GDK_IS_WINDOW (window));
5149 if (GDK_WINDOW_DESTROYED (window) ||
5150 !WINDOW_IS_TOPLEVEL (window))
5153 display = gdk_window_get_display (window);
5157 else if (opacity > 1)
5160 cardinal = opacity * 0xffffffff;
5162 if (cardinal == 0xffffffff)
5163 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5164 GDK_WINDOW_XID (window),
5165 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5167 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5168 GDK_WINDOW_XID (window),
5169 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5172 (guchar *) &cardinal, 1);
5176 gdk_x11_window_set_composited (GdkWindow *window,
5177 gboolean composited)
5179 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5180 GdkWindowImplX11 *impl;
5181 GdkDisplay *display;
5185 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5187 display = gdk_window_get_display (window);
5188 dpy = GDK_DISPLAY_XDISPLAY (display);
5189 xid = GDK_WINDOW_XID (window);
5193 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5194 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5198 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5199 XDamageDestroy (dpy, impl->damage);
5200 impl->damage = None;
5206 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5207 cairo_region_t *region)
5209 _gdk_window_process_updates_recurse (window, region);
5213 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5218 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5220 /* Sync after all drawing, otherwise the client can get "ahead" of
5221 the server rendering during animations, such that we fill up
5222 the Xserver pipes with sync rendering ops not letting other
5223 clients (including the VM) do anything. */
5224 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5228 timestamp_predicate (Display *display,
5232 Window xwindow = GPOINTER_TO_UINT (arg);
5233 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5235 if (xevent->type == PropertyNotify &&
5236 xevent->xproperty.window == xwindow &&
5237 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5238 "GDK_TIMESTAMP_PROP"))
5245 * gdk_x11_get_server_time:
5246 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5247 * with the server. The window must have
5248 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5251 * Routine to get the current X server time stamp.
5253 * Return value: the time stamp.
5256 gdk_x11_get_server_time (GdkWindow *window)
5262 Atom timestamp_prop_atom;
5264 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5265 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5267 xdisplay = GDK_WINDOW_XDISPLAY (window);
5268 xwindow = GDK_WINDOW_XID (window);
5269 timestamp_prop_atom =
5270 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5271 "GDK_TIMESTAMP_PROP");
5273 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5274 timestamp_prop_atom,
5275 8, PropModeReplace, &c, 1);
5277 XIfEvent (xdisplay, &xevent,
5278 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5280 return xevent.xproperty.time;
5284 * gdk_x11_window_get_xid:
5285 * @window: (type GdkX11Window): a native #GdkWindow.
5287 * Returns the X resource (window) belonging to a #GdkWindow.
5289 * Return value: the ID of @drawable's X resource.
5292 gdk_x11_window_get_xid (GdkWindow *window)
5294 /* Try to ensure the window has a native window */
5295 if (!_gdk_window_has_impl (window))
5297 gdk_window_ensure_native (window);
5299 /* We sync here to ensure the window is created in the Xserver when
5300 * this function returns. This is required because the returned XID
5301 * for this window must be valid immediately, even with another
5302 * connection to the Xserver */
5303 gdk_display_sync (gdk_window_get_display (window));
5306 if (!GDK_WINDOW_IS_X11 (window))
5308 g_warning (G_STRLOC " drawable is not a native X11 window");
5312 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5316 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5318 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5319 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5321 object_class->finalize = gdk_window_impl_x11_finalize;
5323 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5324 impl_class->show = gdk_window_x11_show;
5325 impl_class->hide = gdk_window_x11_hide;
5326 impl_class->withdraw = gdk_window_x11_withdraw;
5327 impl_class->set_events = gdk_window_x11_set_events;
5328 impl_class->get_events = gdk_window_x11_get_events;
5329 impl_class->raise = gdk_window_x11_raise;
5330 impl_class->lower = gdk_window_x11_lower;
5331 impl_class->restack_under = gdk_window_x11_restack_under;
5332 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5333 impl_class->move_resize = gdk_window_x11_move_resize;
5334 impl_class->set_background = gdk_window_x11_set_background;
5335 impl_class->reparent = gdk_window_x11_reparent;
5336 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5337 impl_class->get_geometry = gdk_window_x11_get_geometry;
5338 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5339 impl_class->get_device_state = gdk_window_x11_get_device_state;
5340 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5341 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5342 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5343 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5344 impl_class->translate = _gdk_x11_window_translate;
5345 impl_class->destroy = gdk_x11_window_destroy;
5346 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5347 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5348 impl_class->get_shape = gdk_x11_window_get_shape;
5349 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5350 impl_class->beep = gdk_x11_window_beep;
5352 impl_class->focus = gdk_x11_window_focus;
5353 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5354 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5355 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5356 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5357 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5358 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5359 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5360 impl_class->set_title = gdk_x11_window_set_title;
5361 impl_class->set_role = gdk_x11_window_set_role;
5362 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5363 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5364 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5365 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5366 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5367 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5368 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5369 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5370 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5371 impl_class->iconify = gdk_x11_window_iconify;
5372 impl_class->deiconify = gdk_x11_window_deiconify;
5373 impl_class->stick = gdk_x11_window_stick;
5374 impl_class->unstick = gdk_x11_window_unstick;
5375 impl_class->maximize = gdk_x11_window_maximize;
5376 impl_class->unmaximize = gdk_x11_window_unmaximize;
5377 impl_class->fullscreen = gdk_x11_window_fullscreen;
5378 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5379 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5380 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5381 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5382 impl_class->get_group = gdk_x11_window_get_group;
5383 impl_class->set_group = gdk_x11_window_set_group;
5384 impl_class->set_decorations = gdk_x11_window_set_decorations;
5385 impl_class->get_decorations = gdk_x11_window_get_decorations;
5386 impl_class->set_functions = gdk_x11_window_set_functions;
5387 impl_class->set_functions = gdk_x11_window_set_functions;
5388 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5389 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5390 impl_class->set_opacity = gdk_x11_window_set_opacity;
5391 impl_class->set_composited = gdk_x11_window_set_composited;
5392 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5393 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5394 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5395 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5396 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5397 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5398 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5399 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5400 impl_class->get_property = _gdk_x11_window_get_property;
5401 impl_class->change_property = _gdk_x11_window_change_property;
5402 impl_class->delete_property = _gdk_x11_window_delete_property;