summaryrefslogtreecommitdiff
path: root/gdk/x11/gdkwindow-x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/x11/gdkwindow-x11.c')
-rw-r--r--gdk/x11/gdkwindow-x11.c426
1 files changed, 253 insertions, 173 deletions
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 92a64fb47b..1eedd43940 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -39,17 +39,19 @@
#include <unistd.h>
#include "gdk.h"
+#include "gdkx.h"
#include "gdkwindow.h"
#include "gdkwindowimpl.h"
#include "gdkasync.h"
-#include "gdkinputprivate.h"
#include "gdkdisplay-x11.h"
#include "gdkprivate-x11.h"
#include "gdkregion.h"
#include "gdkinternals.h"
#include "MwmUtil.h"
#include "gdkwindow-x11.h"
+#include "gdkdeviceprivate.h"
+#include "gdkeventsource.h"
#include "gdkalias.h"
#include <stdlib.h>
@@ -146,6 +148,8 @@ 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);
}
GdkToplevelX11 *
@@ -210,6 +214,8 @@ gdk_window_impl_x11_finalize (GObject *object)
if (window_impl->cursor)
gdk_cursor_unref (window_impl->cursor);
+ g_hash_table_destroy (window_impl->device_cursor);
+
G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
}
@@ -513,18 +519,31 @@ check_leader_window_title (GdkDisplay *display)
}
static Window
-create_focus_window (Display *xdisplay,
- XID parent)
+create_focus_window (GdkDisplay *display,
+ XID parent)
{
- Window focus_window = XCreateSimpleWindow (xdisplay, parent,
- -1, -1, 1, 1, 0,
- 0, 0);
-
+ GdkDisplayX11 *display_x11;
+ GdkEventMask event_mask;
+ Display *xdisplay;
+ Window focus_window;
+
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
+ display_x11 = GDK_DISPLAY_X11 (display);
+
+ focus_window = XCreateSimpleWindow (xdisplay, parent,
+ -1, -1, 1, 1, 0,
+ 0, 0);
+
/* FIXME: probably better to actually track the requested event mask for the toplevel
*/
- XSelectInput (xdisplay, focus_window,
- KeyPressMask | KeyReleaseMask | FocusChangeMask);
-
+ event_mask = (GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_FOCUS_CHANGE_MASK);
+
+ gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+ focus_window,
+ event_mask, 0);
+
XMapWindow (xdisplay, focus_window);
return focus_window;
@@ -573,6 +592,7 @@ setup_toplevel_window (GdkWindow *window,
{
GdkWindowObject *obj = (GdkWindowObject *)window;
GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+ GdkDisplay *display = gdk_drawable_get_display (window);
Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
XID xid = GDK_WINDOW_XID (window);
XID xparent = GDK_WINDOW_XID (parent);
@@ -591,7 +611,7 @@ setup_toplevel_window (GdkWindow *window,
/* The focus window is off the visible area, and serves to receive key
* press events so they don't get sent to child windows.
*/
- toplevel->focus_window = create_focus_window (xdisplay, xid);
+ toplevel->focus_window = create_focus_window (display, xid);
_gdk_xid_table_insert (screen_x11->display, &toplevel->focus_window, window);
}
@@ -652,6 +672,7 @@ _gdk_window_impl_new (GdkWindow *window,
GdkWindowImplX11 *impl;
GdkDrawableImplX11 *draw_impl;
GdkScreenX11 *screen_x11;
+ GdkDisplayX11 *display_x11;
Window xparent;
Visual *xvisual;
@@ -664,12 +685,12 @@ _gdk_window_impl_new (GdkWindow *window,
unsigned int class;
const char *title;
- int i;
private = (GdkWindowObject *) window;
screen_x11 = GDK_SCREEN_X11 (screen);
xparent = GDK_WINDOW_XID (real_parent);
+ display_x11 = GDK_DISPLAY_X11 (GDK_SCREEN_DISPLAY (screen));
impl = g_object_new (_gdk_window_impl_get_type (), NULL);
private->impl = (GdkDrawable *)impl;
@@ -683,15 +704,6 @@ _gdk_window_impl_new (GdkWindow *window,
xvisual = ((GdkVisualPrivate*) visual)->xvisual;
- xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
- for (i = 0; i < _gdk_nenvent_masks; i++)
- {
- if (event_mask & (1 << (i + 1)))
- xattributes.event_mask |= _gdk_event_mask_table[i];
- }
- if (xattributes.event_mask)
- xattributes_mask |= CWEventMask;
-
if (attributes_mask & GDK_WA_NOREDIR)
{
xattributes.override_redirect =
@@ -837,6 +849,10 @@ _gdk_window_impl_new (GdkWindow *window,
if (attributes_mask & GDK_WA_TYPE_HINT)
gdk_window_set_type_hint (window, attributes->type_hint);
+
+ gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+ GDK_WINDOW_XWINDOW (window), event_mask,
+ StructureNotifyMask | PropertyChangeMask);
}
static GdkEventMask
@@ -2647,41 +2663,30 @@ gdk_window_x11_set_back_pixmap (GdkWindow *window,
}
static void
-gdk_window_x11_set_cursor (GdkWindow *window,
- GdkCursor *cursor)
+gdk_window_x11_set_device_cursor (GdkWindow *window,
+ GdkDevice *device,
+ GdkCursor *cursor)
{
GdkWindowObject *private;
GdkWindowImplX11 *impl;
- GdkCursorPrivate *cursor_private;
- Cursor xcursor;
-
- private = (GdkWindowObject *)window;
- impl = GDK_WINDOW_IMPL_X11 (private->impl);
- cursor_private = (GdkCursorPrivate*) cursor;
- if (impl->cursor)
- {
- gdk_cursor_unref (impl->cursor);
- impl->cursor = NULL;
- }
+ g_return_if_fail (GDK_IS_WINDOW (window));
+ g_return_if_fail (GDK_IS_DEVICE (device));
+
+ private = (GdkWindowObject *) window;
+ impl = GDK_WINDOW_IMPL_X11 (private->impl);
if (!cursor)
- xcursor = None;
+ g_hash_table_remove (impl->device_cursor, device);
else
{
_gdk_x11_cursor_update_theme (cursor);
- xcursor = cursor_private->xcursor;
+ g_hash_table_replace (impl->device_cursor,
+ device, gdk_cursor_ref (cursor));
}
-
+
if (!GDK_WINDOW_DESTROYED (window))
- {
- XDefineCursor (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- xcursor);
-
- if (cursor)
- impl->cursor = gdk_cursor_ref (cursor);
- }
+ GDK_DEVICE_GET_CLASS (device)->set_window_cursor (device, window, cursor);
}
GdkCursor *
@@ -3008,106 +3013,112 @@ gdk_window_get_frame_extents (GdkWindow *window,
}
void
-_gdk_windowing_get_pointer (GdkDisplay *display,
- GdkScreen **screen,
- gint *x,
- gint *y,
- GdkModifierType *mask)
+_gdk_windowing_get_device_state (GdkDisplay *display,
+ GdkDevice *device,
+ GdkScreen **screen,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
{
GdkScreen *default_screen;
- Display *xdisplay;
- Window xwindow;
- Window root = None;
- Window child;
- int rootx, rooty;
- int winx;
- int winy;
- unsigned int xmask;
if (display->closed)
return;
default_screen = gdk_display_get_default_screen (display);
- xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
- xwindow = GDK_SCREEN_XROOTWIN (default_screen);
-
- if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+
+ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
{
- XQueryPointer (xdisplay, xwindow,
- &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
- }
- else
+ GdkWindow *root;
+
+ GDK_DEVICE_GET_CLASS (device)->query_state (device,
+ gdk_screen_get_root_window (default_screen),
+ &root, NULL,
+ x, y,
+ NULL, NULL,
+ mask);
+ *screen = gdk_drawable_get_screen (root);
+ }
+ else
{
XSetWindowAttributes attributes;
- Window w;
-
- w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0,
- CopyFromParent, InputOnly, CopyFromParent,
+ Display *xdisplay;
+ Window xwindow, w, root, child;
+ int rootx, rooty, winx, winy;
+ unsigned int xmask;
+
+ /* FIXME: untrusted clients not multidevice-safe */
+
+ xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
+ xwindow = GDK_SCREEN_XROOTWIN (default_screen);
+
+ w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0,
+ CopyFromParent, InputOnly, CopyFromParent,
0, &attributes);
- XQueryPointer (xdisplay, w,
+ XQueryPointer (xdisplay, w,
&root, &child, &rootx, &rooty, &winx, &winy, &xmask);
XDestroyWindow (xdisplay, w);
+
+ if (root != None)
+ {
+ GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
+ *screen = gdk_drawable_get_screen (gdk_root);
+ }
+
+ *x = rootx;
+ *y = rooty;
+ *mask = xmask;
}
-
- if (root != None)
- {
- GdkWindow *gdk_root = gdk_window_lookup_for_display (display, root);
- *screen = gdk_drawable_get_screen (gdk_root);
- }
-
- *x = rootx;
- *y = rooty;
- *mask = xmask;
}
static gboolean
-gdk_window_x11_get_pointer (GdkWindow *window,
- gint *x,
- gint *y,
- GdkModifierType *mask)
+gdk_window_x11_get_device_state (GdkWindow *window,
+ GdkDevice *device,
+ gint *x,
+ gint *y,
+ GdkModifierType *mask)
{
GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
gboolean return_val;
- Window root;
- Window child;
- int rootx, rooty;
- int winx = 0;
- int winy = 0;
- unsigned int xmask = 0;
g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
-
return_val = TRUE;
+
if (!GDK_WINDOW_DESTROYED (window))
{
if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
{
- if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
- {
- if (child)
- return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child) != NULL;
- }
+ GdkWindow *child;
+
+ GDK_DEVICE_GET_CLASS (device)->query_state (device, window,
+ NULL, &child,
+ NULL, NULL,
+ x, y, mask);
+ return_val = (child != NULL);
}
else
{
GdkScreen *screen;
int originx, originy;
- _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen,
- &rootx, &rooty, &xmask);
+ int rootx, rooty;
+ int winx = 0;
+ int winy = 0;
+ unsigned int xmask = 0;
+
+ _gdk_windowing_get_device_state (gdk_drawable_get_display (window), device,
+ &screen, &rootx, &rooty, &xmask);
gdk_window_get_origin (window, &originx, &originy);
winx = rootx - originx;
winy = rooty - originy;
+
+ *x = winx;
+ *y = winy;
+ *mask = xmask;
}
}
- *x = winx;
- *y = winy;
- *mask = xmask;
-
return return_val;
}
@@ -3131,6 +3142,8 @@ gdk_window_x11_get_pointer (GdkWindow *window,
* for the color picker in the #GtkColorSelectionDialog.
*
* Since: 2.8
+ *
+ * Deprecated: 3.0. Use gdk_display_warp_device() instead.
*/
void
gdk_display_warp_pointer (GdkDisplay *display,
@@ -3138,37 +3151,64 @@ gdk_display_warp_pointer (GdkDisplay *display,
gint x,
gint y)
{
- Display *xdisplay;
- Window dest;
+ GdkDevice *device;
- xdisplay = GDK_DISPLAY_XDISPLAY (display);
- dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+ g_return_if_fail (GDK_IS_SCREEN (screen));
- XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);
+ device = display->core_pointer;
+ GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
+}
+
+/**
+ * gdk_display_warp_device:
+ * @display: a #GdkDisplay.
+ * @device: a #GdkDevice.
+ * @screen: the screen of @display to warp @device to.
+ * @x: the X coordinate of the destination.
+ * @y: the Y coordinate of the destination.
+ *
+ * Warps @device in @display to the point @x,@y on
+ * the screen @screen, unless the device is confined
+ * to a window by a grab, in which case it will be moved
+ * as far as allowed by the grab. Warping the pointer
+ * creates events as if the user had moved the mouse
+ * instantaneously to the destination.
+ *
+ * Note that the pointer should normally be under the
+ * control of the user. This function was added to cover
+ * some rare use cases like keyboard navigation support
+ * for the color picker in the #GtkColorSelectionDialog.
+ *
+ * Since: 3.0
+ **/
+void
+gdk_display_warp_device (GdkDisplay *display,
+ GdkDevice *device,
+ GdkScreen *screen,
+ gint x,
+ gint y)
+{
+ g_return_if_fail (GDK_IS_DISPLAY (display));
+ g_return_if_fail (GDK_IS_DEVICE (device));
+ g_return_if_fail (GDK_IS_SCREEN (screen));
+ g_return_if_fail (display == gdk_device_get_display (device));
+
+ GDK_DEVICE_GET_CLASS (device)->warp (device, screen, x, y);
}
GdkWindow*
-_gdk_windowing_window_at_pointer (GdkDisplay *display,
- gint *win_x,
- gint *win_y,
- GdkModifierType *mask,
- gboolean get_toplevel)
+_gdk_windowing_window_at_device_position (GdkDisplay *display,
+ GdkDevice *device,
+ gint *win_x,
+ gint *win_y,
+ GdkModifierType *mask,
+ gboolean get_toplevel)
{
GdkWindow *window;
GdkScreen *screen;
- Window root;
- Window xwindow;
- Window child;
- Window xwindow_last = 0;
- Display *xdisplay;
- int rootx = -1, rooty = -1;
- int winx, winy;
- unsigned int xmask;
screen = gdk_display_get_default_screen (display);
-
- xwindow = GDK_SCREEN_XROOTWIN (screen);
- xdisplay = GDK_SCREEN_XDISPLAY (screen);
/* This function really only works if the mouse pointer is held still
* during its operation. If it moves from one leaf window to another
@@ -3176,35 +3216,24 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
* and the result.
*/
gdk_x11_display_grab (display);
- if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
- {
- XQueryPointer (xdisplay, xwindow,
- &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
- if (root == xwindow)
- xwindow = child;
- else
- xwindow = root;
-
- while (xwindow)
- {
- xwindow_last = xwindow;
- XQueryPointer (xdisplay, xwindow,
- &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
- if (get_toplevel && xwindow_last != root &&
- (window = gdk_window_lookup_for_display (display, xwindow_last)) != NULL &&
- GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
- {
- xwindow = xwindow_last;
- break;
- }
- }
- }
- else
+ if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
+ window = GDK_DEVICE_GET_CLASS (device)->window_at_position (device, win_x, win_y, mask, get_toplevel);
+ else
{
gint i, screens, width, height;
GList *toplevels, *list;
- Window pointer_window;
-
+ Window pointer_window, root, xwindow, child;
+ Window xwindow_last = 0;
+ Display *xdisplay;
+ int rootx = -1, rooty = -1;
+ int winx, winy;
+ unsigned int xmask;
+
+ /* FIXME: untrusted clients case not multidevice-safe */
+
+ xwindow = GDK_SCREEN_XROOTWIN (screen);
+ xdisplay = GDK_SCREEN_XDISPLAY (screen);
+
pointer_window = None;
screens = gdk_display_get_n_screens (display);
for (i = 0; i < screens; ++i) {
@@ -3265,16 +3294,17 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
break;
}
+
+ window = gdk_window_lookup_for_display (display, xwindow_last);
+
+ *win_x = window ? winx : -1;
+ *win_y = window ? winy : -1;
+ if (mask)
+ *mask = xmask;
}
-
+
gdk_x11_display_ungrab (display);
- window = gdk_window_lookup_for_display (display, xwindow_last);
- *win_x = window ? winx : -1;
- *win_y = window ? winy : -1;
- if (mask)
- *mask = xmask;
-
return window;
}
@@ -3305,21 +3335,18 @@ gdk_window_x11_set_events (GdkWindow *window,
GdkEventMask event_mask)
{
long xevent_mask = 0;
- int i;
if (!GDK_WINDOW_DESTROYED (window))
{
+ GdkDisplayX11 *display_x11;
+
if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
xevent_mask = StructureNotifyMask | PropertyChangeMask;
- for (i = 0; i < _gdk_nenvent_masks; i++)
- {
- if (event_mask & (1 << (i + 1)))
- xevent_mask |= _gdk_event_mask_table[i];
- }
-
- XSelectInput (GDK_WINDOW_XDISPLAY (window),
- GDK_WINDOW_XID (window),
- xevent_mask);
+
+ display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+ gdk_event_source_select_events ((GdkEventSource *) display_x11->event_source,
+ GDK_WINDOW_XWINDOW (window), event_mask,
+ xevent_mask);
}
}
@@ -5529,10 +5556,10 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
iface->reparent = gdk_window_x11_reparent;
iface->clear_region = gdk_window_x11_clear_region;
- iface->set_cursor = gdk_window_x11_set_cursor;
+ iface->set_device_cursor = gdk_window_x11_set_device_cursor;
iface->get_geometry = gdk_window_x11_get_geometry;
iface->get_root_coords = gdk_window_x11_get_root_coords;
- iface->get_pointer = gdk_window_x11_get_pointer;
+ iface->get_device_state = gdk_window_x11_get_device_state;
iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin;
iface->shape_combine_region = gdk_window_x11_shape_combine_region;
iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
@@ -5540,10 +5567,63 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
iface->queue_translation = _gdk_x11_window_queue_translation;
iface->destroy = _gdk_x11_window_destroy;
- iface->input_window_destroy = _gdk_input_window_destroy;
- iface->input_window_crossing = _gdk_input_crossing_event;
iface->supports_native_bg = TRUE;
}
+static Bool
+timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ Window xwindow = GPOINTER_TO_UINT (arg);
+ GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (display);
+
+ if (xevent->type == PropertyNotify &&
+ xevent->xproperty.window == xwindow &&
+ xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (gdk_display,
+ "GDK_TIMESTAMP_PROP"))
+ return True;
+
+ return False;
+}
+
+/**
+ * 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.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Return value: the time stamp.
+ **/
+guint32
+gdk_x11_get_server_time (GdkWindow *window)
+{
+ Display *xdisplay;
+ Window xwindow;
+ guchar c = 'a';
+ XEvent xevent;
+ Atom timestamp_prop_atom;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
+
+ xdisplay = GDK_WINDOW_XDISPLAY (window);
+ xwindow = GDK_WINDOW_XWINDOW (window);
+ timestamp_prop_atom =
+ gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+ "GDK_TIMESTAMP_PROP");
+
+ XChangeProperty (xdisplay, xwindow, timestamp_prop_atom,
+ timestamp_prop_atom,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (xdisplay, &xevent,
+ timestamp_predicate, GUINT_TO_POINTER(xwindow));
+
+ return xevent.xproperty.time;
+}
+
#define __GDK_WINDOW_X11_C__
#include "gdkaliasdef.c"