diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/client.c | 4 | ||||
-rw-r--r-- | src/device.c | 627 | ||||
-rw-r--r-- | src/device.h | 186 | ||||
-rw-r--r-- | src/display.c | 5 | ||||
-rw-r--r-- | src/display.h | 1 | ||||
-rw-r--r-- | src/event_filter.c | 8 | ||||
-rw-r--r-- | src/event_filter.h | 7 | ||||
-rw-r--r-- | src/main.c | 7 | ||||
-rw-r--r-- | src/mywindow.c | 10 | ||||
-rw-r--r-- | src/screen.c | 2 |
11 files changed, 854 insertions, 5 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 8a6309e62..af9dea45d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,8 @@ xfwm4_SOURCES = \ compositor.h \ cycle.c \ cycle.h \ + device.c \ + device.h \ display.c \ display.h \ event_filter.c \ diff --git a/src/client.c b/src/client.c index db61862b1..735dcf5b2 100644 --- a/src/client.c +++ b/src/client.c @@ -1872,6 +1872,10 @@ clientFrame (DisplayInfo *display_info, Window w, gboolean recapture) c->frame = XCreateWindow (display_info->dpy, screen_info->xroot, 0, 0, 1, 1, 0, c->depth, InputOutput, c->visual, valuemask, &attributes); +#ifdef HAVE_XI2 + xfwm_device_configure_xi2_event_mask (display_info->devices, display_info->dpy, + c->frame, attributes.event_mask); +#endif XSelectInput (display_info->dpy, c->window, NoEventMask); XSetWindowBorderWidth (display_info->dpy, c->window, 0); diff --git a/src/device.c b/src/device.c new file mode 100644 index 000000000..b1e33ae2f --- /dev/null +++ b/src/device.c @@ -0,0 +1,627 @@ +/* $Id$ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + + device.c - (c) 2017 Viktor Odintsev + + */ + +#include "device.h" + +#include <gdk/gdkx.h> +#ifdef HAVE_XI2 +#include <X11/extensions/XInput2.h> +#endif + +#ifdef HAVE_XI2 +static const struct +{ + guint core_mask; + guint xi2_event; +} core_to_xi2[] = +{ + { KeyPressMask, XI_KeyPress }, + { KeyReleaseMask, XI_KeyRelease }, + { ButtonPressMask, XI_ButtonPress }, + { ButtonReleaseMask, XI_ButtonRelease }, + { PointerMotionMask | ButtonMotionMask, XI_Motion }, + { EnterWindowMask, XI_Enter }, + { LeaveWindowMask, XI_Leave } +}; +#endif + +#define xfwm_device_fill_meta(evtype, evwindow, evdevice) \ +{ \ + if (event == NULL) \ + { \ + event = g_new0 (XfwmEvent, 1); \ + } \ + event->meta.type = evtype; \ + event->meta.window = evwindow; \ + event->meta.device = evdevice; \ + event->meta.x = xevent; \ +} + +#ifdef HAVE_XI2 +static guint +xfwm_device_obtain_state_xi2 (XIButtonState *buttons, XIModifierState *mods, XIGroupState *group) +{ + guint result; + gint i, count; + + result = mods->effective | (group->effective << 13); + count = MIN (3, buttons->mask_len / 8); + for (i = 0; i < count; i++) + { + /* check first 3 buttons as GDK does */ + if (XIMaskIsSet (buttons->mask, i + 1)) + { + result |= 1 << (8 + i); + } + } + + return result; +} +#endif + +static XfwmEvent * +xfwm_device_translate_event_key_core (XEvent *xevent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_KEY, xevent->xany.window, None); + + event->key.root = xevent->xkey.root; + event->key.pressed = xevent->type == KeyPress; + event->key.keycode = xevent->xkey.keycode; + event->key.state = xevent->xkey.state; + event->key.time = xevent->xkey.time; + + return (XfwmEvent *)event; +} + +#ifdef HAVE_XI2 +static XfwmEvent * +xfwm_device_translate_event_key_xi2 (XEvent *xevent, XIDeviceEvent *xievent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_KEY, xievent->event, xievent->deviceid); + + event->key.root = xievent->root; + event->key.pressed = xievent->evtype == XI_KeyPress; + event->key.keycode = xievent->detail; + event->key.state = xfwm_device_obtain_state_xi2 (&xievent->buttons, + &xievent->mods, + &xievent->group); + event->key.time = xievent->time; + + return (XfwmEvent *)event; +} +#endif + +static XfwmEvent * +xfwm_device_translate_event_button_core (XEvent *xevent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_BUTTON, xevent->xany.window, None); + + event->button.root = xevent->xbutton.root; + event->button.subwindow = xevent->xbutton.subwindow; + event->button.pressed = xevent->type == ButtonPress; + event->button.button = xevent->xbutton.button; + event->button.state = xevent->xbutton.state; + event->button.x = xevent->xbutton.x; + event->button.y = xevent->xbutton.y; + event->button.x_root = xevent->xbutton.x_root; + event->button.y_root = xevent->xbutton.y_root; + event->button.time = xevent->xbutton.time; + + return (XfwmEvent *)event; +} + +#ifdef HAVE_XI2 +static XfwmEvent * +xfwm_device_translate_event_button_xi2 (XEvent *xevent, XIDeviceEvent *xievent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_BUTTON, xievent->event, xievent->deviceid); + + event->button.root = xievent->root; + event->button.subwindow = xievent->child; + event->button.pressed = xievent->evtype == XI_ButtonPress; + event->button.button = xievent->detail; + event->button.state = xfwm_device_obtain_state_xi2 (&xievent->buttons, + &xievent->mods, + &xievent->group); + event->button.x = xievent->event_x; + event->button.y = xievent->event_y; + event->button.x_root = xievent->root_x; + event->button.y_root = xievent->root_y; + event->button.time = xievent->time; + + return (XfwmEvent *)event; +} +#endif + +static XfwmEvent * +xfwm_device_translate_event_motion_core (XEvent *xevent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_MOTION, xevent->xany.window, None); + + event->motion.x = xevent->xbutton.x; + event->motion.y = xevent->xbutton.y; + event->motion.x_root = xevent->xbutton.x_root; + event->motion.y_root = xevent->xbutton.y_root; + event->motion.time = xevent->xbutton.time; + + return (XfwmEvent *)event; +} + +#ifdef HAVE_XI2 +static XfwmEvent * +xfwm_device_translate_event_motion_xi2 (XEvent *xevent, XIDeviceEvent *xievent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_MOTION, xievent->event, xievent->deviceid); + + event->motion.x = xievent->event_x; + event->motion.y = xievent->event_y; + event->motion.x_root = xievent->root_x; + event->motion.y_root = xievent->root_y; + event->motion.time = xievent->time; + + return (XfwmEvent *)event; +} +#endif + +static XfwmEvent * +xfwm_device_translate_event_crossing_core (XEvent *xevent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_CROSSING, xevent->xany.window, None); + + event->crossing.root = xevent->xcrossing.root; + event->crossing.enter = xevent->type == EnterNotify; + event->crossing.mode = xevent->xcrossing.mode; + event->crossing.detail = xevent->xcrossing.detail; + event->crossing.x_root = xevent->xcrossing.x_root; + event->crossing.y_root = xevent->xcrossing.y_root; + event->crossing.time = xevent->xcrossing.time; + + return (XfwmEvent *)event; +} + +#ifdef HAVE_XI2 +static XfwmEvent * +xfwm_device_translate_event_crossing_xi2 (XEvent *xevent, XIEnterEvent *xievent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_CROSSING, xievent->event, xievent->deviceid); + + event->crossing.root = xievent->root; + event->crossing.enter = xievent->evtype == XI_Enter; + event->crossing.mode = xievent->mode; + event->crossing.detail = xievent->detail; + event->crossing.x_root = xievent->root_x; + event->crossing.y_root = xievent->root_y; + event->crossing.time = xievent->time; + + return (XfwmEvent *)event; +} +#endif + +static XfwmEvent * +xfwm_device_translate_event_common (XEvent *xevent, XfwmEvent *event) +{ + xfwm_device_fill_meta (XFWM_EVENT_X, xevent->xany.window, None); + + return event; +} + +XfwmEvent * +xfwm_device_translate_event (XfwmDevices *devices, XEvent *xevent, XfwmEvent *event) +{ + switch (xevent->type) + { + case KeyPress: + case KeyRelease: + return xfwm_device_translate_event_key_core (xevent, event); + case ButtonPress: + case ButtonRelease: + return xfwm_device_translate_event_button_core (xevent, event); + case MotionNotify: + return xfwm_device_translate_event_motion_core (xevent, event); + case EnterNotify: + case LeaveNotify: + return xfwm_device_translate_event_crossing_core (xevent, event); +#ifdef HAVE_XI2 + case GenericEvent: + if (devices->xi2_available && + xevent->xgeneric.extension == devices->xi2_opcode && + xevent->xcookie.data != NULL) + { + XIEvent *xievent = xevent->xcookie.data; + + switch (xievent->evtype) + { + case XI_KeyPress: + case XI_KeyRelease: + return xfwm_device_translate_event_key_xi2 (xevent, (XIDeviceEvent *)xievent, event); + case XI_ButtonPress: + case XI_ButtonRelease: + return xfwm_device_translate_event_button_xi2 (xevent, (XIDeviceEvent *)xievent, event); + case XI_Motion: + return xfwm_device_translate_event_motion_xi2 (xevent, (XIDeviceEvent *)xievent, event); + case XI_Enter: + case XI_Leave: + return xfwm_device_translate_event_crossing_xi2 (xevent, (XIEnterEvent *)xievent, event); + } + } + break; +#endif + } + + return xfwm_device_translate_event_common (xevent, event); +} + +void +xfwm_device_free_event (XfwmEvent *event) +{ + g_free (event); +} + +void +xfwm_device_button_update_window (XfwmEventButton *event, Window window) +{ + event->meta.window = window; +#ifdef HAVE_XI2 + if (event->meta.device != None) + { + ((XIDeviceEvent *)event->meta.x->xcookie.data)->event = window; + } + else +#endif + { + event->meta.x->xany.window = window; + } +} + +#ifdef HAVE_XI2 +static void +xfwm_device_fill_xi2_event_mask (XIEventMask *xievent_mask, gulong core_mask) +{ + gint len = XIMaskLen (XI_LASTEVENT); + guchar *mask = g_new0 (guchar, len); + guint i; + + xievent_mask->deviceid = XIAllMasterDevices; + xievent_mask->mask_len = sizeof (mask); + xievent_mask->mask = mask; + + for (i = 0; i < G_N_ELEMENTS (core_to_xi2); i++) + { + if ((core_mask & core_to_xi2[i].core_mask) == core_to_xi2[i].core_mask) + { + XISetMask (mask, core_to_xi2[i].xi2_event); + } + } + + #undef xi2_set_mask +} +#endif + +#ifdef HAVE_XI2 +void +xfwm_device_configure_xi2_event_mask (XfwmDevices *devices, Display *dpy, + Window window, gulong core_mask) +{ + if (devices->xi2_available) + { + XIEventMask xievent_mask; + xfwm_device_fill_xi2_event_mask (&xievent_mask, core_mask); + XISelectEvents (dpy, window, &xievent_mask, 1); + g_free (xievent_mask.mask); + } +} +#endif + +#ifdef HAVE_XI2 +#define xi2_modifier_mask(core_mask) \ + ((((core_mask) & AnyModifier) == AnyModifier) \ + ? (((core_mask) & ~AnyModifier) | XIAnyModifier) \ + : (core_mask)) +#endif + +gboolean +xfwm_device_grab (XfwmDevices *devices, XfwmDevice *device, Display *display, + Window grab_window, gboolean owner_events, guint event_mask, + gint grab_mode, Window confine_to, Cursor cursor, Time time) +{ + gboolean result; + Status status; +#ifdef HAVE_XI2 + XIEventMask xievent_mask; +#endif + +#ifdef HAVE_XI2 + if (device->xi2_device != None) + { + xfwm_device_fill_xi2_event_mask (&xievent_mask, event_mask); + status = XIGrabDevice (display, device->xi2_device, grab_window, time, cursor, + grab_mode, grab_mode, owner_events, &xievent_mask); + g_free (xievent_mask.mask); + result = (status == XIGrabSuccess); + } + else +#endif + if (device->keyboard) + { + status = XGrabKeyboard (display, grab_window, owner_events, + grab_mode, grab_mode, time); + result = (status == GrabSuccess); + } + else + { + status = XGrabPointer (display, grab_window, owner_events, event_mask, + grab_mode, grab_mode, confine_to, cursor, time); + result = (status == GrabSuccess); + } + return result; +} + +void +xfwm_device_ungrab (XfwmDevices *devices, XfwmDevice *device, Display *display, Time time) +{ +#ifdef HAVE_XI2 + if (device->xi2_device != None) + { + XIUngrabDevice (display, device->xi2_device, time); + } + else +#endif + if (device->keyboard) + { + XUngrabKeyboard (display, time); + } + else + { + XUngrabPointer (display, time); + } +} + +gboolean +xfwm_device_grab_button (XfwmDevices *devices, Display *display, + guint button, guint modifiers, Window grab_window, + gboolean owner_events, guint event_mask, + gint grab_mode, gint paired_device_mode, + Window confine_to, Cursor cursor) +{ + gboolean result; + Status status; +#ifdef HAVE_XI2 + XIGrabModifiers xi2_modifiers; + XIEventMask xievent_mask; +#endif + +#ifdef HAVE_XI2 + if (devices->xi2_available) + { + xi2_modifiers.modifiers = xi2_modifier_mask (modifiers); + xi2_modifiers.status = 0; + + xfwm_device_fill_xi2_event_mask (&xievent_mask, event_mask); + status = XIGrabButton (display, devices->pointer.xi2_device, button, grab_window, + cursor, grab_mode, paired_device_mode, owner_events, + &xievent_mask, 1, &xi2_modifiers); + g_free (xievent_mask.mask); + result = (status == XIGrabSuccess); + } + else +#endif + { + status = XGrabButton (display, button, modifiers, grab_window, + owner_events, event_mask, grab_mode, paired_device_mode, + confine_to, cursor); + result = (status == GrabSuccess); + } + return result; +} + +void +xfwm_device_ungrab_button (XfwmDevices *devices, Display *display, + guint button, guint modifiers, Window grab_window) +{ +#ifdef HAVE_XI2 + XIGrabModifiers xi2_modifiers; +#endif + +#ifdef HAVE_XI2 + if (devices->xi2_available) + { + xi2_modifiers.modifiers = xi2_modifier_mask (modifiers); + xi2_modifiers.status = 0; + + XIUngrabButton (display, devices->pointer.xi2_device, button, + grab_window, 1, &xi2_modifiers); + } + else +#endif + { + XUngrabButton (display, button, modifiers, grab_window); + } +} + +gboolean +xfwm_device_grab_keycode (XfwmDevices *devices, Display *display, + gint keycode, guint modifiers, Window grab_window, + gboolean owner_events, guint event_mask, + gint grab_mode, gint paired_device_mode) +{ + gboolean result; + Status status; +#ifdef HAVE_XI2 + XIGrabModifiers xi2_modifiers; + XIEventMask xievent_mask; +#endif + +#ifdef HAVE_XI2 + if (devices->xi2_available) + { + xi2_modifiers.modifiers = xi2_modifier_mask (modifiers); + xi2_modifiers.status = 0; + + xfwm_device_fill_xi2_event_mask (&xievent_mask, event_mask); + status = XIGrabKeycode (display, devices->keyboard.xi2_device, keycode, grab_window, + grab_mode, paired_device_mode, owner_events, + &xievent_mask, 1, &xi2_modifiers); + g_free (xievent_mask.mask); + result = (status == XIGrabSuccess); + } + else +#endif + { + status = XGrabKey (display, keycode, modifiers, grab_window, + owner_events, grab_mode, paired_device_mode); + result = (status == GrabSuccess); + } + return result; +} + +void +xfwm_device_ungrab_keycode (XfwmDevices *devices, Display *display, + gint keycode, guint modifiers, Window grab_window) +{ +#ifdef HAVE_XI2 + XIGrabModifiers xi2_modifiers; +#endif + +#ifdef HAVE_XI2 + if (devices->xi2_available) + { + xi2_modifiers.modifiers = xi2_modifier_mask (modifiers); + xi2_modifiers.status = 0; + + XIUngrabKeycode (display, devices->keyboard.xi2_device, keycode, + grab_window, 1, &xi2_modifiers); + } + else +#endif + { + XUngrabKey (display, keycode, modifiers, grab_window); + } +} + +#ifdef HAVE_XI2 +typedef struct +{ + XfwmDevices *devices; + XfwmEvent *event; + XIEventMask xievent_mask; +} XI2CheckMaskContext; + +static gboolean +xfwm_device_check_mask_event_xi2_predicate (Display *display, XEvent *xevent, XPointer user_data) +{ + XI2CheckMaskContext *context = (void *)user_data; + + if (xevent->type == GenericEvent && + xevent->xgeneric.extension == context->devices->xi2_opcode && + XIMaskIsSet (context->xievent_mask.mask, xevent->xgeneric.evtype)) + { + /* GDK holds XI2 event data which we are replacing so it should be released here */ + XFreeEventData (display, &context->event->meta.x->xcookie); + return TRUE; + } + + return FALSE; +} +#endif + +gboolean +xfwm_device_check_mask_event (XfwmDevices *devices, Display *display, + guint event_mask, XfwmEvent *event) +{ + gboolean result; +#ifdef HAVE_XI2 + XI2CheckMaskContext context; +#endif + +#ifdef HAVE_XI2 + if (devices->xi2_available && event->meta.device != None) + { + context.devices = devices; + context.event = event; + xfwm_device_fill_xi2_event_mask (&context.xievent_mask, event_mask); + result = XCheckIfEvent (display, event->meta.x, + xfwm_device_check_mask_event_xi2_predicate, (XPointer)&context); + g_free (context.xievent_mask.mask); + + if (result) + { + /* Previos data was released in predicate, allocate a new data for the new event */ + XGetEventData (display, &event->meta.x->xcookie); + } + } + else +#endif + { + result = XCheckMaskEvent (display, event_mask, event->meta.x); + } + + if (result) + { + xfwm_device_translate_event (devices, event->meta.x, event); + } + + return result; +} + +XfwmDevices * +xfwm_devices_new (GdkDisplay *display) +{ + XfwmDevices *devices; +#ifdef HAVE_XI2 + GdkSeat *seat; + GdkDevice *pointer_device; + GdkDevice *keyboard_device; + gint firstevent, firsterror; +#endif + + devices = g_new0 (XfwmDevices, 1); + devices->xi2_available = FALSE; + devices->xi2_opcode = 0; + + devices->pointer.keyboard = FALSE; + devices->pointer.xi2_device = None; + + devices->keyboard.keyboard = TRUE; + devices->keyboard.xi2_device = None; + +#ifdef HAVE_XI2 + seat = gdk_display_get_default_seat (display); + pointer_device = gdk_seat_get_pointer (seat); + keyboard_device = gdk_seat_get_keyboard (seat); + + if (GDK_IS_X11_DEVICE_XI2 (pointer_device) || GDK_IS_X11_DEVICE_XI2 (keyboard_device)) + { + /* GDK uses XI2, let's use it too */ + + /* Obtain XI2 opcode */ + if (XQueryExtension (gdk_x11_display_get_xdisplay (display), "XInputExtension", + &devices->xi2_opcode, &firstevent, &firsterror)) + { + devices->xi2_available = TRUE; + devices->pointer.xi2_device = gdk_x11_device_get_id (pointer_device); + devices->keyboard.xi2_device = gdk_x11_device_get_id (keyboard_device); + } + } +#endif + + return devices; +} diff --git a/src/device.h b/src/device.h new file mode 100644 index 000000000..7cebdd3e2 --- /dev/null +++ b/src/device.h @@ -0,0 +1,186 @@ +/* $Id$ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301, USA. + + + device.h - (c) 2017 Viktor Odintsev + + */ + +#ifndef INC_DEVICE_H +#define INC_DEVICE_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <X11/Xlib.h> +#include <gdk/gdk.h> + +typedef enum +{ + XFWM_EVENT_X, + XFWM_EVENT_KEY, + XFWM_EVENT_BUTTON, + XFWM_EVENT_MOTION, + XFWM_EVENT_CROSSING +} XfwmEventType; + +typedef struct +{ + XfwmEventType type; + Window window; + gint device; + XEvent *x; +} XfwmEventMeta; + +typedef struct +{ + XfwmEventMeta meta; + + Window root; + gboolean pressed; + guint keycode; + guint state; + Time time; +} XfwmEventKey; + +typedef struct +{ + XfwmEventMeta meta; + + Window root; + Window subwindow; + gboolean pressed; + guint button; + guint state; + gint x; + gint y; + gint x_root; + gint y_root; + Time time; +} XfwmEventButton; + +typedef struct +{ + XfwmEventMeta meta; + + gint x; + gint y; + gint x_root; + gint y_root; + Time time; +} XfwmEventMotion; + +typedef struct +{ + XfwmEventMeta meta; + + Window root; + gboolean enter; + gint mode; + gint detail; + gint x_root; + gint y_root; + Time time; +} XfwmEventCrossing; + +typedef union +{ + XfwmEventMeta meta; + XfwmEventKey key; + XfwmEventButton button; + XfwmEventMotion motion; + XfwmEventCrossing crossing; +} XfwmEvent; + +typedef struct +{ + gboolean keyboard; + gint xi2_device; +} XfwmDevice; + +typedef struct { + XfwmDevice pointer; + XfwmDevice keyboard; + + gboolean xi2_available; + gint xi2_opcode; +} XfwmDevices; + +XfwmEvent *xfwm_device_translate_event (XfwmDevices *, + XEvent *, + XfwmEvent *); +void xfwm_device_free_event (XfwmEvent *); +void xfwm_device_button_update_window (XfwmEventButton *, + Window); +#ifdef HAVE_XI2 +void xfwm_device_configure_xi2_event_mask (XfwmDevices *, + Display *, + Window, + gulong); +#endif +gboolean xfwm_device_grab (XfwmDevices *, + XfwmDevice *, + Display *, + Window, + gboolean, + guint, + gint, + Window, + Cursor, + Time); +void xfwm_device_ungrab (XfwmDevices *, + XfwmDevice *, + Display *, + Time); +gboolean xfwm_device_grab_button (XfwmDevices *, + Display *, + guint, + guint, + Window, + gboolean, + guint, + gint, + gint, + Window, + Cursor); +void xfwm_device_ungrab_button (XfwmDevices *, + Display *, + guint, + guint, + Window); +gboolean xfwm_device_grab_keycode (XfwmDevices *, + Display *, + gint, + guint, + Window, + gboolean, + guint, + gint, + gint); +void xfwm_device_ungrab_keycode (XfwmDevices *, + Display *, + gint, + guint, + Window); +gboolean xfwm_device_check_mask_event (XfwmDevices *, + Display *, + guint, + XfwmEvent *); +XfwmDevices *xfwm_devices_new (GdkDisplay *); + +#endif /* INC_DEVICE_H */ diff --git a/src/display.c b/src/display.c index e3ddcd915..29a932d84 100644 --- a/src/display.c +++ b/src/display.c @@ -231,6 +231,8 @@ myDisplayInit (GdkDisplay *gdisplay) g_warning ("Some internal atoms were not properly created."); } + display->devices = xfwm_devices_new (gdisplay); + /* Test XShape extension support */ major = 0; minor = 0; @@ -368,6 +370,9 @@ myDisplayClose (DisplayInfo *display) g_slist_free (display->screens); display->screens = NULL; + g_free (display->devices); + display->devices = NULL; + return display; } diff --git a/src/display.h b/src/display.h index 0babd34b5..882b2b37d 100644 --- a/src/display.h +++ b/src/display.h @@ -299,6 +299,7 @@ struct _DisplayInfo Atom atoms[ATOM_COUNT]; eventFilterSetup *xfilter; + XfwmDevices *devices; GSList *screens; GSList *clients; diff --git a/src/event_filter.c b/src/event_filter.c index c0f5edd36..c1340c3c2 100644 --- a/src/event_filter.c +++ b/src/event_filter.c @@ -200,7 +200,7 @@ eventFilterPop (eventFilterSetup *setup) } GdkWindow * -eventFilterAddWin (GdkScreen *gscr, long event_mask) +eventFilterAddWin (GdkScreen *gscr, XfwmDevices *devices, long event_mask) { XWindowAttributes attribs; Display *dpy; @@ -220,6 +220,9 @@ eventFilterAddWin (GdkScreen *gscr, long event_mask) XGetWindowAttributes (dpy, xroot, &attribs); XSelectInput (dpy, xroot, attribs.your_event_mask | event_mask); +#ifdef HAVE_XI2 + xfwm_device_configure_xi2_event_mask (devices, dpy, xroot, attribs.your_event_mask | event_mask); +#endif gdk_x11_ungrab_server (); gdk_flush (); @@ -235,12 +238,13 @@ eventFilterAddWin (GdkScreen *gscr, long event_mask) } eventFilterSetup * -eventFilterInit (gpointer data) +eventFilterInit (XfwmDevices *devices, gpointer data) { eventFilterSetup *setup; setup = g_new0 (eventFilterSetup, 1); setup->filterstack = NULL; + setup->devices = devices; eventFilterPush (setup, default_event_filter, data); gdk_window_add_filter (NULL, eventXfwmFilter, (gpointer) setup); diff --git a/src/event_filter.h b/src/event_filter.h index 953775e72..8ee215332 100644 --- a/src/event_filter.h +++ b/src/event_filter.h @@ -31,6 +31,8 @@ #include <gdk/gdk.h> #include <X11/Xlib.h> +#include "device.h" + /* this formatting is needed by glib-mkenums */ typedef enum { EVENT_FILTER_STOP = 0x0, @@ -53,16 +55,19 @@ eventFilterStack; typedef struct eventFilterSetup { eventFilterStack *filterstack; + XfwmDevices *devices; } eventFilterSetup; GdkWindow *eventFilterAddWin (GdkScreen *, + XfwmDevices *, long); eventFilterStack *eventFilterPush (eventFilterSetup *, XfwmFilter, gpointer ); eventFilterStack *eventFilterPop (eventFilterSetup *); -eventFilterSetup *eventFilterInit (gpointer); +eventFilterSetup *eventFilterInit (XfwmDevices *, + gpointer); void eventFilterClose (eventFilterSetup *); #endif /* INC_EVENT_FILTER_H */ diff --git a/src/main.c b/src/main.c index 8546fa72d..28136e155 100644 --- a/src/main.c +++ b/src/main.c @@ -615,7 +615,7 @@ initialize (gint compositor_mode, gboolean replace_wm) { return -1; } - display_info->xfilter = eventFilterInit ((gpointer) display_info); + display_info->xfilter = eventFilterInit (display_info->devices, (gpointer) display_info); eventFilterPush (display_info->xfilter, xfwm4_event_filter, (gpointer) display_info); initPerDisplayCallbacks (display_info); @@ -673,6 +673,11 @@ main (int argc, char **argv) xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8"); +#ifndef HAVE_XI2 + /* Disable XI2 in GDK */ + gdk_disable_multidevice (); +#endif + context = g_option_context_new (_("[ARGUMENTS...]")); g_option_context_add_main_entries (context, option_entries, GETTEXT_PACKAGE); g_option_context_add_group (context, gtk_get_option_group (FALSE)); diff --git a/src/mywindow.c b/src/mywindow.c index b829a5e40..819e4c57b 100644 --- a/src/mywindow.c +++ b/src/mywindow.c @@ -124,6 +124,11 @@ xfwmWindowCreate (ScreenInfo * screen_info, Visual *visual, gint depth, Window p #ifdef HAVE_RENDER win->pict_format = XRenderFindVisualFormat (myScreenGetXDisplay (screen_info), win->visual); #endif +#ifdef HAVE_XI2 + xfwm_device_configure_xi2_event_mask (screen_info->display_info->devices, + screen_info->display_info->dpy, + win->window, eventmask); +#endif } void @@ -266,6 +271,11 @@ xfwmWindowTemp (ScreenInfo *screen_info, Visual *visual, win->width = width; win->height = height; xfwmWindowSetVisual (win, visual, depth); +#ifdef HAVE_XI2 + xfwm_device_configure_xi2_event_mask (screen_info->display_info->devices, + screen_info->display_info->dpy, + win->window, eventmask); +#endif } #ifdef HAVE_RENDER diff --git a/src/screen.c b/src/screen.c index 02ce61d8b..3e8695a16 100644 --- a/src/screen.c +++ b/src/screen.c @@ -219,7 +219,7 @@ myScreenInit (DisplayInfo *display_info, GdkScreen *gscr, unsigned long event_ma return NULL; } - event_win = eventFilterAddWin (gscr, event_mask); + event_win = eventFilterAddWin (gscr, display_info->devices, event_mask); if (!event_win) { gtk_widget_destroy (screen_info->gtk_win); |