1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
21 * file for a list of people on the GTK+ Team. See the ChangeLog
22 * files for a list of changes. These files are distributed with
23 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
28 #include "gdkwindow-x11.h"
30 #include "gdkwindow.h"
31 #include "gdkwindowimpl.h"
32 #include "gdkvisualprivate.h"
33 #include "gdkinternals.h"
34 #include "gdkdeviceprivate.h"
36 #include "gdkeventsource.h"
37 #include "gdkdisplay-x11.h"
38 #include "gdkframeclockidle.h"
39 #include "gdkprivate-x11.h"
44 #include <netinet/in.h>
47 #include <cairo-xlib.h>
52 #include <X11/Xutil.h>
53 #include <X11/Xatom.h>
55 #include <X11/extensions/shape.h>
58 #include <X11/XKBlib.h>
61 #ifdef HAVE_XCOMPOSITE
62 #include <X11/extensions/Xcomposite.h>
66 #include <X11/extensions/Xfixes.h>
70 #include <X11/extensions/Xdamage.h>
73 const int _gdk_x11_event_mask_table[21] =
77 PointerMotionHintMask,
94 SubstructureNotifyMask,
95 ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
98 const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
100 /* Forward declarations */
101 static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
102 static void gdk_window_set_static_win_gravity (GdkWindow *window,
104 static gboolean gdk_window_icon_name_set (GdkWindow *window);
105 static void set_wm_name (GdkDisplay *display,
108 static void move_to_current_desktop (GdkWindow *window);
109 static void gdk_window_x11_set_background (GdkWindow *window,
110 cairo_pattern_t *pattern);
112 static void gdk_window_impl_x11_finalize (GObject *object);
114 #define WINDOW_IS_TOPLEVEL_OR_FOREIGN(window) \
115 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
116 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
118 #define WINDOW_IS_TOPLEVEL(window) \
119 (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
120 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
121 GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
123 /* Return whether time1 is considered later than time2 as far as xserver
124 * time is concerned. Accounts for wraparound.
126 #define XSERVER_TIME_IS_LATER(time1, time2) \
127 ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
128 (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
131 struct _GdkX11Window {
135 struct _GdkX11WindowClass {
136 GdkWindowClass parent_class;
139 G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
142 gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
147 gdk_x11_window_init (GdkX11Window *x11_window)
152 G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
155 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
157 impl->toplevel_window_type = -1;
158 impl->device_cursor = g_hash_table_new_full (NULL, NULL,
159 NULL, g_object_unref);
163 _gdk_x11_window_get_toplevel (GdkWindow *window)
165 GdkWindowImplX11 *impl;
167 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
169 if (!WINDOW_IS_TOPLEVEL (window))
172 impl = GDK_WINDOW_IMPL_X11 (window->impl);
176 impl->toplevel = g_new0 (GdkToplevelX11, 1);
177 impl->toplevel->have_focused = TRUE;
180 return impl->toplevel;
183 static const cairo_user_data_key_t gdk_x11_cairo_key;
186 * _gdk_x11_window_update_size:
187 * @impl: a #GdkWindowImplX11.
189 * Updates the state of the window (in particular the drawable's
190 * cairo surface) when its size has changed.
193 _gdk_x11_window_update_size (GdkWindowImplX11 *impl)
195 if (impl->cairo_surface)
197 cairo_xlib_surface_set_size (impl->cairo_surface,
198 gdk_window_get_width (impl->wrapper),
199 gdk_window_get_height (impl->wrapper));
204 set_sync_counter(Display *display,
205 XSyncCounter counter,
208 XSyncValue sync_value;
210 XSyncIntsToValue(&sync_value,
211 value & G_GINT64_CONSTANT(0xFFFFFFFF),
213 XSyncSetCounter(display, counter, sync_value);
217 window_pre_damage (GdkWindow *window)
219 GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
220 GdkWindowImplX11 *impl;
222 if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
225 impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
227 if (impl->toplevel->in_frame &&
228 impl->toplevel->current_counter_value % 2 == 0)
230 impl->toplevel->current_counter_value += 1;
231 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
232 impl->toplevel->extended_update_counter,
233 impl->toplevel->current_counter_value);
238 on_surface_changed (void *data)
240 GdkWindow *window = data;
242 window_pre_damage (window);
245 /* We want to know when cairo drawing causes damage to the window,
246 * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
247 * window only when there actually is drawing. To do that we use
248 * a technique (hack) suggested by Uli Schlachter - if we set
249 * a dummy "mime data" on the cairo surface (this facility is
250 * used to attach JPEG data to an imager), then cairo wil flush
251 * and remove the mime data before making any changes to the window.
255 hook_surface_changed (GdkWindow *window)
257 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
259 if (impl->cairo_surface)
260 cairo_surface_set_mime_data (impl->cairo_surface,
261 "x-gdk/change-notify",
262 (unsigned char *)"X",
269 unhook_surface_changed (GdkWindow *window)
271 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
273 if (impl->cairo_surface)
274 cairo_surface_set_mime_data (impl->cairo_surface,
275 "x-gdk/change-notify",
281 gdk_x11_window_begin_frame (GdkWindow *window)
283 GdkWindowImplX11 *impl;
285 g_return_if_fail (GDK_IS_WINDOW (window));
287 impl = GDK_WINDOW_IMPL_X11 (window->impl);
289 if (!WINDOW_IS_TOPLEVEL (window) ||
290 impl->toplevel->extended_update_counter == None)
293 impl->toplevel->in_frame = TRUE;
295 hook_surface_changed (window);
299 gdk_x11_window_end_frame (GdkWindow *window)
301 GdkFrameClock *clock;
302 GdkFrameHistory *history;
303 gint64 frame_counter;
304 GdkFrameTimings *timings;
305 GdkWindowImplX11 *impl;
307 g_return_if_fail (GDK_IS_WINDOW (window));
309 impl = GDK_WINDOW_IMPL_X11 (window->impl);
311 if (!WINDOW_IS_TOPLEVEL (window) ||
312 impl->toplevel->extended_update_counter == None ||
313 !impl->toplevel->in_frame)
316 clock = gdk_window_get_frame_clock (window);
317 history = gdk_frame_clock_get_history (clock);
318 frame_counter = gdk_frame_history_get_frame_counter (history);
319 timings = gdk_frame_history_get_timings (history, frame_counter);
321 impl->toplevel->in_frame = FALSE;
323 if (impl->toplevel->current_counter_value % 2 == 1)
325 /* An increment of 3 means that the frame was not drawn as fast as possible,
326 * but rather at a particular time. This can trigger different handling from
329 if (gdk_frame_timings_get_slept_before (timings))
330 impl->toplevel->current_counter_value += 3;
332 impl->toplevel->current_counter_value += 1;
334 set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
335 impl->toplevel->extended_update_counter,
336 impl->toplevel->current_counter_value);
338 if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
339 gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
341 impl->toplevel->frame_pending = TRUE;
342 gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
343 gdk_frame_timings_set_cookie (timings,
344 impl->toplevel->current_counter_value);
348 unhook_surface_changed (window);
350 if (!impl->toplevel->frame_pending)
351 gdk_frame_timings_set_complete (timings, TRUE);
354 /*****************************************************
355 * X11 specific implementations of generic functions *
356 *****************************************************/
359 gdk_x11_cairo_surface_destroy (void *data)
361 GdkWindowImplX11 *impl = data;
363 impl->cairo_surface = NULL;
366 static cairo_surface_t *
367 gdk_x11_create_cairo_surface (GdkWindowImplX11 *impl,
373 visual = gdk_window_get_visual (impl->wrapper);
374 return cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (impl->wrapper),
375 GDK_WINDOW_IMPL_X11 (impl)->xid,
376 GDK_VISUAL_XVISUAL (visual),
380 static cairo_surface_t *
381 gdk_x11_ref_cairo_surface (GdkWindow *window)
383 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
385 if (GDK_WINDOW_DESTROYED (window))
388 if (!impl->cairo_surface)
390 impl->cairo_surface = gdk_x11_create_cairo_surface (impl,
391 gdk_window_get_width (window),
392 gdk_window_get_height (window));
394 if (impl->cairo_surface)
395 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
396 impl, gdk_x11_cairo_surface_destroy);
398 if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
399 hook_surface_changed (window);
402 cairo_surface_reference (impl->cairo_surface);
404 return impl->cairo_surface;
408 gdk_window_impl_x11_finalize (GObject *object)
411 GdkWindowImplX11 *impl;
413 g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
415 impl = GDK_WINDOW_IMPL_X11 (object);
417 wrapper = impl->wrapper;
419 if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
420 unhook_surface_changed (wrapper);
422 _gdk_x11_window_grab_check_destroy (wrapper);
424 if (!GDK_WINDOW_DESTROYED (wrapper))
426 GdkDisplay *display = GDK_WINDOW_DISPLAY (wrapper);
428 _gdk_x11_display_remove_window (display, impl->xid);
429 if (impl->toplevel && impl->toplevel->focus_window)
430 _gdk_x11_display_remove_window (display, impl->toplevel->focus_window);
433 g_free (impl->toplevel);
436 g_object_unref (impl->cursor);
438 g_hash_table_destroy (impl->device_cursor);
440 G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
449 free_pixmap (gpointer datap)
451 FreePixmapData *data = datap;
453 if (!gdk_display_is_closed (data->display))
455 XFreePixmap (GDK_DISPLAY_XDISPLAY (data->display),
459 g_object_unref (data->display);
460 g_slice_free (FreePixmapData, data);
464 attach_free_pixmap_handler (cairo_surface_t *surface,
468 static const cairo_user_data_key_t key;
469 FreePixmapData *data;
471 data = g_slice_new (FreePixmapData);
472 data->display = g_object_ref (display);
473 data->pixmap = pixmap;
475 cairo_surface_set_user_data (surface, &key, data, free_pixmap);
478 /* Cairo does not guarantee we get an xlib surface if we call
479 * cairo_surface_create_similar(). In some cases however, we must use a
480 * pixmap or bitmap in the X11 API.
481 * These functions ensure an Xlib surface.
484 _gdk_x11_window_create_bitmap_surface (GdkWindow *window,
488 cairo_surface_t *surface;
491 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
492 GDK_WINDOW_XID (window),
494 surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
496 GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
498 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
503 /* Create a surface backed with a pixmap without alpha on the same screen as window */
504 static cairo_surface_t *
505 gdk_x11_window_create_pixmap_surface (GdkWindow *window,
509 GdkScreen *screen = gdk_window_get_screen (window);
510 GdkVisual *visual = gdk_screen_get_system_visual (screen);
511 cairo_surface_t *surface;
514 pixmap = XCreatePixmap (GDK_WINDOW_XDISPLAY (window),
515 GDK_WINDOW_XID (window),
517 gdk_visual_get_depth (visual));
518 surface = cairo_xlib_surface_create (GDK_WINDOW_XDISPLAY (window),
520 GDK_VISUAL_XVISUAL (visual),
522 attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
528 tmp_unset_bg (GdkWindow *window)
530 GdkWindowImplX11 *impl;
532 impl = GDK_WINDOW_IMPL_X11 (window->impl);
536 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
537 GDK_WINDOW_XID (window), None);
541 tmp_reset_bg (GdkWindow *window)
543 GdkWindowImplX11 *impl;
545 impl = GDK_WINDOW_IMPL_X11 (window->impl);
549 gdk_window_x11_set_background (window, window->background);
552 /* Unsetting and resetting window backgrounds.
554 * In many cases it is possible to avoid flicker by unsetting the
555 * background of windows. For example if the background of the
556 * parent window is unset when a window is unmapped, a brief flicker
557 * of background painting is avoided.
560 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
563 g_return_if_fail (GDK_IS_WINDOW (window));
565 if (window->input_only || window->destroyed ||
566 (window->window_type != GDK_WINDOW_ROOT &&
567 !GDK_WINDOW_IS_MAPPED (window)))
570 if (_gdk_window_has_impl (window) &&
571 GDK_WINDOW_IS_X11 (window) &&
572 window->window_type != GDK_WINDOW_ROOT &&
573 window->window_type != GDK_WINDOW_FOREIGN)
574 tmp_unset_bg (window);
580 for (l = window->children; l != NULL; l = l->next)
581 _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
586 _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
588 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
591 window = _gdk_window_get_impl_window (window->parent);
592 _gdk_x11_window_tmp_unset_bg (window, FALSE);
596 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
599 g_return_if_fail (GDK_IS_WINDOW (window));
601 if (window->input_only || window->destroyed ||
602 (window->window_type != GDK_WINDOW_ROOT &&
603 !GDK_WINDOW_IS_MAPPED (window)))
607 if (_gdk_window_has_impl (window) &&
608 GDK_WINDOW_IS_X11 (window) &&
609 window->window_type != GDK_WINDOW_ROOT &&
610 window->window_type != GDK_WINDOW_FOREIGN)
611 tmp_reset_bg (window);
617 for (l = window->children; l != NULL; l = l->next)
618 _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
623 _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
625 if (GDK_WINDOW_TYPE (window->parent) == GDK_WINDOW_ROOT)
628 window = _gdk_window_get_impl_window (window->parent);
630 _gdk_x11_window_tmp_reset_bg (window, FALSE);
634 _gdk_x11_screen_init_root_window (GdkScreen *screen)
637 GdkWindowImplX11 *impl;
638 GdkX11Screen *x11_screen;
640 x11_screen = GDK_X11_SCREEN (screen);
642 g_assert (x11_screen->root_window == NULL);
644 window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
646 window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
647 window->impl_window = window;
648 window->visual = gdk_screen_get_system_visual (screen);
650 impl = GDK_WINDOW_IMPL_X11 (window->impl);
652 impl->xid = x11_screen->xroot_window;
653 impl->wrapper = window;
655 window->window_type = GDK_WINDOW_ROOT;
656 window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
662 window->width = WidthOfScreen (x11_screen->xscreen);
663 window->height = HeightOfScreen (x11_screen->xscreen);
664 window->viewable = TRUE;
666 /* see init_randr_support() in gdkscreen-x11.c */
667 window->event_mask = GDK_STRUCTURE_MASK;
669 _gdk_window_update_size (x11_screen->root_window);
671 _gdk_x11_display_add_window (x11_screen->display,
672 &x11_screen->xroot_window,
673 x11_screen->root_window);
677 set_wm_protocols (GdkWindow *window)
679 GdkDisplay *display = gdk_window_get_display (window);
683 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
684 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
685 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
688 if (GDK_X11_DISPLAY (display)->use_sync)
689 protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
692 XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
696 get_default_title (void)
700 title = g_get_application_name ();
702 title = g_get_prgname ();
710 check_leader_window_title (GdkDisplay *display)
712 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
714 if (display_x11->leader_window && !display_x11->leader_window_title_set)
716 set_wm_name (display,
717 display_x11->leader_window,
718 get_default_title ());
720 display_x11->leader_window_title_set = TRUE;
725 create_focus_window (GdkDisplay *display,
728 GdkX11Display *display_x11;
729 GdkEventMask event_mask;
733 xdisplay = GDK_DISPLAY_XDISPLAY (display);
734 display_x11 = GDK_X11_DISPLAY (display);
736 focus_window = XCreateSimpleWindow (xdisplay, parent,
740 /* FIXME: probably better to actually track the requested event mask for the toplevel
742 event_mask = (GDK_KEY_PRESS_MASK |
743 GDK_KEY_RELEASE_MASK |
744 GDK_FOCUS_CHANGE_MASK);
746 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
750 XMapWindow (xdisplay, focus_window);
756 ensure_sync_counter (GdkWindow *window)
759 if (!GDK_WINDOW_DESTROYED (window))
761 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
762 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
765 toplevel->update_counter == None &&
766 GDK_X11_DISPLAY (display)->use_sync)
768 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
773 XSyncIntToValue (&value, 0);
775 toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
776 toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
778 atom = gdk_x11_get_xatom_by_name_for_display (display,
779 "_NET_WM_SYNC_REQUEST_COUNTER");
781 counters[0] = toplevel->update_counter;
782 counters[1] = toplevel->extended_update_counter;
783 XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
786 (guchar *)counters, 2);
788 toplevel->current_counter_value = 0;
795 setup_toplevel_window (GdkWindow *window,
798 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
799 GdkDisplay *display = gdk_window_get_display (window);
800 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
801 XID xid = GDK_WINDOW_XID (window);
802 GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
803 XSizeHints size_hints;
805 Window leader_window;
807 set_wm_protocols (window);
809 if (!window->input_only)
811 /* The focus window is off the visible area, and serves to receive key
812 * press events so they don't get sent to child windows.
814 toplevel->focus_window = create_focus_window (display, xid);
815 _gdk_x11_display_add_window (x11_screen->display,
816 &toplevel->focus_window,
820 check_leader_window_title (x11_screen->display);
822 /* FIXME: Is there any point in doing this? Do any WM's pay
823 * attention to PSize, and even if they do, is this the
826 size_hints.flags = PSize;
827 size_hints.width = window->width;
828 size_hints.height = window->height;
830 XSetWMNormalHints (xdisplay, xid, &size_hints);
832 /* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
833 XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
836 XChangeProperty (xdisplay, xid,
837 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
842 leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
845 XChangeProperty (xdisplay, xid,
846 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
847 XA_WINDOW, 32, PropModeReplace,
848 (guchar *) &leader_window, 1);
850 if (toplevel->focus_window != None)
851 XChangeProperty (xdisplay, xid,
852 gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
853 XA_WINDOW, 32, PropModeReplace,
854 (guchar *) &toplevel->focus_window, 1);
856 if (!window->focus_on_map)
857 gdk_x11_window_set_user_time (window, 0);
858 else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
859 gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
861 ensure_sync_counter (window);
863 /* Start off in a frozen state - we'll finish this when we first paint */
864 gdk_x11_window_begin_frame (window);
868 on_frame_clock_before_paint (GdkFrameClock *clock,
871 gdk_x11_window_begin_frame (window);
875 on_frame_clock_after_paint (GdkFrameClock *clock,
878 gdk_x11_window_end_frame (window);
883 _gdk_x11_display_create_window_impl (GdkDisplay *display,
885 GdkWindow *real_parent,
887 GdkEventMask event_mask,
888 GdkWindowAttr *attributes,
889 gint attributes_mask)
891 GdkWindowImplX11 *impl;
892 GdkX11Screen *x11_screen;
893 GdkX11Display *display_x11;
894 GdkFrameClock *clock;
900 XSetWindowAttributes xattributes;
901 long xattributes_mask;
902 XClassHint *class_hint;
907 display_x11 = GDK_X11_DISPLAY (display);
908 xparent = GDK_WINDOW_XID (real_parent);
909 x11_screen = GDK_X11_SCREEN (screen);
911 impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
912 window->impl = GDK_WINDOW_IMPL (impl);
913 impl->wrapper = GDK_WINDOW (window);
915 xdisplay = x11_screen->xdisplay;
917 xattributes_mask = 0;
919 xvisual = gdk_x11_visual_get_xvisual (window->visual);
921 if (attributes_mask & GDK_WA_NOREDIR)
923 xattributes.override_redirect =
924 (attributes->override_redirect == FALSE)?False:True;
925 xattributes_mask |= CWOverrideRedirect;
928 xattributes.override_redirect = False;
930 impl->override_redirect = xattributes.override_redirect;
932 if (window->parent && window->parent->guffaw_gravity)
934 xattributes.win_gravity = StaticGravity;
935 xattributes_mask |= CWWinGravity;
939 switch (window->window_type)
941 case GDK_WINDOW_TOPLEVEL:
942 case GDK_WINDOW_TEMP:
943 if (GDK_WINDOW_TYPE (window->parent) != GDK_WINDOW_ROOT)
945 /* The common code warns for this case */
946 xparent = GDK_SCREEN_XROOTWIN (screen);
950 if (!window->input_only)
954 xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
956 xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
957 xattributes_mask |= CWBorderPixel | CWBackPixel;
959 if (window->guffaw_gravity)
960 xattributes.bit_gravity = StaticGravity;
962 xattributes.bit_gravity = NorthWestGravity;
964 xattributes_mask |= CWBitGravity;
966 xattributes.colormap = _gdk_visual_get_x11_colormap (window->visual);
967 xattributes_mask |= CWColormap;
969 if (window->window_type == GDK_WINDOW_TEMP)
971 xattributes.save_under = True;
972 xattributes.override_redirect = True;
973 xattributes.cursor = None;
974 xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
976 impl->override_redirect = TRUE;
984 if (window->width > 65535 ||
985 window->height > 65535)
987 g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
989 if (window->width > 65535)
990 window->width = 65535;
991 if (window->height > 65535)
992 window->height = 65535;
995 impl->xid = XCreateWindow (xdisplay, xparent,
996 window->x + window->parent->abs_x,
997 window->y + window->parent->abs_y,
998 window->width, window->height,
999 0, window->depth, class, xvisual,
1000 xattributes_mask, &xattributes);
1002 g_object_ref (window);
1003 _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
1005 switch (GDK_WINDOW_TYPE (window))
1007 case GDK_WINDOW_TOPLEVEL:
1008 case GDK_WINDOW_TEMP:
1009 if (attributes_mask & GDK_WA_TITLE)
1010 title = attributes->title;
1012 title = get_default_title ();
1014 gdk_window_set_title (window, title);
1016 if (attributes_mask & GDK_WA_WMCLASS)
1018 class_hint = XAllocClassHint ();
1019 class_hint->res_name = attributes->wmclass_name;
1020 class_hint->res_class = attributes->wmclass_class;
1021 XSetClassHint (xdisplay, impl->xid, class_hint);
1025 setup_toplevel_window (window, window->parent);
1028 case GDK_WINDOW_CHILD:
1033 if (attributes_mask & GDK_WA_TYPE_HINT)
1034 gdk_window_set_type_hint (window, attributes->type_hint);
1036 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
1037 GDK_WINDOW_XID (window), event_mask,
1038 StructureNotifyMask | PropertyChangeMask);
1040 clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
1041 gdk_window_set_frame_clock (window, clock);
1042 g_signal_connect (clock, "before-paint",
1043 G_CALLBACK (on_frame_clock_before_paint), window);
1044 g_signal_connect (clock, "after-paint",
1045 G_CALLBACK (on_frame_clock_after_paint), window);
1047 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
1048 gdk_window_freeze_toplevel_updates_libgtk_only (window);
1052 x_event_mask_to_gdk_event_mask (long mask)
1054 GdkEventMask event_mask = 0;
1057 for (i = 0; i < _gdk_x11_event_mask_table_size; i++)
1059 if (mask & _gdk_x11_event_mask_table[i])
1060 event_mask |= 1 << (i + 1);
1067 * gdk_x11_window_foreign_new_for_display:
1068 * @display: the #GdkDisplay where the window handle comes from.
1069 * @window: an XLib <type>Window</type>
1071 * Wraps a native window in a #GdkWindow. The function will try to
1072 * look up the window using gdk_x11_window_lookup_for_display() first.
1073 * If it does not find it there, it will create a new window.
1075 * This may fail if the window has been destroyed. If the window
1076 * was already known to GDK, a new reference to the existing
1077 * #GdkWindow is returned.
1079 * Return value: (transfer full): a #GdkWindow wrapper for the native
1080 * window, or %NULL if the window has been destroyed. The wrapper
1081 * will be newly created, if one doesn't exist already.
1086 gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
1091 GdkWindowImplX11 *impl;
1092 GdkX11Display *display_x11;
1093 XWindowAttributes attrs;
1094 Window root, parent;
1095 Window *children = NULL;
1099 g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
1101 display_x11 = GDK_X11_DISPLAY (display);
1103 if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
1104 return g_object_ref (win);
1106 gdk_x11_display_error_trap_push (display);
1107 result = XGetWindowAttributes (display_x11->xdisplay, window, &attrs);
1108 if (gdk_x11_display_error_trap_pop (display) || !result)
1111 /* FIXME: This is pretty expensive.
1112 * Maybe the caller should supply the parent
1114 gdk_x11_display_error_trap_push (display);
1115 result = XQueryTree (display_x11->xdisplay, window, &root, &parent, &children, &nchildren);
1116 if (gdk_x11_display_error_trap_pop (display) || !result)
1122 screen = _gdk_x11_display_screen_for_xrootwin (display, root);
1124 win = _gdk_display_create_window (display);
1125 win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
1126 win->impl_window = win;
1127 win->visual = gdk_x11_screen_lookup_visual (screen,
1128 XVisualIDFromVisual (attrs.visual));
1130 impl = GDK_WINDOW_IMPL_X11 (win->impl);
1131 impl->wrapper = win;
1133 win->parent = gdk_x11_window_lookup_for_display (display, parent);
1135 if (!win->parent || GDK_WINDOW_TYPE (win->parent) == GDK_WINDOW_FOREIGN)
1136 win->parent = gdk_screen_get_root_window (screen);
1138 win->parent->children = g_list_prepend (win->parent->children, win);
1144 win->width = attrs.width;
1145 win->height = attrs.height;
1146 win->window_type = GDK_WINDOW_FOREIGN;
1147 win->destroyed = FALSE;
1149 win->event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
1151 if (attrs.map_state == IsUnmapped)
1152 win->state = GDK_WINDOW_STATE_WITHDRAWN;
1155 win->viewable = TRUE;
1157 win->depth = attrs.depth;
1160 _gdk_x11_display_add_window (display, &GDK_WINDOW_XID (win), win);
1162 /* Update the clip region, etc */
1163 _gdk_window_update_size (win);
1169 gdk_toplevel_x11_free_contents (GdkDisplay *display,
1170 GdkToplevelX11 *toplevel)
1172 if (toplevel->icon_pixmap)
1174 cairo_surface_destroy (toplevel->icon_pixmap);
1175 toplevel->icon_pixmap = NULL;
1177 if (toplevel->icon_mask)
1179 cairo_surface_destroy (toplevel->icon_mask);
1180 toplevel->icon_mask = NULL;
1182 if (toplevel->group_leader)
1184 g_object_unref (toplevel->group_leader);
1185 toplevel->group_leader = NULL;
1188 if (toplevel->update_counter != None)
1190 XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display),
1191 toplevel->update_counter);
1192 toplevel->update_counter = None;
1194 toplevel->current_counter_value = 0;
1200 gdk_x11_window_destroy (GdkWindow *window,
1202 gboolean foreign_destroy)
1204 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1205 GdkToplevelX11 *toplevel;
1207 g_return_if_fail (GDK_IS_WINDOW (window));
1209 _gdk_x11_selection_window_destroyed (window);
1211 toplevel = _gdk_x11_window_get_toplevel (window);
1213 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
1215 if (impl->cairo_surface)
1217 cairo_surface_finish (impl->cairo_surface);
1218 cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
1222 if (!recursing && !foreign_destroy)
1223 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1226 static cairo_surface_t *
1227 gdk_window_x11_resize_cairo_surface (GdkWindow *window,
1228 cairo_surface_t *surface,
1232 cairo_xlib_surface_set_size (surface, width, height);
1238 gdk_x11_window_destroy_foreign (GdkWindow *window)
1240 /* It's somebody else's window, but in our hierarchy,
1241 * so reparent it to the root window, and then send
1242 * it a delete event, as if we were a WM
1244 XClientMessageEvent xclient;
1245 GdkDisplay *display;
1247 display = GDK_WINDOW_DISPLAY (window);
1248 gdk_x11_display_error_trap_push (display);
1249 gdk_window_hide (window);
1250 gdk_window_reparent (window, NULL, 0, 0);
1252 memset (&xclient, 0, sizeof (xclient));
1253 xclient.type = ClientMessage;
1254 xclient.window = GDK_WINDOW_XID (window);
1255 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "WM_PROTOCOLS");
1256 xclient.format = 32;
1257 xclient.data.l[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
1258 xclient.data.l[1] = CurrentTime;
1259 xclient.data.l[2] = 0;
1260 xclient.data.l[3] = 0;
1261 xclient.data.l[4] = 0;
1263 XSendEvent (GDK_WINDOW_XDISPLAY (window),
1264 GDK_WINDOW_XID (window),
1265 False, 0, (XEvent *)&xclient);
1266 gdk_x11_display_error_trap_pop_ignored (display);
1270 get_root (GdkWindow *window)
1272 GdkScreen *screen = gdk_window_get_screen (window);
1274 return gdk_screen_get_root_window (screen);
1277 /* This function is called when the XWindow is really gone.
1280 gdk_x11_window_destroy_notify (GdkWindow *window)
1282 GdkWindowImplX11 *window_impl;
1284 window_impl = GDK_WINDOW_IMPL_X11 ((window)->impl);
1286 if (!GDK_WINDOW_DESTROYED (window))
1288 if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
1289 g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
1291 _gdk_window_destroy (window, TRUE);
1294 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), GDK_WINDOW_XID (window));
1295 if (window_impl->toplevel && window_impl->toplevel->focus_window)
1296 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), window_impl->toplevel->focus_window);
1298 _gdk_x11_window_grab_check_destroy (window);
1300 g_object_unref (window);
1303 static GdkDragProtocol
1304 gdk_x11_window_get_drag_protocol (GdkWindow *window,
1307 GdkDragProtocol protocol;
1308 GdkDisplay *display;
1312 display = gdk_window_get_display (window);
1313 xid = _gdk_x11_display_get_drag_protocol (display,
1314 GDK_WINDOW_XID (window->impl_window),
1321 *target = gdk_x11_window_foreign_new_for_display (display, xid);
1330 update_wm_hints (GdkWindow *window,
1333 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
1334 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1338 !toplevel->is_leader &&
1339 window->state & GDK_WINDOW_STATE_WITHDRAWN)
1342 wm_hints.flags = StateHint | InputHint;
1343 wm_hints.input = window->accept_focus ? True : False;
1344 wm_hints.initial_state = NormalState;
1346 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1348 wm_hints.flags |= StateHint;
1349 wm_hints.initial_state = IconicState;
1352 if (toplevel->icon_pixmap)
1354 wm_hints.flags |= IconPixmapHint;
1355 wm_hints.icon_pixmap = cairo_xlib_surface_get_drawable (toplevel->icon_pixmap);
1358 if (toplevel->icon_mask)
1360 wm_hints.flags |= IconMaskHint;
1361 wm_hints.icon_mask = cairo_xlib_surface_get_drawable (toplevel->icon_mask);
1364 wm_hints.flags |= WindowGroupHint;
1365 if (toplevel->group_leader && !GDK_WINDOW_DESTROYED (toplevel->group_leader))
1367 wm_hints.flags |= WindowGroupHint;
1368 wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
1371 wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
1373 if (toplevel->urgency_hint)
1374 wm_hints.flags |= XUrgencyHint;
1376 XSetWMHints (GDK_WINDOW_XDISPLAY (window),
1377 GDK_WINDOW_XID (window),
1382 set_initial_hints (GdkWindow *window)
1384 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
1385 Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
1386 Window xwindow = GDK_WINDOW_XID (window);
1387 GdkToplevelX11 *toplevel;
1391 toplevel = _gdk_x11_window_get_toplevel (window);
1396 update_wm_hints (window, TRUE);
1398 /* We set the spec hints regardless of whether the spec is supported,
1399 * since it can't hurt and it's kind of expensive to check whether
1405 if (window->state & GDK_WINDOW_STATE_MAXIMIZED)
1407 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1408 "_NET_WM_STATE_MAXIMIZED_VERT");
1410 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1411 "_NET_WM_STATE_MAXIMIZED_HORZ");
1413 toplevel->have_maxhorz = toplevel->have_maxvert = TRUE;
1416 if (window->state & GDK_WINDOW_STATE_ABOVE)
1418 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1419 "_NET_WM_STATE_ABOVE");
1423 if (window->state & GDK_WINDOW_STATE_BELOW)
1425 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1426 "_NET_WM_STATE_BELOW");
1430 if (window->state & GDK_WINDOW_STATE_STICKY)
1432 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1433 "_NET_WM_STATE_STICKY");
1435 toplevel->have_sticky = TRUE;
1438 if (window->state & GDK_WINDOW_STATE_FULLSCREEN)
1440 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1441 "_NET_WM_STATE_FULLSCREEN");
1443 toplevel->have_fullscreen = TRUE;
1446 if (window->modal_hint)
1448 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1449 "_NET_WM_STATE_MODAL");
1453 if (toplevel->skip_taskbar_hint)
1455 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1456 "_NET_WM_STATE_SKIP_TASKBAR");
1460 if (toplevel->skip_pager_hint)
1462 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1463 "_NET_WM_STATE_SKIP_PAGER");
1467 if (window->state & GDK_WINDOW_STATE_ICONIFIED)
1469 atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
1470 "_NET_WM_STATE_HIDDEN");
1472 toplevel->have_hidden = TRUE;
1477 XChangeProperty (xdisplay,
1479 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"),
1480 XA_ATOM, 32, PropModeReplace,
1481 (guchar*) atoms, i);
1485 XDeleteProperty (xdisplay,
1487 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE"));
1490 if (window->state & GDK_WINDOW_STATE_STICKY)
1492 atoms[0] = 0xFFFFFFFF;
1493 XChangeProperty (xdisplay,
1495 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"),
1496 XA_CARDINAL, 32, PropModeReplace,
1497 (guchar*) atoms, 1);
1498 toplevel->on_all_desktops = TRUE;
1502 XDeleteProperty (xdisplay,
1504 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP"));
1507 toplevel->map_serial = NextRequest (xdisplay);
1511 gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
1513 GdkDisplay *display;
1514 GdkX11Display *display_x11;
1515 GdkToplevelX11 *toplevel;
1516 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1517 Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
1518 Window xwindow = GDK_WINDOW_XID (window);
1521 if (!already_mapped)
1522 set_initial_hints (window);
1524 if (WINDOW_IS_TOPLEVEL (window))
1526 display = gdk_window_get_display (window);
1527 display_x11 = GDK_X11_DISPLAY (display);
1528 toplevel = _gdk_x11_window_get_toplevel (window);
1530 if (toplevel->user_time != 0 &&
1531 display_x11->user_time != 0 &&
1532 XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
1533 gdk_x11_window_set_user_time (window, display_x11->user_time);
1536 unset_bg = !window->input_only &&
1537 (window->window_type == GDK_WINDOW_CHILD ||
1538 impl->override_redirect) &&
1539 gdk_window_is_viewable (window);
1542 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1544 XMapWindow (xdisplay, xwindow);
1547 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1549 /* Fullscreen on current monitor is the default, no need to apply this mode
1550 * when mapping a window. This also ensures that the default behavior remains
1551 * consistent with pre-fullscreen mode implementation.
1553 if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
1554 gdk_x11_window_apply_fullscreen_mode (window);
1558 pre_unmap (GdkWindow *window)
1560 GdkWindow *start_window = NULL;
1562 if (window->input_only)
1565 if (window->window_type == GDK_WINDOW_CHILD)
1566 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1567 else if (window->window_type == GDK_WINDOW_TEMP)
1568 start_window = get_root (window);
1571 _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
1575 post_unmap (GdkWindow *window)
1577 GdkWindow *start_window = NULL;
1579 if (window->input_only)
1582 if (window->window_type == GDK_WINDOW_CHILD)
1583 start_window = _gdk_window_get_impl_window ((GdkWindow *)window->parent);
1584 else if (window->window_type == GDK_WINDOW_TEMP)
1585 start_window = get_root (window);
1589 _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
1591 if (window->window_type == GDK_WINDOW_CHILD && window->parent)
1593 GdkRectangle invalid_rect;
1595 gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
1596 invalid_rect.width = gdk_window_get_width (window);
1597 invalid_rect.height = gdk_window_get_height (window);
1598 gdk_window_invalidate_rect ((GdkWindow *)window->parent,
1599 &invalid_rect, TRUE);
1605 gdk_window_x11_hide (GdkWindow *window)
1607 /* We'll get the unmap notify eventually, and handle it then,
1608 * but checking here makes things more consistent if we are
1609 * just doing stuff ourself.
1611 _gdk_x11_window_grab_check_unmap (window,
1612 NextRequest (GDK_WINDOW_XDISPLAY (window)));
1614 /* You can't simply unmap toplevel windows. */
1615 switch (window->window_type)
1617 case GDK_WINDOW_TOPLEVEL:
1618 case GDK_WINDOW_TEMP: /* ? */
1619 gdk_window_withdraw (window);
1622 case GDK_WINDOW_FOREIGN:
1623 case GDK_WINDOW_ROOT:
1624 case GDK_WINDOW_CHILD:
1628 _gdk_window_clear_update_area (window);
1631 XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
1632 GDK_WINDOW_XID (window));
1633 post_unmap (window);
1637 gdk_window_x11_withdraw (GdkWindow *window)
1639 if (!window->destroyed)
1641 if (GDK_WINDOW_IS_MAPPED (window))
1642 gdk_synthesize_window_state (window,
1644 GDK_WINDOW_STATE_WITHDRAWN);
1646 g_assert (!GDK_WINDOW_IS_MAPPED (window));
1650 XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
1651 GDK_WINDOW_XID (window), 0);
1653 post_unmap (window);
1658 window_x11_move (GdkWindow *window,
1662 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1664 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1666 /* The window isn't actually damaged, but it's parent is */
1667 window_pre_damage (window);
1668 _gdk_x11_window_move_resize_child (window,
1670 window->width, window->height);
1674 XMoveWindow (GDK_WINDOW_XDISPLAY (window),
1675 GDK_WINDOW_XID (window),
1678 if (impl->override_redirect)
1687 window_x11_resize (GdkWindow *window,
1697 window_pre_damage (window);
1699 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1701 _gdk_x11_window_move_resize_child (window,
1702 window->x, window->y,
1707 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1709 XResizeWindow (GDK_WINDOW_XDISPLAY (window),
1710 GDK_WINDOW_XID (window),
1713 if (impl->override_redirect)
1715 window->width = width;
1716 window->height = height;
1717 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1721 if (width != window->width || height != window->height)
1722 window->resize_count += 1;
1726 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1730 window_x11_move_resize (GdkWindow *window,
1742 window_pre_damage (window);
1744 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1746 _gdk_x11_window_move_resize_child (window, x, y, width, height);
1747 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1751 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
1753 XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
1754 GDK_WINDOW_XID (window),
1755 x, y, width, height);
1757 if (impl->override_redirect)
1762 window->width = width;
1763 window->height = height;
1765 _gdk_x11_window_update_size (GDK_WINDOW_IMPL_X11 (window->impl));
1769 if (width != window->width || height != window->height)
1770 window->resize_count += 1;
1776 gdk_window_x11_move_resize (GdkWindow *window,
1783 if (with_move && (width < 0 && height < 0))
1784 window_x11_move (window, x, y);
1788 window_x11_move_resize (window, x, y, width, height);
1790 window_x11_resize (window, width, height);
1795 gdk_window_x11_reparent (GdkWindow *window,
1796 GdkWindow *new_parent,
1800 GdkWindowImplX11 *impl;
1802 impl = GDK_WINDOW_IMPL_X11 (window->impl);
1804 _gdk_x11_window_tmp_unset_bg (window, TRUE);
1805 _gdk_x11_window_tmp_unset_parent_bg (window);
1806 XReparentWindow (GDK_WINDOW_XDISPLAY (window),
1807 GDK_WINDOW_XID (window),
1808 GDK_WINDOW_XID (new_parent),
1809 new_parent->abs_x + x, new_parent->abs_y + y);
1810 _gdk_x11_window_tmp_reset_parent_bg (window);
1811 _gdk_x11_window_tmp_reset_bg (window, TRUE);
1813 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1814 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1816 window->parent = new_parent;
1818 /* Switch the window type as appropriate */
1820 switch (GDK_WINDOW_TYPE (new_parent))
1822 case GDK_WINDOW_ROOT:
1823 case GDK_WINDOW_FOREIGN:
1824 /* Reparenting to toplevel */
1826 if (!WINDOW_IS_TOPLEVEL (window) &&
1827 GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1829 /* This is also done in common code at a later stage, but we
1830 need it in setup_toplevel, so do it here too */
1831 if (window->toplevel_window_type != -1)
1832 GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
1833 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1834 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1836 /* Wasn't a toplevel, set up */
1837 setup_toplevel_window (window, new_parent);
1842 case GDK_WINDOW_TOPLEVEL:
1843 case GDK_WINDOW_CHILD:
1844 case GDK_WINDOW_TEMP:
1845 if (WINDOW_IS_TOPLEVEL (window) &&
1848 if (impl->toplevel->focus_window)
1850 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
1851 _gdk_x11_display_remove_window (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
1854 gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window),
1856 g_free (impl->toplevel);
1857 impl->toplevel = NULL;
1865 gdk_window_x11_raise (GdkWindow *window)
1867 XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1871 gdk_window_x11_restack_under (GdkWindow *window,
1872 GList *native_siblings /* in requested order, first is bottom-most */)
1878 n_windows = g_list_length (native_siblings) + 1;
1879 windows = g_new (Window, n_windows);
1881 windows[0] = GDK_WINDOW_XID (window);
1882 /* Reverse order, as input order is bottom-most first */
1884 for (l = native_siblings; l != NULL; l = l->next)
1885 windows[i--] = GDK_WINDOW_XID (l->data);
1887 XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
1893 gdk_window_x11_restack_toplevel (GdkWindow *window,
1897 XWindowChanges changes;
1899 changes.sibling = GDK_WINDOW_XID (sibling);
1900 changes.stack_mode = above ? Above : Below;
1901 XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
1902 GDK_WINDOW_XID (window),
1903 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)),
1904 CWStackMode | CWSibling, &changes);
1908 gdk_window_x11_lower (GdkWindow *window)
1910 XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
1914 * gdk_x11_window_move_to_current_desktop:
1915 * @window: (type GdkX11Window): a #GdkWindow
1917 * Moves the window to the correct workspace when running under a
1918 * window manager that supports multiple workspaces, as described
1919 * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
1920 * Window Manager Hints</ulink>. Will not do anything if the
1921 * window is already on all workspaces.
1926 gdk_x11_window_move_to_current_desktop (GdkWindow *window)
1928 GdkToplevelX11 *toplevel;
1930 g_return_if_fail (GDK_IS_WINDOW (window));
1931 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
1933 toplevel = _gdk_x11_window_get_toplevel (window);
1935 if (toplevel->on_all_desktops)
1938 move_to_current_desktop (window);
1942 move_to_current_desktop (GdkWindow *window)
1944 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1945 gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
1946 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
1947 gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
1954 gulong *current_desktop;
1955 GdkDisplay *display;
1957 display = gdk_window_get_display (window);
1959 /* Get current desktop, then set it; this is a race, but not
1960 * one that matters much in practice.
1962 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
1963 GDK_WINDOW_XROOTWIN (window),
1964 gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
1966 False, XA_CARDINAL, &type, &format, &nitems,
1967 &bytes_after, &data);
1969 if (type == XA_CARDINAL)
1971 XClientMessageEvent xclient;
1972 current_desktop = (gulong *)data;
1974 memset (&xclient, 0, sizeof (xclient));
1975 xclient.type = ClientMessage;
1977 xclient.send_event = True;
1978 xclient.window = GDK_WINDOW_XID (window);
1979 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
1980 xclient.format = 32;
1982 xclient.data.l[0] = *current_desktop;
1983 xclient.data.l[1] = 1; /* source indication */
1984 xclient.data.l[2] = 0;
1985 xclient.data.l[3] = 0;
1986 xclient.data.l[4] = 0;
1988 XSendEvent (GDK_DISPLAY_XDISPLAY (display),
1989 GDK_WINDOW_XROOTWIN (window),
1991 SubstructureRedirectMask | SubstructureNotifyMask,
1992 (XEvent *)&xclient);
1994 XFree (current_desktop);
2000 gdk_x11_window_focus (GdkWindow *window,
2003 GdkDisplay *display;
2005 g_return_if_fail (GDK_IS_WINDOW (window));
2007 if (GDK_WINDOW_DESTROYED (window) ||
2008 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2011 display = GDK_WINDOW_DISPLAY (window);
2013 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2014 gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
2016 XClientMessageEvent xclient;
2018 memset (&xclient, 0, sizeof (xclient));
2019 xclient.type = ClientMessage;
2020 xclient.window = GDK_WINDOW_XID (window);
2021 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
2022 "_NET_ACTIVE_WINDOW");
2023 xclient.format = 32;
2024 xclient.data.l[0] = 1; /* requestor type; we're an app */
2025 xclient.data.l[1] = timestamp;
2026 xclient.data.l[2] = None; /* currently active window */
2027 xclient.data.l[3] = 0;
2028 xclient.data.l[4] = 0;
2030 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
2031 SubstructureRedirectMask | SubstructureNotifyMask,
2032 (XEvent *)&xclient);
2036 XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
2038 /* There is no way of knowing reliably whether we are viewable;
2039 * so trap errors asynchronously around the XSetInputFocus call
2041 gdk_x11_display_error_trap_push (display);
2042 XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
2043 GDK_WINDOW_XID (window),
2046 gdk_x11_display_error_trap_pop_ignored (display);
2051 gdk_x11_window_set_type_hint (GdkWindow *window,
2052 GdkWindowTypeHint hint)
2054 GdkDisplay *display;
2057 if (GDK_WINDOW_DESTROYED (window) ||
2058 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2061 display = gdk_window_get_display (window);
2065 case GDK_WINDOW_TYPE_HINT_DIALOG:
2066 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG");
2068 case GDK_WINDOW_TYPE_HINT_MENU:
2069 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU");
2071 case GDK_WINDOW_TYPE_HINT_TOOLBAR:
2072 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR");
2074 case GDK_WINDOW_TYPE_HINT_UTILITY:
2075 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY");
2077 case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
2078 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH");
2080 case GDK_WINDOW_TYPE_HINT_DOCK:
2081 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK");
2083 case GDK_WINDOW_TYPE_HINT_DESKTOP:
2084 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
2086 case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
2087 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
2089 case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
2090 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
2092 case GDK_WINDOW_TYPE_HINT_TOOLTIP:
2093 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
2095 case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
2096 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
2098 case GDK_WINDOW_TYPE_HINT_COMBO:
2099 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
2101 case GDK_WINDOW_TYPE_HINT_DND:
2102 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
2105 g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
2107 case GDK_WINDOW_TYPE_HINT_NORMAL:
2108 atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NORMAL");
2112 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2113 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2114 XA_ATOM, 32, PropModeReplace,
2115 (guchar *)&atom, 1);
2118 static GdkWindowTypeHint
2119 gdk_x11_window_get_type_hint (GdkWindow *window)
2121 GdkDisplay *display;
2122 GdkWindowTypeHint type;
2125 gulong nitems_return;
2126 gulong bytes_after_return;
2127 guchar *data = NULL;
2129 g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
2131 if (GDK_WINDOW_DESTROYED (window) ||
2132 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2133 return GDK_WINDOW_TYPE_HINT_NORMAL;
2135 type = GDK_WINDOW_TYPE_HINT_NORMAL;
2137 display = gdk_window_get_display (window);
2139 if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2140 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
2141 0, G_MAXLONG, False, XA_ATOM, &type_return,
2142 &format_return, &nitems_return, &bytes_after_return,
2145 if ((type_return == XA_ATOM) && (format_return == 32) &&
2146 (data) && (nitems_return == 1))
2148 Atom atom = *(Atom*)data;
2150 if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
2151 type = GDK_WINDOW_TYPE_HINT_DIALOG;
2152 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
2153 type = GDK_WINDOW_TYPE_HINT_MENU;
2154 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
2155 type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
2156 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
2157 type = GDK_WINDOW_TYPE_HINT_UTILITY;
2158 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
2159 type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
2160 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
2161 type = GDK_WINDOW_TYPE_HINT_DOCK;
2162 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
2163 type = GDK_WINDOW_TYPE_HINT_DESKTOP;
2164 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
2165 type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
2166 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
2167 type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
2168 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
2169 type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
2170 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
2171 type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
2172 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
2173 type = GDK_WINDOW_TYPE_HINT_COMBO;
2174 else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
2175 type = GDK_WINDOW_TYPE_HINT_DND;
2178 if (type_return != None && data != NULL)
2186 gdk_wmspec_change_state (gboolean add,
2191 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
2192 XClientMessageEvent xclient;
2194 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */
2195 #define _NET_WM_STATE_ADD 1 /* add/set property */
2196 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */
2198 memset (&xclient, 0, sizeof (xclient));
2199 xclient.type = ClientMessage;
2200 xclient.window = GDK_WINDOW_XID (window);
2201 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
2202 xclient.format = 32;
2203 xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
2204 xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
2205 xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
2206 xclient.data.l[3] = 1; /* source indication */
2207 xclient.data.l[4] = 0;
2209 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
2210 SubstructureRedirectMask | SubstructureNotifyMask,
2211 (XEvent *)&xclient);
2215 gdk_x11_window_set_modal_hint (GdkWindow *window,
2218 if (GDK_WINDOW_DESTROYED (window) ||
2219 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2222 window->modal_hint = modal;
2224 if (GDK_WINDOW_IS_MAPPED (window))
2225 gdk_wmspec_change_state (modal, window,
2226 gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"),
2231 gdk_x11_window_set_skip_taskbar_hint (GdkWindow *window,
2232 gboolean skips_taskbar)
2234 GdkToplevelX11 *toplevel;
2236 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2238 if (GDK_WINDOW_DESTROYED (window) ||
2239 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2242 toplevel = _gdk_x11_window_get_toplevel (window);
2243 toplevel->skip_taskbar_hint = skips_taskbar;
2245 if (GDK_WINDOW_IS_MAPPED (window))
2246 gdk_wmspec_change_state (skips_taskbar, window,
2247 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"),
2252 gdk_x11_window_set_skip_pager_hint (GdkWindow *window,
2253 gboolean skips_pager)
2255 GdkToplevelX11 *toplevel;
2257 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2259 if (GDK_WINDOW_DESTROYED (window) ||
2260 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2263 toplevel = _gdk_x11_window_get_toplevel (window);
2264 toplevel->skip_pager_hint = skips_pager;
2266 if (GDK_WINDOW_IS_MAPPED (window))
2267 gdk_wmspec_change_state (skips_pager, window,
2268 gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"),
2273 gdk_x11_window_set_urgency_hint (GdkWindow *window,
2276 GdkToplevelX11 *toplevel;
2278 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
2280 if (GDK_WINDOW_DESTROYED (window) ||
2281 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2284 toplevel = _gdk_x11_window_get_toplevel (window);
2285 toplevel->urgency_hint = urgent;
2287 update_wm_hints (window, FALSE);
2291 gdk_x11_window_set_geometry_hints (GdkWindow *window,
2292 const GdkGeometry *geometry,
2293 GdkWindowHints geom_mask)
2295 XSizeHints size_hints;
2297 if (GDK_WINDOW_DESTROYED (window) ||
2298 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2301 size_hints.flags = 0;
2303 if (geom_mask & GDK_HINT_POS)
2305 size_hints.flags |= PPosition;
2306 /* We need to initialize the following obsolete fields because KWM
2307 * apparently uses these fields if they are non-zero.
2314 if (geom_mask & GDK_HINT_USER_POS)
2316 size_hints.flags |= USPosition;
2319 if (geom_mask & GDK_HINT_USER_SIZE)
2321 size_hints.flags |= USSize;
2324 if (geom_mask & GDK_HINT_MIN_SIZE)
2326 size_hints.flags |= PMinSize;
2327 size_hints.min_width = geometry->min_width;
2328 size_hints.min_height = geometry->min_height;
2331 if (geom_mask & GDK_HINT_MAX_SIZE)
2333 size_hints.flags |= PMaxSize;
2334 size_hints.max_width = MAX (geometry->max_width, 1);
2335 size_hints.max_height = MAX (geometry->max_height, 1);
2338 if (geom_mask & GDK_HINT_BASE_SIZE)
2340 size_hints.flags |= PBaseSize;
2341 size_hints.base_width = geometry->base_width;
2342 size_hints.base_height = geometry->base_height;
2345 if (geom_mask & GDK_HINT_RESIZE_INC)
2347 size_hints.flags |= PResizeInc;
2348 size_hints.width_inc = geometry->width_inc;
2349 size_hints.height_inc = geometry->height_inc;
2352 if (geom_mask & GDK_HINT_ASPECT)
2354 size_hints.flags |= PAspect;
2355 if (geometry->min_aspect <= 1)
2357 size_hints.min_aspect.x = 65536 * geometry->min_aspect;
2358 size_hints.min_aspect.y = 65536;
2362 size_hints.min_aspect.x = 65536;
2363 size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
2365 if (geometry->max_aspect <= 1)
2367 size_hints.max_aspect.x = 65536 * geometry->max_aspect;
2368 size_hints.max_aspect.y = 65536;
2372 size_hints.max_aspect.x = 65536;
2373 size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
2377 if (geom_mask & GDK_HINT_WIN_GRAVITY)
2379 size_hints.flags |= PWinGravity;
2380 size_hints.win_gravity = geometry->win_gravity;
2383 /* FIXME: Would it be better to delete this property if
2384 * geom_mask == 0? It would save space on the server
2386 XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2387 GDK_WINDOW_XID (window),
2392 gdk_window_get_geometry_hints (GdkWindow *window,
2393 GdkGeometry *geometry,
2394 GdkWindowHints *geom_mask)
2396 XSizeHints *size_hints;
2397 glong junk_supplied_mask = 0;
2399 g_return_if_fail (GDK_IS_WINDOW (window));
2400 g_return_if_fail (geometry != NULL);
2401 g_return_if_fail (geom_mask != NULL);
2405 if (GDK_WINDOW_DESTROYED (window) ||
2406 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2409 size_hints = XAllocSizeHints ();
2413 if (!XGetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
2414 GDK_WINDOW_XID (window),
2416 &junk_supplied_mask))
2417 size_hints->flags = 0;
2419 if (size_hints->flags & PMinSize)
2421 *geom_mask |= GDK_HINT_MIN_SIZE;
2422 geometry->min_width = size_hints->min_width;
2423 geometry->min_height = size_hints->min_height;
2426 if (size_hints->flags & PMaxSize)
2428 *geom_mask |= GDK_HINT_MAX_SIZE;
2429 geometry->max_width = MAX (size_hints->max_width, 1);
2430 geometry->max_height = MAX (size_hints->max_height, 1);
2433 if (size_hints->flags & PResizeInc)
2435 *geom_mask |= GDK_HINT_RESIZE_INC;
2436 geometry->width_inc = size_hints->width_inc;
2437 geometry->height_inc = size_hints->height_inc;
2440 if (size_hints->flags & PAspect)
2442 *geom_mask |= GDK_HINT_ASPECT;
2444 geometry->min_aspect = (gdouble) size_hints->min_aspect.x / (gdouble) size_hints->min_aspect.y;
2445 geometry->max_aspect = (gdouble) size_hints->max_aspect.x / (gdouble) size_hints->max_aspect.y;
2448 if (size_hints->flags & PWinGravity)
2450 *geom_mask |= GDK_HINT_WIN_GRAVITY;
2451 geometry->win_gravity = size_hints->win_gravity;
2458 utf8_is_latin1 (const gchar *str)
2460 const char *p = str;
2464 gunichar ch = g_utf8_get_char (p);
2469 p = g_utf8_next_char (p);
2475 /* Set the property to @utf8_str as STRING if the @utf8_str is fully
2476 * convertable to STRING, otherwise, set it as compound text
2479 set_text_property (GdkDisplay *display,
2482 const gchar *utf8_str)
2484 gchar *prop_text = NULL;
2488 gboolean is_compound_text;
2490 if (utf8_is_latin1 (utf8_str))
2492 prop_type = XA_STRING;
2493 prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
2494 prop_length = prop_text ? strlen (prop_text) : 0;
2496 is_compound_text = FALSE;
2502 gdk_x11_display_utf8_to_compound_text (display,
2503 utf8_str, &gdk_type, &prop_format,
2504 (guchar **)&prop_text, &prop_length);
2505 prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
2506 is_compound_text = TRUE;
2511 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
2514 prop_type, prop_format,
2515 PropModeReplace, (guchar *)prop_text,
2518 if (is_compound_text)
2519 gdk_x11_free_compound_text ((guchar *)prop_text);
2525 /* Set WM_NAME and _NET_WM_NAME
2528 set_wm_name (GdkDisplay *display,
2532 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2533 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
2534 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2535 PropModeReplace, (guchar *)name, strlen (name));
2537 set_text_property (display, xwindow,
2538 gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
2543 gdk_x11_window_set_title (GdkWindow *window,
2546 GdkDisplay *display;
2550 g_return_if_fail (title != NULL);
2552 if (GDK_WINDOW_DESTROYED (window) ||
2553 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2556 display = gdk_window_get_display (window);
2557 xdisplay = GDK_DISPLAY_XDISPLAY (display);
2558 xwindow = GDK_WINDOW_XID (window);
2560 set_wm_name (display, xwindow, title);
2562 if (!gdk_window_icon_name_set (window))
2564 XChangeProperty (xdisplay, xwindow,
2565 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
2566 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2567 PropModeReplace, (guchar *)title, strlen (title));
2569 set_text_property (display, xwindow,
2570 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
2576 gdk_x11_window_set_role (GdkWindow *window,
2579 GdkDisplay *display;
2581 display = gdk_window_get_display (window);
2583 if (GDK_WINDOW_DESTROYED (window) ||
2584 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2588 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2589 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
2590 XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
2592 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2593 gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
2597 gdk_x11_window_set_startup_id (GdkWindow *window,
2598 const gchar *startup_id)
2600 GdkDisplay *display;
2602 g_return_if_fail (GDK_IS_WINDOW (window));
2604 display = gdk_window_get_display (window);
2606 if (GDK_WINDOW_DESTROYED (window) ||
2607 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2611 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2612 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"),
2613 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
2614 PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
2616 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
2617 gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
2621 gdk_x11_window_set_transient_for (GdkWindow *window,
2624 if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
2625 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
2626 XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
2627 GDK_WINDOW_XID (window),
2628 GDK_WINDOW_XID (parent));
2632 gdk_window_x11_set_back_color (GdkWindow *window,
2638 GdkVisual *visual = gdk_window_get_visual (window);
2640 /* I suppose we could handle these, but that'd require fiddling with
2641 * xrender formats... */
2645 switch (visual->type)
2647 case GDK_VISUAL_DIRECT_COLOR:
2648 case GDK_VISUAL_TRUE_COLOR:
2650 /* If bits not used for color are used for something other than padding,
2651 * it's likely alpha, so we set them to 1s.
2653 guint padding, pixel;
2655 /* Shifting by >= width-of-type isn't defined in C */
2656 if (visual->depth >= 32)
2659 padding = ((~(guint32)0)) << visual->depth;
2661 pixel = ~ (visual->red_mask | visual->green_mask | visual->blue_mask | padding);
2663 pixel += (((int) (red * ((1 << visual->red_prec ) - 1))) << visual->red_shift ) +
2664 (((int) (green * ((1 << visual->green_prec) - 1))) << visual->green_shift) +
2665 (((int) (blue * ((1 << visual->blue_prec ) - 1))) << visual->blue_shift );
2667 XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
2668 GDK_WINDOW_XID (window), pixel);
2672 /* These require fiddling with the colormap, and as they're essentially unused
2673 * we're just gonna skip them for now.
2675 case GDK_VISUAL_PSEUDO_COLOR:
2676 case GDK_VISUAL_GRAYSCALE:
2677 case GDK_VISUAL_STATIC_GRAY:
2678 case GDK_VISUAL_STATIC_COLOR:
2687 matrix_is_identity (cairo_matrix_t *matrix)
2689 return matrix->xx == 1.0 && matrix->yy == 1.0 &&
2690 matrix->yx == 0.0 && matrix->xy == 0.0 &&
2691 matrix->x0 == 0.0 && matrix->y0 == 0.0;
2695 gdk_window_x11_set_background (GdkWindow *window,
2696 cairo_pattern_t *pattern)
2699 cairo_surface_t *surface;
2700 cairo_matrix_t matrix;
2702 if (GDK_WINDOW_DESTROYED (window))
2705 if (pattern == NULL)
2709 /* X throws BadMatch if the parent has a different visual when
2710 * using ParentRelative */
2711 parent = gdk_window_get_parent (window);
2712 if (parent && gdk_window_get_visual (parent) == gdk_window_get_visual (window))
2713 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2714 GDK_WINDOW_XID (window), ParentRelative);
2716 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2717 GDK_WINDOW_XID (window), None);
2721 switch (cairo_pattern_get_type (pattern))
2723 case CAIRO_PATTERN_TYPE_SOLID:
2724 cairo_pattern_get_rgba (pattern, &r, &g, &b, &a);
2725 if (gdk_window_x11_set_back_color (window, r, g, b, a))
2728 case CAIRO_PATTERN_TYPE_SURFACE:
2729 cairo_pattern_get_matrix (pattern, &matrix);
2730 if (cairo_pattern_get_surface (pattern, &surface) == CAIRO_STATUS_SUCCESS &&
2731 matrix_is_identity (&matrix) &&
2732 cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB &&
2733 cairo_xlib_surface_get_visual (surface) == GDK_VISUAL_XVISUAL (gdk_window_get_visual ((window))) &&
2734 cairo_xlib_surface_get_display (surface) == GDK_WINDOW_XDISPLAY (window))
2738 cairo_surface_get_device_offset (surface, &x, &y);
2739 /* XXX: This still bombs for non-pixmaps, but there's no way to
2740 * detect we're not a pixmap in Cairo... */
2741 if (x == 0.0 && y == 0.0)
2743 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2744 GDK_WINDOW_XID (window),
2745 cairo_xlib_surface_get_drawable (surface));
2750 case CAIRO_PATTERN_TYPE_LINEAR:
2751 case CAIRO_PATTERN_TYPE_RADIAL:
2753 /* fallback: just use black */
2757 XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
2758 GDK_WINDOW_XID (window), None);
2762 gdk_window_x11_set_device_cursor (GdkWindow *window,
2766 GdkWindowImplX11 *impl;
2768 g_return_if_fail (GDK_IS_WINDOW (window));
2769 g_return_if_fail (GDK_IS_DEVICE (device));
2771 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2774 g_hash_table_remove (impl->device_cursor, device);
2777 _gdk_x11_cursor_update_theme (cursor);
2778 g_hash_table_replace (impl->device_cursor,
2779 device, g_object_ref (cursor));
2782 if (!GDK_WINDOW_DESTROYED (window))
2783 GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
2787 _gdk_x11_window_get_cursor (GdkWindow *window)
2789 GdkWindowImplX11 *impl;
2791 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2793 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2795 return impl->cursor;
2799 gdk_window_x11_get_geometry (GdkWindow *window,
2810 guint tborder_width;
2813 if (!GDK_WINDOW_DESTROYED (window))
2815 XGetGeometry (GDK_WINDOW_XDISPLAY (window),
2816 GDK_WINDOW_XID (window),
2817 &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
2831 gdk_window_x11_get_root_coords (GdkWindow *window,
2842 return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
2843 GDK_WINDOW_XID (window),
2844 GDK_WINDOW_XROOTWIN (window),
2857 gdk_x11_window_get_root_origin (GdkWindow *window,
2863 gdk_window_get_frame_extents (window, &rect);
2873 gdk_x11_window_get_frame_extents (GdkWindow *window,
2876 GdkDisplay *display;
2877 GdkWindowImplX11 *impl;
2888 gulong nitems_return;
2889 gulong bytes_after_return;
2892 guint ww, wh, wb, wd;
2894 gboolean got_frame_extents = FALSE;
2896 g_return_if_fail (rect != NULL);
2903 while (window->parent && (window->parent)->parent)
2904 window = window->parent;
2906 /* Refine our fallback answer a bit using local information */
2907 rect->x = window->x;
2908 rect->y = window->y;
2909 rect->width = window->width;
2910 rect->height = window->height;
2912 impl = GDK_WINDOW_IMPL_X11 (window->impl);
2913 if (GDK_WINDOW_DESTROYED (window) || impl->override_redirect)
2919 display = gdk_window_get_display (window);
2921 gdk_x11_display_error_trap_push (display);
2923 xwindow = GDK_WINDOW_XID (window);
2925 /* first try: use _NET_FRAME_EXTENTS */
2926 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2927 gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
2928 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
2929 gdk_x11_get_xatom_by_name_for_display (display,
2930 "_NET_FRAME_EXTENTS"),
2931 0, G_MAXLONG, False, XA_CARDINAL, &type_return,
2932 &format_return, &nitems_return, &bytes_after_return,
2936 if ((type_return == XA_CARDINAL) && (format_return == 32) &&
2937 (nitems_return == 4) && (data))
2939 gulong *ldata = (gulong *) data;
2940 got_frame_extents = TRUE;
2942 /* try to get the real client window geometry */
2943 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
2944 &root, &wx, &wy, &ww, &wh, &wb, &wd) &&
2945 XTranslateCoordinates (GDK_DISPLAY_XDISPLAY (display),
2946 xwindow, root, 0, 0, &wx, &wy, &child))
2954 /* _NET_FRAME_EXTENTS format is left, right, top, bottom */
2955 rect->x -= ldata[0];
2956 rect->y -= ldata[2];
2957 rect->width += ldata[0] + ldata[1];
2958 rect->height += ldata[2] + ldata[3];
2965 if (got_frame_extents)
2968 /* no frame extents property available, which means we either have a WM that
2969 is not EWMH compliant or is broken - try fallback and walk up the window
2970 tree to get our window's parent which hopefully is the window frame */
2972 /* use NETWM_VIRTUAL_ROOTS if available */
2973 root = GDK_WINDOW_XROOTWIN (window);
2975 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
2976 gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
2977 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
2978 gdk_x11_get_xatom_by_name_for_display (display,
2979 "_NET_VIRTUAL_ROOTS"),
2980 0, G_MAXLONG, False, XA_WINDOW, &type_return,
2981 &format_return, &nitems_return, &bytes_after_return,
2985 if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
2987 nvroots = nitems_return;
2988 vroots = (Window *)data;
2992 xparent = GDK_WINDOW_XID (window);
2998 if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
3000 &children, &nchildren))
3006 /* check virtual roots */
3007 for (i = 0; i < nvroots; i++)
3009 if (xparent == vroots[i])
3016 while (xparent != root);
3018 if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow,
3019 &root, &wx, &wy, &ww, &wh, &wb, &wd))
3031 gdk_x11_display_error_trap_pop_ignored (display);
3035 gdk_window_x11_get_device_state (GdkWindow *window,
3039 GdkModifierType *mask)
3043 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
3045 if (GDK_WINDOW_DESTROYED (window))
3048 GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
3052 return child != NULL;
3056 gdk_window_x11_get_events (GdkWindow *window)
3058 XWindowAttributes attrs;
3059 GdkEventMask event_mask;
3060 GdkEventMask filtered;
3062 if (GDK_WINDOW_DESTROYED (window))
3066 XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3067 GDK_WINDOW_XID (window),
3069 event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
3070 /* if property change was filtered out before, keep it filtered out */
3071 filtered = GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK;
3072 window->event_mask = event_mask & ((window->event_mask & filtered) | ~filtered);
3078 gdk_window_x11_set_events (GdkWindow *window,
3079 GdkEventMask event_mask)
3081 long xevent_mask = 0;
3083 if (!GDK_WINDOW_DESTROYED (window))
3085 GdkX11Display *display_x11;
3087 if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
3088 xevent_mask = StructureNotifyMask | PropertyChangeMask;
3090 display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
3091 gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
3092 GDK_WINDOW_XID (window), event_mask,
3098 do_shape_combine_region (GdkWindow *window,
3099 const cairo_region_t *shape_region,
3104 if (GDK_WINDOW_DESTROYED (window))
3107 if (shape_region == NULL)
3109 /* Use NULL mask to unset the shape */
3110 if (shape == ShapeBounding
3111 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3112 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3114 if (shape == ShapeBounding)
3116 _gdk_x11_window_tmp_unset_parent_bg (window);
3117 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3119 XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
3120 GDK_WINDOW_XID (window),
3125 if (shape == ShapeBounding)
3127 _gdk_x11_window_tmp_reset_parent_bg (window);
3128 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3134 if (shape == ShapeBounding
3135 ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
3136 : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
3139 XRectangle *xrects = NULL;
3141 _gdk_x11_region_get_xrectangles (shape_region,
3145 if (shape == ShapeBounding)
3147 _gdk_x11_window_tmp_unset_parent_bg (window);
3148 _gdk_x11_window_tmp_unset_bg (window, TRUE);
3150 XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
3151 GDK_WINDOW_XID (window),
3158 if (shape == ShapeBounding)
3160 _gdk_x11_window_tmp_reset_parent_bg (window);
3161 _gdk_x11_window_tmp_reset_bg (window, TRUE);
3169 gdk_window_x11_shape_combine_region (GdkWindow *window,
3170 const cairo_region_t *shape_region,
3174 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
3178 gdk_window_x11_input_shape_combine_region (GdkWindow *window,
3179 const cairo_region_t *shape_region,
3184 do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
3190 gdk_x11_window_set_override_redirect (GdkWindow *window,
3191 gboolean override_redirect)
3193 XSetWindowAttributes attr;
3195 if (!GDK_WINDOW_DESTROYED (window) &&
3196 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3198 GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
3200 attr.override_redirect = (override_redirect? True : False);
3201 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
3202 GDK_WINDOW_XID (window),
3206 impl->override_redirect = attr.override_redirect;
3211 gdk_x11_window_set_accept_focus (GdkWindow *window,
3212 gboolean accept_focus)
3214 accept_focus = accept_focus != FALSE;
3216 if (window->accept_focus != accept_focus)
3218 window->accept_focus = accept_focus;
3220 if (!GDK_WINDOW_DESTROYED (window) &&
3221 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3222 update_wm_hints (window, FALSE);
3227 gdk_x11_window_set_focus_on_map (GdkWindow *window,
3228 gboolean focus_on_map)
3230 focus_on_map = focus_on_map != FALSE;
3232 if (window->focus_on_map != focus_on_map)
3234 window->focus_on_map = focus_on_map;
3236 if ((!GDK_WINDOW_DESTROYED (window)) &&
3237 (!window->focus_on_map) &&
3238 WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3239 gdk_x11_window_set_user_time (window, 0);
3244 * gdk_x11_window_set_user_time:
3245 * @window: (type GdkX11Window): A toplevel #GdkWindow
3246 * @timestamp: An XServer timestamp to which the property should be set
3248 * The application can use this call to update the _NET_WM_USER_TIME
3249 * property on a toplevel window. This property stores an Xserver
3250 * time which represents the time of the last user input event
3251 * received for this window. This property may be used by the window
3252 * manager to alter the focus, stacking, and/or placement behavior of
3253 * windows when they are mapped depending on whether the new window
3254 * was created by a user action or is a "pop-up" window activated by a
3255 * timer or some other event.
3257 * Note that this property is automatically updated by GDK, so this
3258 * function should only be used by applications which handle input
3259 * events bypassing GDK.
3264 gdk_x11_window_set_user_time (GdkWindow *window,
3267 GdkDisplay *display;
3268 GdkX11Display *display_x11;
3269 GdkToplevelX11 *toplevel;
3270 glong timestamp_long = (glong)timestamp;
3273 if (GDK_WINDOW_DESTROYED (window) ||
3274 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3277 display = gdk_window_get_display (window);
3278 display_x11 = GDK_X11_DISPLAY (display);
3279 toplevel = _gdk_x11_window_get_toplevel (window);
3283 g_warning ("gdk_window_set_user_time called on non-toplevel\n");
3287 if (toplevel->focus_window != None &&
3288 gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
3289 gdk_atom_intern_static_string ("_NET_WM_USER_TIME_WINDOW")))
3290 xid = toplevel->focus_window;
3292 xid = GDK_WINDOW_XID (window);
3294 XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xid,
3295 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
3296 XA_CARDINAL, 32, PropModeReplace,
3297 (guchar *)×tamp_long, 1);
3299 if (timestamp_long != GDK_CURRENT_TIME &&
3300 (display_x11->user_time == GDK_CURRENT_TIME ||
3301 XSERVER_TIME_IS_LATER (timestamp_long, display_x11->user_time)))
3302 display_x11->user_time = timestamp_long;
3305 toplevel->user_time = timestamp_long;
3309 * gdk_x11_window_set_utf8_property:
3310 * @window: (type GdkX11Window): a #GdkWindow
3311 * @name: Property name, will be interned as an X atom
3312 * @value: (allow-none): Property value, or %NULL to delete
3314 * This function modifies or removes an arbitrary X11 window
3315 * property of type UTF8_STRING. If the given @window is
3316 * not a toplevel window, it is ignored.
3321 gdk_x11_window_set_utf8_property (GdkWindow *window,
3325 GdkDisplay *display;
3327 if (!WINDOW_IS_TOPLEVEL (window))
3330 display = gdk_window_get_display (window);
3334 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3335 GDK_WINDOW_XID (window),
3336 gdk_x11_get_xatom_by_name_for_display (display, name),
3337 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3338 PropModeReplace, (guchar *)value, strlen (value));
3342 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3343 GDK_WINDOW_XID (window),
3344 gdk_x11_get_xatom_by_name_for_display (display, name));
3349 * gdk_x11_window_set_hide_titlebar_when_maximized:
3350 * @window: (type GdkX11Window): a #GdkWindow
3351 * @hide_titlebar_when_maximized: whether to hide the titlebar when
3354 * Set a hint for the window manager, requesting that the titlebar
3355 * should be hidden when the window is maximized.
3357 * Note that this property is automatically updated by GTK+, so this
3358 * function should only be used by applications which do not use GTK+
3359 * to create toplevel windows.
3364 gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
3365 gboolean hide_titlebar_when_maximized)
3367 GdkDisplay *display;
3369 if (!WINDOW_IS_TOPLEVEL (window))
3372 display = gdk_window_get_display (window);
3374 if (hide_titlebar_when_maximized)
3377 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3378 GDK_WINDOW_XID (window),
3379 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
3381 PropModeReplace, (guchar *)&hide, 1);
3385 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3386 GDK_WINDOW_XID (window),
3387 gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
3392 * gdk_x11_window_set_theme_variant:
3393 * @window: (type GdkX11Window): a #GdkWindow
3394 * @variant: the theme variant to export
3396 * GTK+ applications can request a dark theme variant. In order to
3397 * make other applications - namely window managers using GTK+ for
3398 * themeing - aware of this choice, GTK+ uses this function to
3399 * export the requested theme variant as _GTK_THEME_VARIANT property
3400 * on toplevel windows.
3402 * Note that this property is automatically updated by GTK+, so this
3403 * function should only be used by applications which do not use GTK+
3404 * to create toplevel windows.
3409 gdk_x11_window_set_theme_variant (GdkWindow *window,
3412 return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
3415 #define GDK_SELECTION_MAX_SIZE(display) \
3417 XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
3418 ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100 \
3419 : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
3422 gdk_window_update_icon (GdkWindow *window,
3425 GdkToplevelX11 *toplevel;
3426 GdkPixbuf *best_icon;
3430 toplevel = _gdk_x11_window_get_toplevel (window);
3432 if (toplevel->icon_pixmap != NULL)
3434 cairo_surface_destroy (toplevel->icon_pixmap);
3435 toplevel->icon_pixmap = NULL;
3438 if (toplevel->icon_mask != NULL)
3440 cairo_surface_destroy (toplevel->icon_mask);
3441 toplevel->icon_mask = NULL;
3444 #define IDEAL_SIZE 48
3446 best_size = G_MAXINT;
3448 for (tmp_list = icon_list; tmp_list; tmp_list = tmp_list->next)
3450 GdkPixbuf *pixbuf = tmp_list->data;
3453 /* average width and height - if someone passes in a rectangular
3454 * icon they deserve what they get.
3456 this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf);
3459 if (best_icon == NULL)
3466 /* icon is better if it's 32 pixels or larger, and closer to
3467 * the ideal size than the current best.
3470 (ABS (best_size - IDEAL_SIZE) <
3471 ABS (this - IDEAL_SIZE)))
3481 int width = gdk_pixbuf_get_width (best_icon);
3482 int height = gdk_pixbuf_get_height (best_icon);
3485 toplevel->icon_pixmap = gdk_x11_window_create_pixmap_surface (window,
3489 cr = cairo_create (toplevel->icon_pixmap);
3490 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3491 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3492 if (gdk_pixbuf_get_has_alpha (best_icon))
3494 /* Saturate the image, so it has bilevel alpha */
3495 cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
3497 cairo_set_operator (cr, CAIRO_OPERATOR_SATURATE);
3499 cairo_pop_group_to_source (cr);
3504 if (gdk_pixbuf_get_has_alpha (best_icon))
3506 toplevel->icon_mask = _gdk_x11_window_create_bitmap_surface (window,
3510 cr = cairo_create (toplevel->icon_mask);
3511 gdk_cairo_set_source_pixbuf (cr, best_icon, 0, 0);
3512 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
3518 update_wm_hints (window, FALSE);
3522 gdk_x11_window_set_icon_list (GdkWindow *window,
3531 gint width, height, stride;
3534 GdkDisplay *display;
3537 if (GDK_WINDOW_DESTROYED (window) ||
3538 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3541 display = gdk_window_get_display (window);
3549 g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
3551 width = gdk_pixbuf_get_width (pixbuf);
3552 height = gdk_pixbuf_get_height (pixbuf);
3554 /* silently ignore overlarge icons */
3555 if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
3557 g_warning ("gdk_window_set_icon_list: icons too large");
3562 size += 2 + width * height;
3564 l = g_list_next (l);
3567 data = g_malloc (size * sizeof (gulong));
3575 width = gdk_pixbuf_get_width (pixbuf);
3576 height = gdk_pixbuf_get_height (pixbuf);
3577 stride = gdk_pixbuf_get_rowstride (pixbuf);
3578 n_channels = gdk_pixbuf_get_n_channels (pixbuf);
3583 pixels = gdk_pixbuf_get_pixels (pixbuf);
3585 for (y = 0; y < height; y++)
3587 for (x = 0; x < width; x++)
3591 r = pixels[y*stride + x*n_channels + 0];
3592 g = pixels[y*stride + x*n_channels + 1];
3593 b = pixels[y*stride + x*n_channels + 2];
3594 if (n_channels >= 4)
3595 a = pixels[y*stride + x*n_channels + 3];
3599 *p++ = a << 24 | r << 16 | g << 8 | b ;
3603 l = g_list_next (l);
3609 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3610 GDK_WINDOW_XID (window),
3611 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"),
3614 (guchar*) data, size);
3618 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3619 GDK_WINDOW_XID (window),
3620 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON"));
3625 gdk_window_update_icon (window, pixbufs);
3629 gdk_window_icon_name_set (GdkWindow *window)
3631 return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
3632 g_quark_from_static_string ("gdk-icon-name-set")));
3636 gdk_x11_window_set_icon_name (GdkWindow *window,
3639 GdkDisplay *display;
3641 if (GDK_WINDOW_DESTROYED (window) ||
3642 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3645 display = gdk_window_get_display (window);
3647 g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
3648 GUINT_TO_POINTER (name != NULL));
3652 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
3653 GDK_WINDOW_XID (window),
3654 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
3655 gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
3656 PropModeReplace, (guchar *)name, strlen (name));
3658 set_text_property (display, GDK_WINDOW_XID (window),
3659 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
3664 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3665 GDK_WINDOW_XID (window),
3666 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"));
3667 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
3668 GDK_WINDOW_XID (window),
3669 gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"));
3674 gdk_x11_window_iconify (GdkWindow *window)
3676 if (GDK_WINDOW_DESTROYED (window) ||
3677 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3680 if (GDK_WINDOW_IS_MAPPED (window))
3682 XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
3683 GDK_WINDOW_XID (window),
3684 gdk_screen_get_number (GDK_WINDOW_SCREEN (window)));
3688 /* Flip our client side flag, the real work happens on map. */
3689 gdk_synthesize_window_state (window,
3691 GDK_WINDOW_STATE_ICONIFIED);
3692 gdk_wmspec_change_state (TRUE, window,
3693 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3699 gdk_x11_window_deiconify (GdkWindow *window)
3701 if (GDK_WINDOW_DESTROYED (window) ||
3702 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3705 if (GDK_WINDOW_IS_MAPPED (window))
3707 gdk_window_show (window);
3708 gdk_wmspec_change_state (FALSE, window,
3709 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3714 /* Flip our client side flag, the real work happens on map. */
3715 gdk_synthesize_window_state (window,
3716 GDK_WINDOW_STATE_ICONIFIED,
3718 gdk_wmspec_change_state (FALSE, window,
3719 gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
3725 gdk_x11_window_stick (GdkWindow *window)
3727 if (GDK_WINDOW_DESTROYED (window) ||
3728 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3731 if (GDK_WINDOW_IS_MAPPED (window))
3733 /* "stick" means stick to all desktops _and_ do not scroll with the
3734 * viewport. i.e. glue to the monitor glass in all cases.
3737 XClientMessageEvent xclient;
3739 /* Request stick during viewport scroll */
3740 gdk_wmspec_change_state (TRUE, window,
3741 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3744 /* Request desktop 0xFFFFFFFF */
3745 memset (&xclient, 0, sizeof (xclient));
3746 xclient.type = ClientMessage;
3747 xclient.window = GDK_WINDOW_XID (window);
3748 xclient.display = GDK_WINDOW_XDISPLAY (window);
3749 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3751 xclient.format = 32;
3753 xclient.data.l[0] = 0xFFFFFFFF;
3754 xclient.data.l[1] = 0;
3755 xclient.data.l[2] = 0;
3756 xclient.data.l[3] = 0;
3757 xclient.data.l[4] = 0;
3759 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3760 SubstructureRedirectMask | SubstructureNotifyMask,
3761 (XEvent *)&xclient);
3765 /* Flip our client side flag, the real work happens on map. */
3766 gdk_synthesize_window_state (window,
3768 GDK_WINDOW_STATE_STICKY);
3773 gdk_x11_window_unstick (GdkWindow *window)
3775 if (GDK_WINDOW_DESTROYED (window) ||
3776 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3779 if (GDK_WINDOW_IS_MAPPED (window))
3781 /* Request unstick from viewport */
3782 gdk_wmspec_change_state (FALSE, window,
3783 gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
3786 move_to_current_desktop (window);
3790 /* Flip our client side flag, the real work happens on map. */
3791 gdk_synthesize_window_state (window,
3792 GDK_WINDOW_STATE_STICKY,
3799 gdk_x11_window_maximize (GdkWindow *window)
3801 if (GDK_WINDOW_DESTROYED (window) ||
3802 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3805 if (GDK_WINDOW_IS_MAPPED (window))
3806 gdk_wmspec_change_state (TRUE, window,
3807 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3808 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3810 gdk_synthesize_window_state (window,
3812 GDK_WINDOW_STATE_MAXIMIZED);
3816 gdk_x11_window_unmaximize (GdkWindow *window)
3818 if (GDK_WINDOW_DESTROYED (window) ||
3819 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3822 if (GDK_WINDOW_IS_MAPPED (window))
3823 gdk_wmspec_change_state (FALSE, window,
3824 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
3825 gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
3827 gdk_synthesize_window_state (window,
3828 GDK_WINDOW_STATE_MAXIMIZED,
3833 gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
3835 if (GDK_WINDOW_DESTROYED (window) ||
3836 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3839 /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
3840 * to which monitors so span across when the window is fullscreen, but it's
3841 * not a state in itself so this would have no effect if the window is not
3845 if (GDK_WINDOW_IS_MAPPED (window))
3847 XClientMessageEvent xclient;
3848 gint gdk_monitors[4];
3851 memset (&xclient, 0, sizeof (xclient));
3852 xclient.type = ClientMessage;
3853 xclient.window = GDK_WINDOW_XID (window);
3854 xclient.display = GDK_WINDOW_XDISPLAY (window);
3855 xclient.format = 32;
3857 switch (window->fullscreen_mode)
3859 case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
3861 /* FIXME: This is not part of the EWMH spec!
3863 * There is no documented mechanism to remove the property
3864 * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
3865 * invalid, largest possible value.
3867 * When given values larger than actual possible monitor values, most
3868 * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
3869 * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
3872 * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
3874 * Note, this (non documented) mechanism is unlikely to be an issue
3875 * as it's used only for transitionning back from "all monitors" to
3876 * "current monitor" mode.
3878 * Applications who don't change the default mode won't trigger this
3881 for (i = 0; i < 4; ++i)
3882 xclient.data.l[i] = G_MAXLONG;
3886 case GDK_FULLSCREEN_ON_ALL_MONITORS:
3888 _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
3893 /* Translate all 4 monitors from the GDK set into XINERAMA indices */
3894 for (i = 0; i < 4; ++i)
3896 xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
3898 /* Sanity check, if XINERAMA is not available, we could have invalid
3899 * negative values for the XINERAMA indices.
3901 if (xclient.data.l[i] < 0)
3903 g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
3910 g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
3911 window->fullscreen_mode);
3915 /* Send fullscreen monitors client message */
3916 xclient.data.l[4] = 1; /* source indication */
3917 xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
3918 "_NET_WM_FULLSCREEN_MONITORS");
3919 XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
3920 SubstructureRedirectMask | SubstructureNotifyMask,
3921 (XEvent *)&xclient);
3926 gdk_x11_window_fullscreen (GdkWindow *window)
3928 if (GDK_WINDOW_DESTROYED (window) ||
3929 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3932 if (GDK_WINDOW_IS_MAPPED (window))
3934 gdk_wmspec_change_state (TRUE, window,
3935 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3937 /* Actual XRandR layout may have change since we computed the fullscreen
3938 * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
3940 if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
3941 gdk_x11_window_apply_fullscreen_mode (window);
3944 gdk_synthesize_window_state (window,
3946 GDK_WINDOW_STATE_FULLSCREEN);
3950 gdk_x11_window_unfullscreen (GdkWindow *window)
3952 if (GDK_WINDOW_DESTROYED (window) ||
3953 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3956 if (GDK_WINDOW_IS_MAPPED (window))
3957 gdk_wmspec_change_state (FALSE, window,
3958 gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
3962 gdk_synthesize_window_state (window,
3963 GDK_WINDOW_STATE_FULLSCREEN,
3968 gdk_x11_window_set_keep_above (GdkWindow *window,
3971 g_return_if_fail (GDK_IS_WINDOW (window));
3973 if (GDK_WINDOW_DESTROYED (window) ||
3974 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
3977 if (GDK_WINDOW_IS_MAPPED (window))
3980 gdk_wmspec_change_state (FALSE, window,
3981 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
3983 gdk_wmspec_change_state (setting, window,
3984 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
3988 gdk_synthesize_window_state (window,
3989 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
3990 setting ? GDK_WINDOW_STATE_ABOVE : 0);
3994 gdk_x11_window_set_keep_below (GdkWindow *window, gboolean setting)
3996 g_return_if_fail (GDK_IS_WINDOW (window));
3998 if (GDK_WINDOW_DESTROYED (window) ||
3999 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4002 if (GDK_WINDOW_IS_MAPPED (window))
4005 gdk_wmspec_change_state (FALSE, window,
4006 gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
4008 gdk_wmspec_change_state (setting, window,
4009 gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
4013 gdk_synthesize_window_state (window,
4014 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
4015 setting ? GDK_WINDOW_STATE_BELOW : 0);
4019 gdk_x11_window_get_group (GdkWindow *window)
4021 GdkToplevelX11 *toplevel;
4023 if (GDK_WINDOW_DESTROYED (window) ||
4024 !WINDOW_IS_TOPLEVEL (window))
4027 toplevel = _gdk_x11_window_get_toplevel (window);
4029 return toplevel->group_leader;
4033 gdk_x11_window_set_group (GdkWindow *window,
4036 GdkToplevelX11 *toplevel;
4038 g_return_if_fail (GDK_IS_WINDOW (window));
4039 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
4040 g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
4042 if (GDK_WINDOW_DESTROYED (window) ||
4043 (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
4044 !WINDOW_IS_TOPLEVEL (window))
4047 toplevel = _gdk_x11_window_get_toplevel (window);
4050 leader = gdk_display_get_default_group (gdk_window_get_display (window));
4052 if (toplevel->group_leader != leader)
4054 if (toplevel->group_leader)
4055 g_object_unref (toplevel->group_leader);
4056 toplevel->group_leader = g_object_ref (leader);
4057 (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;
4060 update_wm_hints (window, FALSE);
4063 static MotifWmHints *
4064 gdk_window_get_mwm_hints (GdkWindow *window)
4066 GdkDisplay *display;
4067 Atom hints_atom = None;
4074 if (GDK_WINDOW_DESTROYED (window))
4077 display = gdk_window_get_display (window);
4079 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4081 XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
4082 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4083 False, AnyPropertyType, &type, &format, &nitems,
4084 &bytes_after, &data);
4089 return (MotifWmHints *)data;
4093 gdk_window_set_mwm_hints (GdkWindow *window,
4094 MotifWmHints *new_hints)
4096 GdkDisplay *display;
4097 Atom hints_atom = None;
4099 MotifWmHints *hints;
4105 if (GDK_WINDOW_DESTROYED (window))
4108 display = gdk_window_get_display (window);
4110 hints_atom = gdk_x11_get_xatom_by_name_for_display (display, _XA_MOTIF_WM_HINTS);
4112 XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4113 hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
4114 False, AnyPropertyType, &type, &format, &nitems,
4115 &bytes_after, &data);
4121 hints = (MotifWmHints *)data;
4123 if (new_hints->flags & MWM_HINTS_FUNCTIONS)
4125 hints->flags |= MWM_HINTS_FUNCTIONS;
4126 hints->functions = new_hints->functions;
4128 if (new_hints->flags & MWM_HINTS_DECORATIONS)
4130 hints->flags |= MWM_HINTS_DECORATIONS;
4131 hints->decorations = new_hints->decorations;
4135 XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
4136 hints_atom, hints_atom, 32, PropModeReplace,
4137 (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
4139 if (hints != new_hints)
4144 gdk_x11_window_set_decorations (GdkWindow *window,
4145 GdkWMDecoration decorations)
4149 if (GDK_WINDOW_DESTROYED (window) ||
4150 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4153 /* initialize to zero to avoid writing uninitialized data to socket */
4154 memset(&hints, 0, sizeof(hints));
4155 hints.flags = MWM_HINTS_DECORATIONS;
4156 hints.decorations = decorations;
4158 gdk_window_set_mwm_hints (window, &hints);
4162 gdk_x11_window_get_decorations(GdkWindow *window,
4163 GdkWMDecoration *decorations)
4165 MotifWmHints *hints;
4166 gboolean result = FALSE;
4168 if (GDK_WINDOW_DESTROYED (window) ||
4169 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4172 hints = gdk_window_get_mwm_hints (window);
4176 if (hints->flags & MWM_HINTS_DECORATIONS)
4179 *decorations = hints->decorations;
4190 gdk_x11_window_set_functions (GdkWindow *window,
4191 GdkWMFunction functions)
4195 g_return_if_fail (GDK_IS_WINDOW (window));
4197 if (GDK_WINDOW_DESTROYED (window) ||
4198 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4201 /* initialize to zero to avoid writing uninitialized data to socket */
4202 memset(&hints, 0, sizeof(hints));
4203 hints.flags = MWM_HINTS_FUNCTIONS;
4204 hints.functions = functions;
4206 gdk_window_set_mwm_hints (window, &hints);
4210 _gdk_x11_xwindow_get_shape (Display *xdisplay,
4214 cairo_region_t *shape;
4222 /* Note that XShapeGetRectangles returns NULL in two situations:
4223 * - the server doesn't support the SHAPE extension
4224 * - the shape is empty
4226 * Since we can't discriminate these here, we always return
4227 * an empty shape. It is the callers responsibility to check
4228 * whether the server supports the SHAPE extensions beforehand.
4230 xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
4233 return cairo_region_create (); /* Empty */
4235 if (ord != YXBanded)
4237 /* This really shouldn't happen with any xserver, as they
4238 * generally convert regions to YXBanded internally
4240 g_warning ("non YXBanded shape masks not supported");
4245 rl = g_new (GdkRectangle, rn);
4246 for (i = 0; i < rn; i++)
4250 rl[i].width = xrl[i].width;
4251 rl[i].height = xrl[i].height;
4255 shape = cairo_region_create_rectangles (rl, rn);
4262 static cairo_region_t *
4263 gdk_x11_window_get_shape (GdkWindow *window)
4265 if (!GDK_WINDOW_DESTROYED (window) &&
4266 gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
4267 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4268 GDK_WINDOW_XID (window),
4274 static cairo_region_t *
4275 gdk_x11_window_get_input_shape (GdkWindow *window)
4277 #if defined(ShapeInput)
4278 if (!GDK_WINDOW_DESTROYED (window) &&
4279 gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
4280 return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
4281 GDK_WINDOW_XID (window),
4289 gdk_window_set_static_bit_gravity (GdkWindow *window,
4292 XSetWindowAttributes xattributes;
4293 guint xattributes_mask = 0;
4295 g_return_if_fail (GDK_IS_WINDOW (window));
4297 if (window->input_only)
4300 xattributes.bit_gravity = StaticGravity;
4301 xattributes_mask |= CWBitGravity;
4302 xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
4303 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4304 GDK_WINDOW_XID (window),
4305 CWBitGravity, &xattributes);
4309 gdk_window_set_static_win_gravity (GdkWindow *window,
4312 XSetWindowAttributes xattributes;
4314 g_return_if_fail (GDK_IS_WINDOW (window));
4316 xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
4318 XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
4319 GDK_WINDOW_XID (window),
4320 CWWinGravity, &xattributes);
4324 gdk_window_x11_set_static_gravities (GdkWindow *window,
4325 gboolean use_static)
4329 if (!use_static == !window->guffaw_gravity)
4332 window->guffaw_gravity = use_static;
4334 if (!GDK_WINDOW_DESTROYED (window))
4336 gdk_window_set_static_bit_gravity (window, use_static);
4338 tmp_list = window->children;
4341 gdk_window_set_static_win_gravity (tmp_list->data, use_static);
4343 tmp_list = tmp_list->next;
4350 /* From the WM spec */
4351 #define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
4352 #define _NET_WM_MOVERESIZE_SIZE_TOP 1
4353 #define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
4354 #define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
4355 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
4356 #define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
4357 #define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
4358 #define _NET_WM_MOVERESIZE_SIZE_LEFT 7
4359 #define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
4360 #define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
4361 #define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
4362 #define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
4365 wmspec_send_message (GdkDisplay *display,
4372 XClientMessageEvent xclient;
4374 memset (&xclient, 0, sizeof (xclient));
4375 xclient.type = ClientMessage;
4376 xclient.window = GDK_WINDOW_XID (window);
4377 xclient.message_type =
4378 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_MOVERESIZE");
4379 xclient.format = 32;
4380 xclient.data.l[0] = root_x;
4381 xclient.data.l[1] = root_y;
4382 xclient.data.l[2] = action;
4383 xclient.data.l[3] = button;
4384 xclient.data.l[4] = 1; /* source indication */
4386 XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
4387 SubstructureRedirectMask | SubstructureNotifyMask,
4388 (XEvent *)&xclient);
4392 handle_wmspec_button_release (GdkDisplay *display,
4395 GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
4398 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4399 XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
4400 XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
4402 if (xevent->xany.type == GenericEvent)
4403 window = gdk_x11_window_lookup_for_display (display, xidev->event);
4406 window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
4408 if (display_x11->wm_moveresize_button != 0 && window != NULL)
4410 if ((xevent->xany.type == ButtonRelease &&
4411 xevent->xbutton.button == display_x11->wm_moveresize_button)
4412 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4414 (xevent->xany.type == GenericEvent &&
4415 xiev->evtype == XI_ButtonRelease &&
4416 xidev->detail == display_x11->wm_moveresize_button)
4420 display_x11->wm_moveresize_button = 0;
4421 wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
4427 wmspec_moveresize (GdkWindow *window,
4435 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
4437 /* Release passive grab */
4438 gdk_device_ungrab (device, timestamp);
4439 GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
4441 wmspec_send_message (display, window, root_x, root_y, direction, button);
4445 wmspec_resize_drag (GdkWindow *window,
4455 /* Let the compiler turn a switch into a table, instead
4456 * of doing the table manually, this way is easier to verify.
4460 case GDK_WINDOW_EDGE_NORTH_WEST:
4461 direction = _NET_WM_MOVERESIZE_SIZE_TOPLEFT;
4464 case GDK_WINDOW_EDGE_NORTH:
4465 direction = _NET_WM_MOVERESIZE_SIZE_TOP;
4468 case GDK_WINDOW_EDGE_NORTH_EAST:
4469 direction = _NET_WM_MOVERESIZE_SIZE_TOPRIGHT;
4472 case GDK_WINDOW_EDGE_WEST:
4473 direction = _NET_WM_MOVERESIZE_SIZE_LEFT;
4476 case GDK_WINDOW_EDGE_EAST:
4477 direction = _NET_WM_MOVERESIZE_SIZE_RIGHT;
4480 case GDK_WINDOW_EDGE_SOUTH_WEST:
4481 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT;
4484 case GDK_WINDOW_EDGE_SOUTH:
4485 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOM;
4488 case GDK_WINDOW_EDGE_SOUTH_EAST:
4489 direction = _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT;
4493 g_warning ("gdk_window_begin_resize_drag: bad resize edge %d!",
4498 wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
4501 typedef struct _MoveResizeData MoveResizeData;
4503 struct _MoveResizeData
4505 GdkDisplay *display;
4507 GdkWindow *moveresize_window;
4508 GdkWindow *moveresize_emulation_window;
4510 GdkWindowEdge resize_edge;
4512 gint moveresize_button;
4515 gint moveresize_orig_x;
4516 gint moveresize_orig_y;
4517 gint moveresize_orig_width;
4518 gint moveresize_orig_height;
4519 GdkWindowHints moveresize_geom_mask;
4520 GdkGeometry moveresize_geometry;
4521 Time moveresize_process_time;
4522 XEvent *moveresize_pending_event;
4525 static MoveResizeData *
4526 get_move_resize_data (GdkDisplay *display,
4529 MoveResizeData *mv_resize;
4530 static GQuark move_resize_quark = 0;
4532 if (!move_resize_quark)
4533 move_resize_quark = g_quark_from_static_string ("gdk-window-moveresize");
4535 mv_resize = g_object_get_qdata (G_OBJECT (display), move_resize_quark);
4537 if (!mv_resize && create)
4539 mv_resize = g_new0 (MoveResizeData, 1);
4540 mv_resize->display = display;
4542 g_object_set_qdata (G_OBJECT (display), move_resize_quark, mv_resize);
4549 update_pos (MoveResizeData *mv_resize,
4555 dx = new_root_x - mv_resize->moveresize_x;
4556 dy = new_root_y - mv_resize->moveresize_y;
4558 if (mv_resize->is_resize)
4562 x = mv_resize->moveresize_orig_x;
4563 y = mv_resize->moveresize_orig_y;
4565 w = mv_resize->moveresize_orig_width;
4566 h = mv_resize->moveresize_orig_height;
4568 switch (mv_resize->resize_edge)
4570 case GDK_WINDOW_EDGE_NORTH_WEST:
4576 case GDK_WINDOW_EDGE_NORTH:
4580 case GDK_WINDOW_EDGE_NORTH_EAST:
4585 case GDK_WINDOW_EDGE_SOUTH_WEST:
4590 case GDK_WINDOW_EDGE_SOUTH_EAST:
4594 case GDK_WINDOW_EDGE_SOUTH:
4597 case GDK_WINDOW_EDGE_EAST:
4600 case GDK_WINDOW_EDGE_WEST:
4611 if (mv_resize->moveresize_geom_mask)
4613 gdk_window_constrain_size (&mv_resize->moveresize_geometry,
4614 mv_resize->moveresize_geom_mask,
4618 gdk_window_move_resize (mv_resize->moveresize_window, x, y, w, h);
4624 x = mv_resize->moveresize_orig_x + dx;
4625 y = mv_resize->moveresize_orig_y + dy;
4627 gdk_window_move (mv_resize->moveresize_window, x, y);
4632 finish_drag (MoveResizeData *mv_resize)
4634 gdk_window_destroy (mv_resize->moveresize_emulation_window);
4635 mv_resize->moveresize_emulation_window = NULL;
4636 g_object_unref (mv_resize->moveresize_window);
4637 mv_resize->moveresize_window = NULL;
4639 if (mv_resize->moveresize_pending_event)
4641 g_free (mv_resize->moveresize_pending_event);
4642 mv_resize->moveresize_pending_event = NULL;
4647 lookahead_motion_predicate (Display *xdisplay,
4651 gboolean *seen_release = (gboolean *)arg;
4652 GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
4653 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4658 switch (event->xany.type)
4661 *seen_release = TRUE;
4664 mv_resize->moveresize_process_time = event->xmotion.time;
4674 moveresize_lookahead (MoveResizeData *mv_resize,
4678 gboolean seen_release = FALSE;
4680 if (mv_resize->moveresize_process_time)
4682 if (event->xmotion.time == mv_resize->moveresize_process_time)
4684 mv_resize->moveresize_process_time = 0;
4691 XCheckIfEvent (event->xany.display, &tmp_event,
4692 lookahead_motion_predicate, (XPointer) & seen_release);
4694 return mv_resize->moveresize_process_time == 0;
4698 _gdk_x11_moveresize_handle_event (XEvent *event)
4700 guint button_mask = 0;
4701 GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
4702 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4704 if (!mv_resize || !mv_resize->moveresize_window)
4706 handle_wmspec_button_release (display, event);
4710 button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
4712 switch (event->xany.type)
4715 if (mv_resize->moveresize_window->resize_count > 0)
4717 if (mv_resize->moveresize_pending_event)
4718 *mv_resize->moveresize_pending_event = *event;
4720 mv_resize->moveresize_pending_event =
4721 g_memdup (event, sizeof (XEvent));
4725 if (!moveresize_lookahead (mv_resize, event))
4728 update_pos (mv_resize,
4729 event->xmotion.x_root,
4730 event->xmotion.y_root);
4732 /* This should never be triggered in normal cases, but in the
4733 * case where the drag started without an implicit grab being
4734 * in effect, we could miss the release if it occurs before
4735 * we grab the pointer; this ensures that we will never
4736 * get a permanently stuck grab.
4738 if ((event->xmotion.state & button_mask) == 0)
4739 finish_drag (mv_resize);
4743 update_pos (mv_resize,
4744 event->xbutton.x_root,
4745 event->xbutton.y_root);
4747 if (event->xbutton.button == mv_resize->moveresize_button)
4748 finish_drag (mv_resize);
4751 #if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
4754 /* we just assume this is an XI2 event */
4755 XIEvent *ev = (XIEvent *) event->xcookie.data;
4756 XIDeviceEvent *xev = (XIDeviceEvent *)ev;
4761 update_pos (mv_resize, xev->root_x, xev->root_y);
4762 state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
4763 if ((state & button_mask) == 0)
4764 finish_drag (mv_resize);
4767 case XI_ButtonRelease:
4768 update_pos (mv_resize, xev->root_x, xev->root_y);
4769 if (xev->detail == mv_resize->moveresize_button)
4770 finish_drag (mv_resize);
4782 _gdk_x11_moveresize_configure_done (GdkDisplay *display,
4786 MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
4788 if (!mv_resize || window != mv_resize->moveresize_window)
4791 if (mv_resize->moveresize_pending_event)
4793 tmp_event = mv_resize->moveresize_pending_event;
4794 mv_resize->moveresize_pending_event = NULL;
4795 _gdk_x11_moveresize_handle_event (tmp_event);
4803 create_moveresize_window (MoveResizeData *mv_resize,
4806 GdkWindowAttr attributes;
4807 gint attributes_mask;
4808 GdkGrabStatus status;
4810 g_assert (mv_resize->moveresize_emulation_window == NULL);
4812 attributes.x = -100;
4813 attributes.y = -100;
4814 attributes.width = 10;
4815 attributes.height = 10;
4816 attributes.window_type = GDK_WINDOW_TEMP;
4817 attributes.wclass = GDK_INPUT_ONLY;
4818 attributes.override_redirect = TRUE;
4819 attributes.event_mask = 0;
4821 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
4823 mv_resize->moveresize_emulation_window =
4824 gdk_window_new (gdk_screen_get_root_window (gdk_display_get_default_screen (mv_resize->display)),
4828 gdk_window_show (mv_resize->moveresize_emulation_window);
4830 status = gdk_device_grab (mv_resize->device,
4831 mv_resize->moveresize_emulation_window,
4834 GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
4838 if (status != GDK_GRAB_SUCCESS)
4840 /* If this fails, some other client has grabbed the window
4843 finish_drag (mv_resize);
4846 mv_resize->moveresize_process_time = 0;
4850 Calculate mv_resize->moveresize_orig_x and mv_resize->moveresize_orig_y
4851 so that calling XMoveWindow with these coordinates will not move the
4853 Note that this depends on the WM to implement ICCCM-compliant reference
4857 calculate_unmoving_origin (MoveResizeData *mv_resize)
4862 if (mv_resize->moveresize_geom_mask & GDK_HINT_WIN_GRAVITY &&
4863 mv_resize->moveresize_geometry.win_gravity == GDK_GRAVITY_STATIC)
4865 gdk_window_get_origin (mv_resize->moveresize_window,
4866 &mv_resize->moveresize_orig_x,
4867 &mv_resize->moveresize_orig_y);
4871 gdk_window_get_frame_extents (mv_resize->moveresize_window, &rect);
4872 gdk_window_get_geometry (mv_resize->moveresize_window,
4873 NULL, NULL, &width, &height);
4875 switch (mv_resize->moveresize_geometry.win_gravity)
4877 case GDK_GRAVITY_NORTH_WEST:
4878 mv_resize->moveresize_orig_x = rect.x;
4879 mv_resize->moveresize_orig_y = rect.y;
4881 case GDK_GRAVITY_NORTH:
4882 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4883 mv_resize->moveresize_orig_y = rect.y;
4885 case GDK_GRAVITY_NORTH_EAST:
4886 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4887 mv_resize->moveresize_orig_y = rect.y;
4889 case GDK_GRAVITY_WEST:
4890 mv_resize->moveresize_orig_x = rect.x;
4891 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4893 case GDK_GRAVITY_CENTER:
4894 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4895 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4897 case GDK_GRAVITY_EAST:
4898 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4899 mv_resize->moveresize_orig_y = rect.y + rect.height / 2 - height / 2;
4901 case GDK_GRAVITY_SOUTH_WEST:
4902 mv_resize->moveresize_orig_x = rect.x;
4903 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4905 case GDK_GRAVITY_SOUTH:
4906 mv_resize->moveresize_orig_x = rect.x + rect.width / 2 - width / 2;
4907 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4909 case GDK_GRAVITY_SOUTH_EAST:
4910 mv_resize->moveresize_orig_x = rect.x + rect.width - width;
4911 mv_resize->moveresize_orig_y = rect.y + rect.height - height;
4914 mv_resize->moveresize_orig_x = rect.x;
4915 mv_resize->moveresize_orig_y = rect.y;
4922 emulate_resize_drag (GdkWindow *window,
4930 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4932 mv_resize->is_resize = TRUE;
4933 mv_resize->moveresize_button = button;
4934 mv_resize->resize_edge = edge;
4935 mv_resize->device = device;
4936 mv_resize->moveresize_x = root_x;
4937 mv_resize->moveresize_y = root_y;
4938 mv_resize->moveresize_window = g_object_ref (window);
4940 mv_resize->moveresize_orig_width = gdk_window_get_width (window);
4941 mv_resize->moveresize_orig_height = gdk_window_get_height (window);
4943 mv_resize->moveresize_geom_mask = 0;
4944 gdk_window_get_geometry_hints (window,
4945 &mv_resize->moveresize_geometry,
4946 &mv_resize->moveresize_geom_mask);
4948 calculate_unmoving_origin (mv_resize);
4950 create_moveresize_window (mv_resize, timestamp);
4954 emulate_move_drag (GdkWindow *window,
4961 MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
4963 mv_resize->is_resize = FALSE;
4964 mv_resize->device = device;
4965 mv_resize->moveresize_button = button;
4966 mv_resize->moveresize_x = root_x;
4967 mv_resize->moveresize_y = root_y;
4969 mv_resize->moveresize_window = g_object_ref (window);
4971 calculate_unmoving_origin (mv_resize);
4973 create_moveresize_window (mv_resize, timestamp);
4977 gdk_x11_window_begin_resize_drag (GdkWindow *window,
4985 if (GDK_WINDOW_DESTROYED (window) ||
4986 !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
4989 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
4990 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
4991 wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4993 emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
4997 gdk_x11_window_begin_move_drag (GdkWindow *window,
5004 if (GDK_WINDOW_DESTROYED (window) ||
5005 !WINDOW_IS_TOPLEVEL (window))
5008 if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
5009 gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
5010 wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
5011 device, button, root_x, root_y, timestamp);
5013 emulate_move_drag (window, device, button, root_x, root_y, timestamp);
5017 gdk_x11_window_enable_synchronized_configure (GdkWindow *window)
5019 GdkWindowImplX11 *impl;
5021 if (!GDK_IS_WINDOW_IMPL_X11 (window->impl))
5024 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5026 if (!impl->use_synchronized_configure)
5028 /* This basically means you want to do fancy X specific stuff, so
5029 ensure we have a native window */
5030 gdk_window_ensure_native (window);
5032 impl->use_synchronized_configure = TRUE;
5033 ensure_sync_counter (window);
5038 gdk_x11_window_configure_finished (GdkWindow *window)
5040 GdkWindowImplX11 *impl;
5042 if (!WINDOW_IS_TOPLEVEL (window))
5045 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5046 if (!impl->use_synchronized_configure)
5050 if (!GDK_WINDOW_DESTROYED (window))
5052 GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
5053 GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
5055 if (toplevel && toplevel->update_counter != None &&
5056 GDK_X11_DISPLAY (display)->use_sync &&
5057 toplevel->configure_counter_value != 0)
5059 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5060 toplevel->update_counter,
5061 toplevel->configure_counter_value);
5063 toplevel->current_counter_value = toplevel->configure_counter_value;
5064 if ((toplevel->current_counter_value % 2) == 1)
5065 toplevel->current_counter_value += 1;
5067 toplevel->configure_counter_value = 0;
5069 set_sync_counter (GDK_WINDOW_XDISPLAY (window),
5070 toplevel->extended_update_counter,
5071 toplevel->current_counter_value);
5078 gdk_x11_window_beep (GdkWindow *window)
5080 GdkDisplay *display;
5082 display = GDK_WINDOW_DISPLAY (window);
5085 if (GDK_X11_DISPLAY (display)->use_xkb)
5087 XkbBell (GDK_DISPLAY_XDISPLAY (display),
5088 GDK_WINDOW_XID (window),
5099 gdk_x11_window_set_opacity (GdkWindow *window,
5102 GdkDisplay *display;
5105 g_return_if_fail (GDK_IS_WINDOW (window));
5107 if (GDK_WINDOW_DESTROYED (window) ||
5108 !WINDOW_IS_TOPLEVEL (window))
5111 display = gdk_window_get_display (window);
5115 else if (opacity > 1)
5118 cardinal = opacity * 0xffffffff;
5120 if (cardinal == 0xffffffff)
5121 XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
5122 GDK_WINDOW_XID (window),
5123 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"));
5125 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
5126 GDK_WINDOW_XID (window),
5127 gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_OPACITY"),
5130 (guchar *) &cardinal, 1);
5134 gdk_x11_window_set_composited (GdkWindow *window,
5135 gboolean composited)
5137 #if defined(HAVE_XCOMPOSITE) && defined(HAVE_XDAMAGE) && defined (HAVE_XFIXES)
5138 GdkWindowImplX11 *impl;
5139 GdkDisplay *display;
5143 impl = GDK_WINDOW_IMPL_X11 (window->impl);
5145 display = gdk_window_get_display (window);
5146 dpy = GDK_DISPLAY_XDISPLAY (display);
5147 xid = GDK_WINDOW_XID (window);
5151 XCompositeRedirectWindow (dpy, xid, CompositeRedirectManual);
5152 impl->damage = XDamageCreate (dpy, xid, XDamageReportBoundingBox);
5156 XCompositeUnredirectWindow (dpy, xid, CompositeRedirectManual);
5157 XDamageDestroy (dpy, impl->damage);
5158 impl->damage = None;
5164 gdk_x11_window_process_updates_recurse (GdkWindow *window,
5165 cairo_region_t *region)
5167 _gdk_window_process_updates_recurse (window, region);
5171 _gdk_x11_display_before_process_all_updates (GdkDisplay *display)
5176 _gdk_x11_display_after_process_all_updates (GdkDisplay *display)
5178 /* Sync after all drawing, otherwise the client can get "ahead" of
5179 the server rendering during animations, such that we fill up
5180 the Xserver pipes with sync rendering ops not letting other
5181 clients (including the VM) do anything. */
5182 XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
5186 timestamp_predicate (Display *display,
5190 Window xwindow = GPOINTER_TO_UINT (arg);
5191 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
5193 if (xevent->type == PropertyNotify &&
5194 xevent->xproperty.window == xwindow &&
5195 xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
5196 "GDK_TIMESTAMP_PROP"))
5203 * gdk_x11_get_server_time:
5204 * @window: (type GdkX11Window): a #GdkWindow, used for communication
5205 * with the server. The window must have
5206 * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
5209 * Routine to get the current X server time stamp.
5211 * Return value: the time stamp.
5214 gdk_x11_get_server_time (GdkWindow *window)
5220 Atom timestamp_prop_atom;
5222 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5223 g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
5225 xdisplay = GDK_WINDOW_XDISPLAY (window);
5226 xwindow = GDK_WINDOW_XID (window);
5227 timestamp_prop_atom =
5228 gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
5229 "GDK_TIMESTAMP_PROP");
5231 XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
5232 timestamp_prop_atom,
5233 8, PropModeReplace, &c, 1);
5235 XIfEvent (xdisplay, &xevent,
5236 timestamp_predicate, GUINT_TO_POINTER(xwindow));
5238 return xevent.xproperty.time;
5242 * gdk_x11_window_get_xid:
5243 * @window: (type GdkX11Window): a native #GdkWindow.
5245 * Returns the X resource (window) belonging to a #GdkWindow.
5247 * Return value: the ID of @drawable's X resource.
5250 gdk_x11_window_get_xid (GdkWindow *window)
5252 /* Try to ensure the window has a native window */
5253 if (!_gdk_window_has_impl (window))
5255 gdk_window_ensure_native (window);
5257 /* We sync here to ensure the window is created in the Xserver when
5258 * this function returns. This is required because the returned XID
5259 * for this window must be valid immediately, even with another
5260 * connection to the Xserver */
5261 gdk_display_sync (gdk_window_get_display (window));
5264 if (!GDK_WINDOW_IS_X11 (window))
5266 g_warning (G_STRLOC " drawable is not a native X11 window");
5270 return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
5274 gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
5276 GObjectClass *object_class = G_OBJECT_CLASS (klass);
5277 GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_CLASS (klass);
5279 object_class->finalize = gdk_window_impl_x11_finalize;
5281 impl_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
5282 impl_class->show = gdk_window_x11_show;
5283 impl_class->hide = gdk_window_x11_hide;
5284 impl_class->withdraw = gdk_window_x11_withdraw;
5285 impl_class->set_events = gdk_window_x11_set_events;
5286 impl_class->get_events = gdk_window_x11_get_events;
5287 impl_class->raise = gdk_window_x11_raise;
5288 impl_class->lower = gdk_window_x11_lower;
5289 impl_class->restack_under = gdk_window_x11_restack_under;
5290 impl_class->restack_toplevel = gdk_window_x11_restack_toplevel;
5291 impl_class->move_resize = gdk_window_x11_move_resize;
5292 impl_class->set_background = gdk_window_x11_set_background;
5293 impl_class->reparent = gdk_window_x11_reparent;
5294 impl_class->set_device_cursor = gdk_window_x11_set_device_cursor;
5295 impl_class->get_geometry = gdk_window_x11_get_geometry;
5296 impl_class->get_root_coords = gdk_window_x11_get_root_coords;
5297 impl_class->get_device_state = gdk_window_x11_get_device_state;
5298 impl_class->shape_combine_region = gdk_window_x11_shape_combine_region;
5299 impl_class->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
5300 impl_class->set_static_gravities = gdk_window_x11_set_static_gravities;
5301 impl_class->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
5302 impl_class->translate = _gdk_x11_window_translate;
5303 impl_class->destroy = gdk_x11_window_destroy;
5304 impl_class->destroy_foreign = gdk_x11_window_destroy_foreign;
5305 impl_class->resize_cairo_surface = gdk_window_x11_resize_cairo_surface;
5306 impl_class->get_shape = gdk_x11_window_get_shape;
5307 impl_class->get_input_shape = gdk_x11_window_get_input_shape;
5308 impl_class->beep = gdk_x11_window_beep;
5310 impl_class->focus = gdk_x11_window_focus;
5311 impl_class->set_type_hint = gdk_x11_window_set_type_hint;
5312 impl_class->get_type_hint = gdk_x11_window_get_type_hint;
5313 impl_class->set_modal_hint = gdk_x11_window_set_modal_hint;
5314 impl_class->set_skip_taskbar_hint = gdk_x11_window_set_skip_taskbar_hint;
5315 impl_class->set_skip_pager_hint = gdk_x11_window_set_skip_pager_hint;
5316 impl_class->set_urgency_hint = gdk_x11_window_set_urgency_hint;
5317 impl_class->set_geometry_hints = gdk_x11_window_set_geometry_hints;
5318 impl_class->set_title = gdk_x11_window_set_title;
5319 impl_class->set_role = gdk_x11_window_set_role;
5320 impl_class->set_startup_id = gdk_x11_window_set_startup_id;
5321 impl_class->set_transient_for = gdk_x11_window_set_transient_for;
5322 impl_class->get_root_origin = gdk_x11_window_get_root_origin;
5323 impl_class->get_frame_extents = gdk_x11_window_get_frame_extents;
5324 impl_class->set_override_redirect = gdk_x11_window_set_override_redirect;
5325 impl_class->set_accept_focus = gdk_x11_window_set_accept_focus;
5326 impl_class->set_focus_on_map = gdk_x11_window_set_focus_on_map;
5327 impl_class->set_icon_list = gdk_x11_window_set_icon_list;
5328 impl_class->set_icon_name = gdk_x11_window_set_icon_name;
5329 impl_class->iconify = gdk_x11_window_iconify;
5330 impl_class->deiconify = gdk_x11_window_deiconify;
5331 impl_class->stick = gdk_x11_window_stick;
5332 impl_class->unstick = gdk_x11_window_unstick;
5333 impl_class->maximize = gdk_x11_window_maximize;
5334 impl_class->unmaximize = gdk_x11_window_unmaximize;
5335 impl_class->fullscreen = gdk_x11_window_fullscreen;
5336 impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
5337 impl_class->unfullscreen = gdk_x11_window_unfullscreen;
5338 impl_class->set_keep_above = gdk_x11_window_set_keep_above;
5339 impl_class->set_keep_below = gdk_x11_window_set_keep_below;
5340 impl_class->get_group = gdk_x11_window_get_group;
5341 impl_class->set_group = gdk_x11_window_set_group;
5342 impl_class->set_decorations = gdk_x11_window_set_decorations;
5343 impl_class->get_decorations = gdk_x11_window_get_decorations;
5344 impl_class->set_functions = gdk_x11_window_set_functions;
5345 impl_class->set_functions = gdk_x11_window_set_functions;
5346 impl_class->begin_resize_drag = gdk_x11_window_begin_resize_drag;
5347 impl_class->begin_move_drag = gdk_x11_window_begin_move_drag;
5348 impl_class->enable_synchronized_configure = gdk_x11_window_enable_synchronized_configure;
5349 impl_class->configure_finished = gdk_x11_window_configure_finished;
5350 impl_class->set_opacity = gdk_x11_window_set_opacity;
5351 impl_class->set_composited = gdk_x11_window_set_composited;
5352 impl_class->destroy_notify = gdk_x11_window_destroy_notify;
5353 impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
5354 impl_class->register_dnd = _gdk_x11_window_register_dnd;
5355 impl_class->drag_begin = _gdk_x11_window_drag_begin;
5356 impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;
5357 impl_class->sync_rendering = _gdk_x11_window_sync_rendering;
5358 impl_class->simulate_key = _gdk_x11_window_simulate_key;
5359 impl_class->simulate_button = _gdk_x11_window_simulate_button;
5360 impl_class->get_property = _gdk_x11_window_get_property;
5361 impl_class->change_property = _gdk_x11_window_change_property;
5362 impl_class->delete_property = _gdk_x11_window_delete_property;