* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
#include "gdkasync.h"
#include "gdkeventsource.h"
#include "gdkdisplay-x11.h"
+#include "gdkframeclockidle.h"
#include "gdkprivate-x11.h"
#include <stdlib.h>
const gint _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table);
/* Forward declarations */
+static void gdk_x11_window_apply_fullscreen_mode (GdkWindow *window);
static void gdk_window_set_static_win_gravity (GdkWindow *window,
gboolean on);
static gboolean gdk_window_icon_name_set (GdkWindow *window);
(( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
)
+struct _GdkX11Window {
+ GdkWindow parent;
+};
+
+struct _GdkX11WindowClass {
+ GdkWindowClass parent_class;
+};
+
+G_DEFINE_TYPE (GdkX11Window, gdk_x11_window, GDK_TYPE_WINDOW)
+
+static void
+gdk_x11_window_class_init (GdkX11WindowClass *x11_window_class)
+{
+}
+
+static void
+gdk_x11_window_init (GdkX11Window *x11_window)
+{
+}
+
+
G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_WINDOW_IMPL)
static void
gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
{
impl->toplevel_window_type = -1;
- impl->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
- (GDestroyNotify) gdk_cursor_unref);
+ impl->device_cursor = g_hash_table_new_full (NULL, NULL,
+ NULL, g_object_unref);
}
GdkToplevelX11 *
impl = GDK_WINDOW_IMPL_X11 (window->impl);
if (!impl->toplevel)
- impl->toplevel = g_new0 (GdkToplevelX11, 1);
+ {
+ impl->toplevel = g_new0 (GdkToplevelX11, 1);
+ impl->toplevel->have_focused = TRUE;
+ }
return impl->toplevel;
}
}
}
+static void
+set_sync_counter(Display *display,
+ XSyncCounter counter,
+ gint64 value)
+{
+ XSyncValue sync_value;
+
+ XSyncIntsToValue(&sync_value,
+ value & G_GINT64_CONSTANT(0xFFFFFFFF),
+ value >> 32);
+ XSyncSetCounter(display, counter, sync_value);
+}
+
+static void
+window_pre_damage (GdkWindow *window)
+{
+ GdkWindow *toplevel_window = gdk_window_get_toplevel (window);
+ GdkWindowImplX11 *impl;
+
+ if (!toplevel_window || !WINDOW_IS_TOPLEVEL (toplevel_window))
+ return;
+
+ impl = GDK_WINDOW_IMPL_X11 (toplevel_window->impl);
+
+ if (impl->toplevel->in_frame &&
+ impl->toplevel->current_counter_value % 2 == 0)
+ {
+ impl->toplevel->current_counter_value += 1;
+ set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
+ impl->toplevel->extended_update_counter,
+ impl->toplevel->current_counter_value);
+ }
+}
+
+static void
+on_surface_changed (void *data)
+{
+ GdkWindow *window = data;
+
+ window_pre_damage (window);
+}
+
+/* We want to know when cairo drawing causes damage to the window,
+ * so we engage in the _NET_WM_FRAME_DRAWN protocol with the
+ * window only when there actually is drawing. To do that we use
+ * a technique (hack) suggested by Uli Schlachter - if we set
+ * a dummy "mime data" on the cairo surface (this facility is
+ * used to attach JPEG data to an imager), then cairo wil flush
+ * and remove the mime data before making any changes to the window.
+ */
+
+static void
+hook_surface_changed (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
+
+ if (impl->cairo_surface)
+ cairo_surface_set_mime_data (impl->cairo_surface,
+ "x-gdk/change-notify",
+ (unsigned char *)"X",
+ 1,
+ on_surface_changed,
+ window);
+}
+
+static void
+unhook_surface_changed (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
+
+ if (impl->cairo_surface)
+ cairo_surface_set_mime_data (impl->cairo_surface,
+ "x-gdk/change-notify",
+ NULL, 0,
+ NULL, NULL);
+}
+
+static void
+gdk_x11_window_begin_frame (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl = GDK_WINDOW_IMPL_X11 (window->impl);
+
+ if (!WINDOW_IS_TOPLEVEL (window) ||
+ impl->toplevel->extended_update_counter == None)
+ return;
+
+ impl->toplevel->in_frame = TRUE;
+
+ hook_surface_changed (window);
+}
+
+static void
+gdk_x11_window_end_frame (GdkWindow *window)
+{
+ GdkWindowImplX11 *impl;
+
+ g_return_if_fail (GDK_IS_WINDOW (window));
+
+ impl = GDK_WINDOW_IMPL_X11 (window->impl);
+
+ if (!WINDOW_IS_TOPLEVEL (window) ||
+ impl->toplevel->extended_update_counter == None ||
+ !impl->toplevel->in_frame)
+ return;
+
+ impl->toplevel->in_frame = FALSE;
+
+ if (impl->toplevel->current_counter_value % 2 == 1)
+ {
+ impl->toplevel->current_counter_value += 1;
+ set_sync_counter(GDK_WINDOW_XDISPLAY (impl->wrapper),
+ impl->toplevel->extended_update_counter,
+ impl->toplevel->current_counter_value);
+
+ if (gdk_x11_screen_supports_net_wm_hint (gdk_window_get_screen (window),
+ gdk_atom_intern_static_string ("_NET_WM_FRAME_DRAWN")))
+ {
+ impl->toplevel->frame_pending = TRUE;
+ gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
+ }
+ }
+
+ unhook_surface_changed (window);
+}
+
/*****************************************************
* X11 specific implementations of generic functions *
*****************************************************/
if (impl->cairo_surface)
cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
impl, gdk_x11_cairo_surface_destroy);
+
+ if (WINDOW_IS_TOPLEVEL (window) && impl->toplevel->in_frame)
+ hook_surface_changed (window);
}
else
cairo_surface_reference (impl->cairo_surface);
wrapper = impl->wrapper;
+ if (WINDOW_IS_TOPLEVEL (wrapper) && impl->toplevel->in_frame)
+ unhook_surface_changed (wrapper);
+
_gdk_x11_window_grab_check_destroy (wrapper);
if (!GDK_WINDOW_DESTROYED (wrapper))
g_free (impl->toplevel);
if (impl->cursor)
- gdk_cursor_unref (impl->cursor);
+ g_object_unref (impl->cursor);
g_hash_table_destroy (impl->device_cursor);
width, height, 1);
surface = cairo_xlib_surface_create_for_bitmap (GDK_WINDOW_XDISPLAY (window),
pixmap,
- GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (window))->xscreen,
+ GDK_X11_SCREEN (GDK_WINDOW_SCREEN (window))->xscreen,
width, height);
attach_free_pixmap_handler (surface, GDK_WINDOW_DISPLAY (window), pixmap);
{
GdkWindow *window;
GdkWindowImplX11 *impl;
- GdkScreenX11 *screen_x11;
+ GdkX11Screen *x11_screen;
- screen_x11 = GDK_SCREEN_X11 (screen);
+ x11_screen = GDK_X11_SCREEN (screen);
- g_assert (screen_x11->root_window == NULL);
+ g_assert (x11_screen->root_window == NULL);
- window = screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
+ window = x11_screen->root_window = _gdk_display_create_window (gdk_screen_get_display (screen));
window->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
window->impl_window = window;
impl = GDK_WINDOW_IMPL_X11 (window->impl);
- impl->xid = screen_x11->xroot_window;
+ impl->xid = x11_screen->xroot_window;
impl->wrapper = window;
window->window_type = GDK_WINDOW_ROOT;
- window->depth = DefaultDepthOfScreen (screen_x11->xscreen);
+ window->depth = DefaultDepthOfScreen (x11_screen->xscreen);
window->x = 0;
window->y = 0;
window->abs_x = 0;
window->abs_y = 0;
- window->width = WidthOfScreen (screen_x11->xscreen);
- window->height = HeightOfScreen (screen_x11->xscreen);
+ window->width = WidthOfScreen (x11_screen->xscreen);
+ window->height = HeightOfScreen (x11_screen->xscreen);
window->viewable = TRUE;
/* see init_randr_support() in gdkscreen-x11.c */
window->event_mask = GDK_STRUCTURE_MASK;
- _gdk_window_update_size (screen_x11->root_window);
+ _gdk_window_update_size (x11_screen->root_window);
- _gdk_x11_display_add_window (screen_x11->display,
- &screen_x11->xroot_window,
- screen_x11->root_window);
+ _gdk_x11_display_add_window (x11_screen->display,
+ &x11_screen->xroot_window,
+ x11_screen->root_window);
}
static void
protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
#ifdef HAVE_XSYNC
- if (GDK_DISPLAY_X11 (display)->use_sync)
+ if (GDK_X11_DISPLAY (display)->use_sync)
protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
#endif
static void
check_leader_window_title (GdkDisplay *display)
{
- GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
if (display_x11->leader_window && !display_x11->leader_window_title_set)
{
create_focus_window (GdkDisplay *display,
XID parent)
{
- GdkDisplayX11 *display_x11;
+ GdkX11Display *display_x11;
GdkEventMask event_mask;
Display *xdisplay;
Window focus_window;
xdisplay = GDK_DISPLAY_XDISPLAY (display);
- display_x11 = GDK_DISPLAY_X11 (display);
+ display_x11 = GDK_X11_DISPLAY (display);
focus_window = XCreateSimpleWindow (xdisplay, parent,
-1, -1, 1, 1, 0,
{
GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
- GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
- if (toplevel && impl->use_synchronized_configure &&
+ if (toplevel &&
toplevel->update_counter == None &&
- GDK_DISPLAY_X11 (display)->use_sync)
+ GDK_X11_DISPLAY (display)->use_sync)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
XSyncValue value;
Atom atom;
+ XID counters[2];
XSyncIntToValue (&value, 0);
toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+ toplevel->extended_update_counter = XSyncCreateCounter (xdisplay, value);
atom = gdk_x11_get_xatom_by_name_for_display (display,
"_NET_WM_SYNC_REQUEST_COUNTER");
-
+
+ counters[0] = toplevel->update_counter;
+ counters[1] = toplevel->extended_update_counter;
XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
atom, XA_CARDINAL,
32, PropModeReplace,
- (guchar *)&toplevel->update_counter, 1);
+ (guchar *)counters, 2);
- XSyncIntToValue (&toplevel->current_counter_value, 0);
+ toplevel->current_counter_value = 0;
}
}
#endif
GdkDisplay *display = gdk_window_get_display (window);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
- GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (parent));
+ GdkX11Screen *x11_screen = GDK_X11_SCREEN (GDK_WINDOW_SCREEN (parent));
XSizeHints size_hints;
long pid;
Window leader_window;
* press events so they don't get sent to child windows.
*/
toplevel->focus_window = create_focus_window (display, xid);
- _gdk_x11_display_add_window (screen_x11->display,
+ _gdk_x11_display_add_window (x11_screen->display,
&toplevel->focus_window,
window);
}
- check_leader_window_title (screen_x11->display);
+ check_leader_window_title (x11_screen->display);
/* FIXME: Is there any point in doing this? Do any WM's pay
* attention to PSize, and even if they do, is this the
pid = getpid ();
XChangeProperty (xdisplay, xid,
- gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_PID"),
+ gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_PID"),
XA_CARDINAL, 32,
PropModeReplace,
(guchar *)&pid, 1);
- leader_window = GDK_DISPLAY_X11 (screen_x11->display)->leader_window;
+ leader_window = GDK_X11_DISPLAY (x11_screen->display)->leader_window;
if (!leader_window)
leader_window = xid;
XChangeProperty (xdisplay, xid,
- gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "WM_CLIENT_LEADER"),
+ gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "WM_CLIENT_LEADER"),
XA_WINDOW, 32, PropModeReplace,
(guchar *) &leader_window, 1);
if (toplevel->focus_window != None)
XChangeProperty (xdisplay, xid,
- gdk_x11_get_xatom_by_name_for_display (screen_x11->display, "_NET_WM_USER_TIME_WINDOW"),
+ gdk_x11_get_xatom_by_name_for_display (x11_screen->display, "_NET_WM_USER_TIME_WINDOW"),
XA_WINDOW, 32, PropModeReplace,
(guchar *) &toplevel->focus_window, 1);
if (!window->focus_on_map)
gdk_x11_window_set_user_time (window, 0);
- else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
- gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
+ else if (GDK_X11_DISPLAY (x11_screen->display)->user_time != 0)
+ gdk_x11_window_set_user_time (window, GDK_X11_DISPLAY (x11_screen->display)->user_time);
ensure_sync_counter (window);
+
+ /* Start off in a frozen state - we'll finish this when we first paint */
+ gdk_x11_window_begin_frame (window);
+}
+
+static void
+on_frame_clock_before_paint (GdkFrameClock *clock,
+ GdkWindow *window)
+{
+ gdk_x11_window_begin_frame (window);
+}
+
+static void
+on_frame_clock_after_paint (GdkFrameClock *clock,
+ GdkWindow *window)
+{
+ gdk_x11_window_end_frame (window);
}
void
gint attributes_mask)
{
GdkWindowImplX11 *impl;
- GdkScreenX11 *screen_x11;
- GdkDisplayX11 *display_x11;
+ GdkX11Screen *x11_screen;
+ GdkX11Display *display_x11;
+ GdkFrameClock *clock;
Window xparent;
Visual *xvisual;
unsigned int class;
const char *title;
- display_x11 = GDK_DISPLAY_X11 (display);
+ display_x11 = GDK_X11_DISPLAY (display);
xparent = GDK_WINDOW_XID (real_parent);
- screen_x11 = GDK_SCREEN_X11 (screen);
+ x11_screen = GDK_X11_SCREEN (screen);
impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
window->impl = GDK_WINDOW_IMPL (impl);
impl->wrapper = GDK_WINDOW (window);
- xdisplay = screen_x11->xdisplay;
+ xdisplay = x11_screen->xdisplay;
xattributes_mask = 0;
{
class = InputOutput;
- xattributes.background_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+ xattributes.background_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
- xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+ xattributes.border_pixel = BlackPixel (xdisplay, x11_screen->screen_num);
xattributes_mask |= CWBorderPixel | CWBackPixel;
if (window->guffaw_gravity)
xattributes_mask, &xattributes);
g_object_ref (window);
- _gdk_x11_display_add_window (screen_x11->display, &impl->xid, window);
+ _gdk_x11_display_add_window (x11_screen->display, &impl->xid, window);
switch (GDK_WINDOW_TYPE (window))
{
gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
GDK_WINDOW_XID (window), event_mask,
StructureNotifyMask | PropertyChangeMask);
+
+ clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
+ gdk_window_set_frame_clock (window, clock);
+ g_signal_connect (clock, "before-paint",
+ G_CALLBACK (on_frame_clock_before_paint), window);
+ g_signal_connect (clock, "after-paint",
+ G_CALLBACK (on_frame_clock_after_paint), window);
+
+ if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+ gdk_window_freeze_toplevel_updates_libgtk_only (window);
}
static GdkEventMask
* @display: the #GdkDisplay where the window handle comes from.
* @window: an XLib <type>Window</type>
*
- * Wraps a native window in a #GdkWindow.
+ * Wraps a native window in a #GdkWindow. The function will try to
+ * look up the window using gdk_x11_window_lookup_for_display() first.
+ * If it does not find it there, it will create a new window.
*
* This may fail if the window has been destroyed. If the window
* was already known to GDK, a new reference to the existing
* window, or %NULL if the window has been destroyed. The wrapper
* will be newly created, if one doesn't exist already.
*
- * Since: 3.0
+ * Since: 2.24
*/
GdkWindow *
gdk_x11_window_foreign_new_for_display (GdkDisplay *display,
GdkScreen *screen;
GdkWindow *win;
GdkWindowImplX11 *impl;
- GdkDisplayX11 *display_x11;
+ GdkX11Display *display_x11;
XWindowAttributes attrs;
Window root, parent;
Window *children = NULL;
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
- display_x11 = GDK_DISPLAY_X11 (display);
+ display_x11 = GDK_X11_DISPLAY (display);
if ((win = gdk_x11_window_lookup_for_display (display, window)) != NULL)
return g_object_ref (win);
screen = _gdk_x11_display_screen_for_xrootwin (display, root);
- win = g_object_new (GDK_TYPE_WINDOW, NULL);
+ win = _gdk_display_create_window (display);
win->impl = g_object_new (GDK_TYPE_WINDOW_IMPL_X11, NULL);
win->impl_window = win;
win->visual = gdk_x11_screen_lookup_visual (screen,
toplevel->update_counter);
toplevel->update_counter = None;
- XSyncIntToValue (&toplevel->current_counter_value, 0);
+ toplevel->current_counter_value = 0;
}
#endif
}
g_return_if_fail (GDK_IS_WINDOW (window));
- _gdk_selection_window_destroyed (window);
+ _gdk_x11_selection_window_destroyed (window);
toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel)
g_object_unref (window);
}
+static GdkDragProtocol
+gdk_x11_window_get_drag_protocol (GdkWindow *window,
+ GdkWindow **target)
+{
+ GdkDragProtocol protocol;
+ GdkDisplay *display;
+ guint version;
+ Window xid;
+
+ display = gdk_window_get_display (window);
+ xid = _gdk_x11_display_get_drag_protocol (display,
+ GDK_WINDOW_XID (window->impl_window),
+ &protocol,
+ &version);
+
+ if (target)
+ {
+ if (xid != None)
+ *target = gdk_x11_window_foreign_new_for_display (display, xid);
+ else
+ *target = NULL;
+ }
+
+ return protocol;
+}
+
static void
update_wm_hints (GdkWindow *window,
gboolean force)
wm_hints.window_group = GDK_WINDOW_XID (toplevel->group_leader);
}
else
- wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
+ wm_hints.window_group = GDK_X11_DISPLAY (display)->leader_window;
if (toplevel->urgency_hint)
wm_hints.flags |= XUrgencyHint;
++i;
}
+ if (window->state & GDK_WINDOW_STATE_ICONIFIED)
+ {
+ atoms[i] = gdk_x11_get_xatom_by_name_for_display (display,
+ "_NET_WM_STATE_HIDDEN");
+ ++i;
+ toplevel->have_hidden = TRUE;
+ }
+
if (i > 0)
{
XChangeProperty (xdisplay,
gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
{
GdkDisplay *display;
- GdkDisplayX11 *display_x11;
+ GdkX11Display *display_x11;
GdkToplevelX11 *toplevel;
GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (window->impl);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
if (WINDOW_IS_TOPLEVEL (window))
{
display = gdk_window_get_display (window);
- display_x11 = GDK_DISPLAY_X11 (display);
+ display_x11 = GDK_X11_DISPLAY (display);
toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel->user_time != 0 &&
if (unset_bg)
_gdk_x11_window_tmp_reset_bg (window, TRUE);
+
+ /* Fullscreen on current monitor is the default, no need to apply this mode
+ * when mapping a window. This also ensures that the default behavior remains
+ * consistent with pre-fullscreen mode implementation.
+ */
+ if (window->fullscreen_mode != GDK_FULLSCREEN_ON_CURRENT_MONITOR)
+ gdk_x11_window_apply_fullscreen_mode (window);
}
static void
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
{
+ /* The window isn't actually damaged, but it's parent is */
+ window_pre_damage (window);
_gdk_x11_window_move_resize_child (window,
x, y,
window->width, window->height);
if (height < 1)
height = 1;
+ window_pre_damage (window);
+
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
{
_gdk_x11_window_move_resize_child (window,
if (height < 1)
height = 1;
+ window_pre_damage (window);
+
if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
{
_gdk_x11_window_move_resize_child (window, x, y, width, height);
/**
* gdk_x11_window_move_to_current_desktop:
- * @window: a #GdkWindow
+ * @window: (type GdkX11Window): a #GdkWindow
*
* Moves the window to the correct workspace when running under a
* window manager that supports multiple workspaces, as described
move_to_current_desktop (GdkWindow *window)
{
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
- gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
+ gdk_atom_intern_static_string ("_NET_WM_DESKTOP")) &&
+ gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
+ gdk_atom_intern_static_string ("_NET_CURRENT_DESKTOP")))
{
Atom type;
gint format;
xclient.format = 32;
xclient.data.l[0] = *current_desktop;
- xclient.data.l[1] = 0;
+ xclient.data.l[1] = 1; /* source indication */
xclient.data.l[2] = 0;
xclient.data.l[3] = 0;
xclient.data.l[4] = 0;
xclient.type = ClientMessage;
xclient.window = GDK_WINDOW_XID (window);
xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
- "_NET_ACTIVE_WINDOW");
+ "_NET_ACTIVE_WINDOW");
xclient.format = 32;
xclient.data.l[0] = 1; /* requestor type; we're an app */
xclient.data.l[1] = timestamp;
XRaiseWindow (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window));
/* There is no way of knowing reliably whether we are viewable;
- * _gdk_x11_set_input_focus_safe() traps errors asynchronously.
+ * so trap errors asynchronously around the XSetInputFocus call
*/
- _gdk_x11_set_input_focus_safe (display, GDK_WINDOW_XID (window),
- RevertToParent,
- timestamp);
+ gdk_x11_display_error_trap_push (display);
+ XSetInputFocus (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (window),
+ RevertToParent,
+ timestamp);
+ gdk_x11_display_error_trap_pop_ignored (display);
}
}
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
xclient.data.l[1] = gdk_x11_atom_to_xatom_for_display (display, state1);
xclient.data.l[2] = gdk_x11_atom_to_xatom_for_display (display, state2);
- xclient.data.l[3] = 0;
+ xclient.data.l[3] = 1; /* source indication */
xclient.data.l[4] = 0;
XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
if (utf8_is_latin1 (utf8_str))
{
prop_type = XA_STRING;
- prop_text = gdk_utf8_to_string_target (utf8_str);
+ prop_text = _gdk_x11_display_utf8_to_string_target (display, utf8_str);
prop_length = prop_text ? strlen (prop_text) : 0;
prop_format = 8;
is_compound_text = FALSE;
else
{
GdkAtom gdk_type;
-
- gdk_utf8_to_compound_text_for_display (display,
- utf8_str, &gdk_type, &prop_format,
- (guchar **)&prop_text, &prop_length);
+
+ gdk_x11_display_utf8_to_compound_text (display,
+ utf8_str, &gdk_type, &prop_format,
+ (guchar **)&prop_text, &prop_length);
prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
is_compound_text = TRUE;
}
prop_length);
if (is_compound_text)
- gdk_free_compound_text ((guchar *)prop_text);
+ gdk_x11_free_compound_text ((guchar *)prop_text);
else
g_free (prop_text);
}
{
_gdk_x11_cursor_update_theme (cursor);
g_hash_table_replace (impl->device_cursor,
- device, gdk_cursor_ref (cursor));
+ device, g_object_ref (cursor));
}
if (!GDK_WINDOW_DESTROYED (window))
xwindow = GDK_WINDOW_XID (window);
/* first try: use _NET_FRAME_EXTENTS */
- if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
+ if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
+ gdk_atom_intern_static_string ("_NET_FRAME_EXTENTS")) &&
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
gdk_x11_get_xatom_by_name_for_display (display,
"_NET_FRAME_EXTENTS"),
0, G_MAXLONG, False, XA_CARDINAL, &type_return,
/* use NETWM_VIRTUAL_ROOTS if available */
root = GDK_WINDOW_XROOTWIN (window);
- if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
+ if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
+ gdk_atom_intern_static_string ("_NET_VIRTUAL_ROOTS")) &&
+ XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
gdk_x11_get_xatom_by_name_for_display (display,
"_NET_VIRTUAL_ROOTS"),
0, G_MAXLONG, False, XA_WINDOW, &type_return,
if (!GDK_WINDOW_DESTROYED (window))
{
- GdkDisplayX11 *display_x11;
+ GdkX11Display *display_x11;
if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
xevent_mask = StructureNotifyMask | PropertyChangeMask;
- display_x11 = GDK_DISPLAY_X11 (gdk_window_get_display (window));
+ display_x11 = GDK_X11_DISPLAY (gdk_window_get_display (window));
gdk_x11_event_source_select_events ((GdkEventSource *) display_x11->event_source,
GDK_WINDOW_XID (window), event_mask,
xevent_mask);
/**
* gdk_x11_window_set_user_time:
- * @window: A toplevel #GdkWindow
+ * @window: (type GdkX11Window): A toplevel #GdkWindow
* @timestamp: An XServer timestamp to which the property should be set
*
* The application can use this call to update the _NET_WM_USER_TIME
guint32 timestamp)
{
GdkDisplay *display;
- GdkDisplayX11 *display_x11;
+ GdkX11Display *display_x11;
GdkToplevelX11 *toplevel;
glong timestamp_long = (glong)timestamp;
Window xid;
return;
display = gdk_window_get_display (window);
- display_x11 = GDK_DISPLAY_X11 (display);
+ display_x11 = GDK_X11_DISPLAY (display);
toplevel = _gdk_x11_window_get_toplevel (window);
if (!toplevel)
toplevel->user_time = timestamp_long;
}
+/**
+ * gdk_x11_window_set_utf8_property:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @name: Property name, will be interned as an X atom
+ * @value: (allow-none): Property value, or %NULL to delete
+ *
+ * This function modifies or removes an arbitrary X11 window
+ * property of type UTF8_STRING. If the given @window is
+ * not a toplevel window, it is ignored.
+ *
+ * Since: 3.4
+ */
+void
+gdk_x11_window_set_utf8_property (GdkWindow *window,
+ const gchar *name,
+ const gchar *value)
+{
+ GdkDisplay *display;
+
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
+
+ display = gdk_window_get_display (window);
+
+ if (value != NULL)
+ {
+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, name),
+ gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
+ PropModeReplace, (guchar *)value, strlen (value));
+ }
+ else
+ {
+ XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, name));
+ }
+}
+
+/**
+ * gdk_x11_window_set_hide_titlebar_when_maximized:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @hide_titlebar_when_maximized: whether to hide the titlebar when
+ * maximized
+ *
+ * Set a hint for the window manager, requesting that the titlebar
+ * should be hidden when the window is maximized.
+ *
+ * Note that this property is automatically updated by GTK+, so this
+ * function should only be used by applications which do not use GTK+
+ * to create toplevel windows.
+ *
+ * Since: 3.4
+ */
+void
+gdk_x11_window_set_hide_titlebar_when_maximized (GdkWindow *window,
+ gboolean hide_titlebar_when_maximized)
+{
+ GdkDisplay *display;
+
+ if (!WINDOW_IS_TOPLEVEL (window))
+ return;
+
+ display = gdk_window_get_display (window);
+
+ if (hide_titlebar_when_maximized)
+ {
+ guint32 hide = 1;
+ XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"),
+ XA_CARDINAL, 32,
+ PropModeReplace, (guchar *)&hide, 1);
+ }
+ else
+ {
+ XDeleteProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XID (window),
+ gdk_x11_get_xatom_by_name_for_display (display, "_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED"));
+ }
+}
+
+/**
+ * gdk_x11_window_set_theme_variant:
+ * @window: (type GdkX11Window): a #GdkWindow
+ * @variant: the theme variant to export
+ *
+ * GTK+ applications can request a dark theme variant. In order to
+ * make other applications - namely window managers using GTK+ for
+ * themeing - aware of this choice, GTK+ uses this function to
+ * export the requested theme variant as _GTK_THEME_VARIANT property
+ * on toplevel windows.
+ *
+ * Note that this property is automatically updated by GTK+, so this
+ * function should only be used by applications which do not use GTK+
+ * to create toplevel windows.
+ *
+ * Since: 3.2
+ */
+void
+gdk_x11_window_set_theme_variant (GdkWindow *window,
+ char *variant)
+{
+ return gdk_x11_window_set_utf8_property (window, "_GTK_THEME_VARIANT", variant);
+}
+
#define GDK_SELECTION_MAX_SIZE(display) \
MIN(262144, \
XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0 \
gdk_synthesize_window_state (window,
0,
GDK_WINDOW_STATE_ICONIFIED);
+ gdk_wmspec_change_state (TRUE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+ GDK_NONE);
}
}
if (GDK_WINDOW_IS_MAPPED (window))
{
gdk_window_show (window);
+ gdk_wmspec_change_state (FALSE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+ GDK_NONE);
}
else
{
gdk_synthesize_window_state (window,
GDK_WINDOW_STATE_ICONIFIED,
0);
+ gdk_wmspec_change_state (FALSE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_HIDDEN"),
+ GDK_NONE);
}
}
}
static void
-gdk_x11_window_fullscreen (GdkWindow *window)
+gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
{
if (GDK_WINDOW_DESTROYED (window) ||
!WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
return;
+ /* _NET_WM_FULLSCREEN_MONITORS gives an indication to the window manager as
+ * to which monitors so span across when the window is fullscreen, but it's
+ * not a state in itself so this would have no effect if the window is not
+ * mapped.
+ */
+
if (GDK_WINDOW_IS_MAPPED (window))
- gdk_wmspec_change_state (TRUE, window,
- gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
- GDK_NONE);
+ {
+ XClientMessageEvent xclient;
+ gint gdk_monitors[4];
+ gint i;
+ memset (&xclient, 0, sizeof (xclient));
+ xclient.type = ClientMessage;
+ xclient.window = GDK_WINDOW_XID (window);
+ xclient.display = GDK_WINDOW_XDISPLAY (window);
+ xclient.format = 32;
+
+ switch (window->fullscreen_mode)
+ {
+ case GDK_FULLSCREEN_ON_CURRENT_MONITOR:
+
+ /* FIXME: This is not part of the EWMH spec!
+ *
+ * There is no documented mechanism to remove the property
+ * _NET_WM_FULLSCREEN_MONITORS once set, so we use use a set of
+ * invalid, largest possible value.
+ *
+ * When given values larger than actual possible monitor values, most
+ * window managers who support the _NET_WM_FULLSCREEN_MONITORS spec
+ * will simply unset _NET_WM_FULLSCREEN_MONITORS and revert to their
+ * default behavior.
+ *
+ * Successfully tested on mutter/metacity, kwin, compiz and xfwm4.
+ *
+ * Note, this (non documented) mechanism is unlikely to be an issue
+ * as it's used only for transitionning back from "all monitors" to
+ * "current monitor" mode.
+ *
+ * Applications who don't change the default mode won't trigger this
+ * mechanism.
+ */
+ for (i = 0; i < 4; ++i)
+ xclient.data.l[i] = G_MAXLONG;
+
+ break;
+
+ case GDK_FULLSCREEN_ON_ALL_MONITORS:
+
+ _gdk_x11_screen_get_edge_monitors (GDK_WINDOW_SCREEN (window),
+ &gdk_monitors[0],
+ &gdk_monitors[1],
+ &gdk_monitors[2],
+ &gdk_monitors[3]);
+ /* Translate all 4 monitors from the GDK set into XINERAMA indices */
+ for (i = 0; i < 4; ++i)
+ {
+ xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
+ gdk_monitors[i]);
+ /* Sanity check, if XINERAMA is not available, we could have invalid
+ * negative values for the XINERAMA indices.
+ */
+ if (xclient.data.l[i] < 0)
+ {
+ g_warning ("gdk_x11_window_apply_fullscreen_mode: Invalid XINERAMA monitor index");
+ return;
+ }
+ }
+ break;
+
+ default:
+ g_warning ("gdk_x11_window_apply_fullscreen_mode: Unhandled fullscreen mode %d",
+ window->fullscreen_mode);
+ return;
+ }
+
+ /* Send fullscreen monitors client message */
+ xclient.data.l[4] = 1; /* source indication */
+ xclient.message_type = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ "_NET_WM_FULLSCREEN_MONITORS");
+ XSendEvent (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XROOTWIN (window), False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ (XEvent *)&xclient);
+ }
+}
+
+static void
+gdk_x11_window_fullscreen (GdkWindow *window)
+{
+ if (GDK_WINDOW_DESTROYED (window) ||
+ !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
+ return;
+
+ if (GDK_WINDOW_IS_MAPPED (window))
+ {
+ gdk_wmspec_change_state (TRUE, window,
+ gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
+ GDK_NONE);
+ /* Actual XRandR layout may have change since we computed the fullscreen
+ * monitors in GDK_FULLSCREEN_ON_ALL_MONITORS mode.
+ */
+ if (window->fullscreen_mode == GDK_FULLSCREEN_ON_ALL_MONITORS)
+ gdk_x11_window_apply_fullscreen_mode (window);
+ }
else
gdk_synthesize_window_state (window,
0,
shape = NULL;
rn = 0;
- xrl = XShapeGetRectangles (xdisplay,
- window,
- shape_type, &rn, &ord);
+ /* Note that XShapeGetRectangles returns NULL in two situations:
+ * - the server doesn't support the SHAPE extension
+ * - the shape is empty
+ *
+ * Since we can't discriminate these here, we always return
+ * an empty shape. It is the callers responsibility to check
+ * whether the server supports the SHAPE extensions beforehand.
+ */
+ xrl = XShapeGetRectangles (xdisplay, window, shape_type, &rn, &ord);
- if (xrl == NULL || rn == 0)
+ if (rn == 0)
return cairo_region_create (); /* Empty */
if (ord != YXBanded)
{
/* This really shouldn't happen with any xserver, as they
- generally convert regions to YXBanded internally */
+ * generally convert regions to YXBanded internally
+ */
g_warning ("non YXBanded shape masks not supported");
XFree (xrl);
return NULL;
rl[i].height = xrl[i].height;
}
XFree (xrl);
-
+
shape = cairo_region_create_rectangles (rl, rn);
g_free (rl);
-
+
return shape;
}
{
#if defined(ShapeInput)
if (!GDK_WINDOW_DESTROYED (window) &&
- gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+ gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
return _gdk_x11_xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
GDK_WINDOW_XID (window),
ShapeInput);
return TRUE;
}
+/* From the WM spec */
+#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
+#define _NET_WM_MOVERESIZE_SIZE_TOP 1
+#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
+#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
+#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
+#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
+#define _NET_WM_MOVERESIZE_MOVE 8 /* movement only */
+#define _NET_WM_MOVERESIZE_SIZE_KEYBOARD 9 /* size via keyboard */
+#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10 /* move via keyboard */
+#define _NET_WM_MOVERESIZE_CANCEL 11 /* cancel operation */
+
static void
-wmspec_moveresize (GdkWindow *window,
- gint direction,
- gint root_x,
- gint root_y,
- guint32 timestamp)
+wmspec_send_message (GdkDisplay *display,
+ GdkWindow *window,
+ gint root_x,
+ gint root_y,
+ gint action,
+ gint button)
{
- GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
-
XClientMessageEvent xclient;
- /* Release passive grab */
- gdk_display_pointer_ungrab (display, timestamp);
-
memset (&xclient, 0, sizeof (xclient));
xclient.type = ClientMessage;
xclient.window = GDK_WINDOW_XID (window);
xclient.format = 32;
xclient.data.l[0] = root_x;
xclient.data.l[1] = root_y;
- xclient.data.l[2] = direction;
- xclient.data.l[3] = 0;
- xclient.data.l[4] = 0;
-
+ xclient.data.l[2] = action;
+ xclient.data.l[3] = button;
+ xclient.data.l[4] = 1; /* source indication */
+
XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- (XEvent *)&xclient);
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ (XEvent *)&xclient);
}
-typedef struct _MoveResizeData MoveResizeData;
+static void
+handle_wmspec_button_release (GdkDisplay *display,
+ XEvent *xevent)
+{
+ GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+ GdkWindow *window;
-struct _MoveResizeData
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+ XIEvent *xiev = (XIEvent *) xevent->xcookie.data;
+ XIDeviceEvent *xidev = (XIDeviceEvent *) xiev;
+
+ if (xevent->xany.type == GenericEvent)
+ window = gdk_x11_window_lookup_for_display (display, xidev->event);
+ else
+#endif
+ window = gdk_x11_window_lookup_for_display (display, xevent->xany.window);
+
+ if (display_x11->wm_moveresize_button != 0 && window != NULL)
+ {
+ if ((xevent->xany.type == ButtonRelease &&
+ xevent->xbutton.button == display_x11->wm_moveresize_button)
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+ ||
+ (xevent->xany.type == GenericEvent &&
+ xiev->evtype == XI_ButtonRelease &&
+ xidev->detail == display_x11->wm_moveresize_button)
+#endif
+ )
+ {
+ display_x11->wm_moveresize_button = 0;
+ wmspec_send_message (display, window, 0, 0, _NET_WM_MOVERESIZE_CANCEL, 0);
+ }
+ }
+}
+
+static void
+wmspec_moveresize (GdkWindow *window,
+ gint direction,
+ GdkDevice *device,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
{
- GdkDisplay *display;
-
- GdkWindow *moveresize_window;
- GdkWindow *moveresize_emulation_window;
- gboolean is_resize;
- GdkWindowEdge resize_edge;
- gint moveresize_button;
- gint moveresize_x;
- gint moveresize_y;
- gint moveresize_orig_x;
- gint moveresize_orig_y;
- gint moveresize_orig_width;
- gint moveresize_orig_height;
- GdkWindowHints moveresize_geom_mask;
- GdkGeometry moveresize_geometry;
- Time moveresize_process_time;
- XEvent *moveresize_pending_event;
-};
+ GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
-/* From the WM spec */
-#define _NET_WM_MOVERESIZE_SIZE_TOPLEFT 0
-#define _NET_WM_MOVERESIZE_SIZE_TOP 1
-#define _NET_WM_MOVERESIZE_SIZE_TOPRIGHT 2
-#define _NET_WM_MOVERESIZE_SIZE_RIGHT 3
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMRIGHT 4
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOM 5
-#define _NET_WM_MOVERESIZE_SIZE_BOTTOMLEFT 6
-#define _NET_WM_MOVERESIZE_SIZE_LEFT 7
-#define _NET_WM_MOVERESIZE_MOVE 8
+ /* Release passive grab */
+ gdk_device_ungrab (device, timestamp);
+ GDK_X11_DISPLAY (display)->wm_moveresize_button = button;
+
+ wmspec_send_message (display, window, root_x, root_y, direction, button);
+}
static void
wmspec_resize_drag (GdkWindow *window,
GdkWindowEdge edge,
+ GdkDevice *device,
gint button,
gint root_x,
gint root_y,
return;
}
- wmspec_moveresize (window, direction, root_x, root_y, timestamp);
+ wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
}
+typedef struct _MoveResizeData MoveResizeData;
+
+struct _MoveResizeData
+{
+ GdkDisplay *display;
+
+ GdkWindow *moveresize_window;
+ GdkWindow *moveresize_emulation_window;
+ gboolean is_resize;
+ GdkWindowEdge resize_edge;
+ GdkDevice *device;
+ gint moveresize_button;
+ gint moveresize_x;
+ gint moveresize_y;
+ gint moveresize_orig_x;
+ gint moveresize_orig_y;
+ gint moveresize_orig_width;
+ gint moveresize_orig_height;
+ GdkWindowHints moveresize_geom_mask;
+ GdkGeometry moveresize_geometry;
+ Time moveresize_process_time;
+ XEvent *moveresize_pending_event;
+};
+
static MoveResizeData *
get_move_resize_data (GdkDisplay *display,
gboolean create)
MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
if (!mv_resize || !mv_resize->moveresize_window)
- return FALSE;
+ {
+ handle_wmspec_button_release (display, event);
+ return FALSE;
+ }
button_mask = GDK_BUTTON1_MASK << (mv_resize->moveresize_button - 1);
if (event->xbutton.button == mv_resize->moveresize_button)
finish_drag (mv_resize);
break;
+
+#if defined (HAVE_XGENERICEVENTS) && defined (XINPUT_2)
+ case GenericEvent:
+ {
+ /* we just assume this is an XI2 event */
+ XIEvent *ev = (XIEvent *) event->xcookie.data;
+ XIDeviceEvent *xev = (XIDeviceEvent *)ev;
+ gint state;
+ switch (ev->evtype)
+ {
+ case XI_Motion:
+ update_pos (mv_resize, xev->root_x, xev->root_y);
+ state = _gdk_x11_device_xi2_translate_state (&xev->mods, &xev->buttons, &xev->group);
+ if ((state & button_mask) == 0)
+ finish_drag (mv_resize);
+ break;
+
+ case XI_ButtonRelease:
+ update_pos (mv_resize, xev->root_x, xev->root_y);
+ if (xev->detail == mv_resize->moveresize_button)
+ finish_drag (mv_resize);
+ break;
+ }
+ }
+ break;
+#endif
+
}
return TRUE;
}
gdk_window_show (mv_resize->moveresize_emulation_window);
- status = gdk_pointer_grab (mv_resize->moveresize_emulation_window,
- FALSE,
- GDK_BUTTON_RELEASE_MASK |
- GDK_POINTER_MOTION_MASK,
- NULL,
- NULL,
- timestamp);
+ status = gdk_device_grab (mv_resize->device,
+ mv_resize->moveresize_emulation_window,
+ GDK_OWNERSHIP_NONE,
+ FALSE,
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK,
+ NULL,
+ timestamp);
if (status != GDK_GRAB_SUCCESS)
{
static void
emulate_resize_drag (GdkWindow *window,
GdkWindowEdge edge,
+ GdkDevice *device,
gint button,
gint root_x,
gint root_y,
mv_resize->is_resize = TRUE;
mv_resize->moveresize_button = button;
mv_resize->resize_edge = edge;
+ mv_resize->device = device;
mv_resize->moveresize_x = root_x;
mv_resize->moveresize_y = root_y;
mv_resize->moveresize_window = g_object_ref (window);
static void
emulate_move_drag (GdkWindow *window,
+ GdkDevice *device,
gint button,
gint root_x,
gint root_y,
MoveResizeData *mv_resize = get_move_resize_data (GDK_WINDOW_DISPLAY (window), TRUE);
mv_resize->is_resize = FALSE;
+ mv_resize->device = device;
mv_resize->moveresize_button = button;
mv_resize->moveresize_x = root_x;
mv_resize->moveresize_y = root_y;
static void
gdk_x11_window_begin_resize_drag (GdkWindow *window,
- GdkWindowEdge edge,
- gint button,
- gint root_x,
- gint root_y,
- guint32 timestamp)
+ GdkWindowEdge edge,
+ GdkDevice *device,
+ gint button,
+ gint root_x,
+ gint root_y,
+ guint32 timestamp)
{
if (GDK_WINDOW_DESTROYED (window) ||
!WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
- wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
+ wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
else
- emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
+ emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
}
static void
gdk_x11_window_begin_move_drag (GdkWindow *window,
+ GdkDevice *device,
gint button,
gint root_x,
gint root_y,
if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
- wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
- timestamp);
+ wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE,
+ device, button, root_x, root_y, timestamp);
else
- emulate_move_drag (window, button, root_x, root_y, timestamp);
+ emulate_move_drag (window, device, button, root_x, root_y, timestamp);
}
static void
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
if (toplevel && toplevel->update_counter != None &&
- GDK_DISPLAY_X11 (display)->use_sync &&
- !XSyncValueIsZero (toplevel->current_counter_value))
+ GDK_X11_DISPLAY (display)->use_sync &&
+ toplevel->configure_counter_value != 0)
{
- XSyncSetCounter (GDK_WINDOW_XDISPLAY (window),
- toplevel->update_counter,
- toplevel->current_counter_value);
-
- XSyncIntToValue (&toplevel->current_counter_value, 0);
+ set_sync_counter (GDK_WINDOW_XDISPLAY (window),
+ toplevel->update_counter,
+ toplevel->configure_counter_value);
+
+ toplevel->current_counter_value = toplevel->configure_counter_value;
+ if ((toplevel->current_counter_value % 2) == 1)
+ toplevel->current_counter_value += 1;
+
+ toplevel->configure_counter_value = 0;
+
+ set_sync_counter (GDK_WINDOW_XDISPLAY (window),
+ toplevel->extended_update_counter,
+ toplevel->current_counter_value);
}
}
#endif
display = GDK_WINDOW_DISPLAY (window);
#ifdef HAVE_XKB
- if (GDK_DISPLAY_X11 (display)->use_xkb)
+ if (GDK_X11_DISPLAY (display)->use_xkb)
{
XkbBell (GDK_DISPLAY_XDISPLAY (display),
GDK_WINDOW_XID (window),
void
_gdk_x11_display_after_process_all_updates (GdkDisplay *display)
{
+ /* Sync after all drawing, otherwise the client can get "ahead" of
+ the server rendering during animations, such that we fill up
+ the Xserver pipes with sync rendering ops not letting other
+ clients (including the VM) do anything. */
+ XSync (GDK_DISPLAY_XDISPLAY (display), FALSE);
}
static Bool
/**
* gdk_x11_get_server_time:
- * @window: a #GdkWindow, used for communication with the server.
- * The window must have GDK_PROPERTY_CHANGE_MASK in its
- * events mask or a hang will result.
+ * @window: (type GdkX11Window): a #GdkWindow, used for communication
+ * with the server. The window must have
+ * GDK_PROPERTY_CHANGE_MASK in its events mask or a hang will
+ * result.
*
* Routine to get the current X server time stamp.
*
/**
* gdk_x11_window_get_xid:
- * @window: a native #GdkWindow.
+ * @window: (type GdkX11Window): a native #GdkWindow.
*
* Returns the X resource (window) belonging to a #GdkWindow.
*
return GDK_WINDOW_IMPL_X11 (window->impl)->xid;
}
-extern GdkDragContext * _gdk_x11_window_drag_begin (GdkWindow *window,
- GdkDevice *device,
- GList *targets);
-
static void
gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
{
impl_class->maximize = gdk_x11_window_maximize;
impl_class->unmaximize = gdk_x11_window_unmaximize;
impl_class->fullscreen = gdk_x11_window_fullscreen;
+ impl_class->apply_fullscreen_mode = gdk_x11_window_apply_fullscreen_mode;
impl_class->unfullscreen = gdk_x11_window_unfullscreen;
impl_class->set_keep_above = gdk_x11_window_set_keep_above;
impl_class->set_keep_below = gdk_x11_window_set_keep_below;
impl_class->set_opacity = gdk_x11_window_set_opacity;
impl_class->set_composited = gdk_x11_window_set_composited;
impl_class->destroy_notify = gdk_x11_window_destroy_notify;
+ impl_class->get_drag_protocol = gdk_x11_window_get_drag_protocol;
impl_class->register_dnd = _gdk_x11_window_register_dnd;
impl_class->drag_begin = _gdk_x11_window_drag_begin;
impl_class->process_updates_recurse = gdk_x11_window_process_updates_recurse;