* 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/>.
*/
/*
(( 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 *
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,
if (toplevel && impl->use_synchronized_configure &&
toplevel->update_counter == None &&
- GDK_DISPLAY_X11 (display)->use_sync)
+ GDK_X11_DISPLAY (display)->use_sync)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
XSyncValue value;
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);
}
gint attributes_mask)
{
GdkWindowImplX11 *impl;
- GdkScreenX11 *screen_x11;
- GdkDisplayX11 *display_x11;
+ GdkX11Screen *x11_screen;
+ GdkX11Display *display_x11;
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))
{
* @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,
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;
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 &&
/**
* 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
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))
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 \
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 gboolean
+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);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+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)
GdkDisplay *display = gdk_x11_lookup_xdisplay (event->xany.display);
MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+ if (handle_wmspec_button_release (display, event))
+ return TRUE;
+
if (!mv_resize || !mv_resize->moveresize_window)
return FALSE;
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;
}
XEvent *tmp_event;
MoveResizeData *mv_resize = get_move_resize_data (display, FALSE);
+ GDK_X11_DISPLAY (display)->wm_moveresize_button = 0;
+
if (!mv_resize || window != mv_resize->moveresize_window)
return FALSE;
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 &&
+ GDK_X11_DISPLAY (display)->use_sync &&
!XSyncValueIsZero (toplevel->current_counter_value))
{
XSyncSetCounter (GDK_WINDOW_XDISPLAY (window),
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),
/**
* 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.
*
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;