Compare commits
60 Commits
wip/carlos
...
wip/xinput
Author | SHA1 | Date | |
---|---|---|---|
eac32fb142 | |||
b93c72315d | |||
f84637d31e | |||
48a88a33ef | |||
8847281c31 | |||
d05297593f | |||
a285b8ae44 | |||
e6ba5ec298 | |||
f6d9b29ad0 | |||
e6f0af9abc | |||
d32c726967 | |||
2c873990d1 | |||
f15993f940 | |||
d482dbcd16 | |||
f5334dd6cf | |||
972a9d231f | |||
1dd50cf006 | |||
855095ad1a | |||
95b2e6fafc | |||
dfcd079ec2 | |||
e0966e7499 | |||
38df2715f2 | |||
5ecbb3ec3b | |||
656fa71649 | |||
bde0d28f1b | |||
4cb9a5e3bf | |||
90c25f0cfe | |||
2484e8cd64 | |||
61a7789c83 | |||
c352e1078e | |||
d664579115 | |||
49dfb40b82 | |||
e08c4756eb | |||
6378527458 | |||
f0705e142c | |||
3f7193e558 | |||
3af9de08ab | |||
111c23a6e0 | |||
db6ddc4a7f | |||
884e13474b | |||
722420df3a | |||
50cee11c53 | |||
a727114ac2 | |||
722d2d6472 | |||
7b9a26fbd8 | |||
5819e74c22 | |||
36e237cf1e | |||
3b0aa9f881 | |||
e6d09c9d0b | |||
e26bf9dcef | |||
748954a15e | |||
4c4f21c001 | |||
166559059a | |||
7566b4ea17 | |||
1b7a6ce912 | |||
dc4ecdd0d2 | |||
d381c0465b | |||
38a0aecf61 | |||
7573aae855 | |||
684d40d1a1 |
28
configure.in
28
configure.in
@ -238,6 +238,33 @@ if test x$have_xcursor = xyes; then
|
||||
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
|
||||
fi
|
||||
|
||||
XINPUT2_VERSION=1.4.0
|
||||
|
||||
AC_ARG_ENABLE(xinput2,
|
||||
AC_HELP_STRING([--disable-xinput2],
|
||||
[disable XInput2 usage]),,
|
||||
enable_xinput2=yes)
|
||||
|
||||
if test x$enable_xinput2 = xyes; then
|
||||
AC_MSG_CHECKING([XInput2])
|
||||
if $PKG_CONFIG --atleast-version $XINPUT2_VERSION xi; then
|
||||
have_xinput2=yes
|
||||
else
|
||||
have_xinput2=no
|
||||
fi
|
||||
AC_MSG_RESULT($have_xinput2)
|
||||
else
|
||||
have_xinput2=no
|
||||
fi
|
||||
|
||||
if test x$have_xinput2 = xyes; then
|
||||
echo "Building with XInput2"
|
||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xi"
|
||||
AC_DEFINE(HAVE_XINPUT2, , [Building with XInput2 support])
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL(HAVE_XINPUT2, test "$have_xinput2" = "yes")
|
||||
|
||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||
|
||||
AC_PATH_XTRA
|
||||
@ -557,6 +584,7 @@ mutter-$VERSION
|
||||
Shape extension: ${found_shape}
|
||||
Xsync: ${found_xsync}
|
||||
Xcursor: ${have_xcursor}
|
||||
XInput2: ${have_xinput2}
|
||||
"
|
||||
|
||||
|
||||
|
@ -75,6 +75,20 @@ libmutter_la_SOURCES = \
|
||||
core/constraints.h \
|
||||
core/core.c \
|
||||
core/delete.c \
|
||||
core/device.c \
|
||||
meta/device.h \
|
||||
core/device-keyboard.c \
|
||||
core/device-keyboard.h \
|
||||
core/device-pointer.c \
|
||||
core/device-pointer.h \
|
||||
core/device-private.h \
|
||||
core/device-map.c \
|
||||
meta/device-map.h \
|
||||
core/device-map-private.h \
|
||||
core/device-map-core.c \
|
||||
core/device-map-core.h \
|
||||
core/devices-core.c \
|
||||
core/devices-core.h \
|
||||
core/display.c \
|
||||
core/display-private.h \
|
||||
meta/display.h \
|
||||
@ -97,6 +111,8 @@ libmutter_la_SOURCES = \
|
||||
meta/group.h \
|
||||
core/iconcache.c \
|
||||
core/iconcache.h \
|
||||
core/input-events.c \
|
||||
core/input-events.h \
|
||||
core/keybindings.c \
|
||||
core/keybindings-private.h \
|
||||
core/main.c \
|
||||
@ -154,6 +170,14 @@ libmutter_la_SOURCES = \
|
||||
ui/preview-widget.c \
|
||||
$(mutter_built_sources)
|
||||
|
||||
if HAVE_XINPUT2
|
||||
libmutter_la_SOURCES += \
|
||||
core/device-map-xi2.c \
|
||||
core/device-map-xi2.h \
|
||||
core/devices-xi2.c \
|
||||
core/devices-xi2.h
|
||||
endif
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
libmutter_la_LIBADD = $(MUTTER_LIBS)
|
||||
|
||||
@ -164,6 +188,8 @@ libmutterinclude_base_headers = \
|
||||
meta/common.h \
|
||||
meta/compositor-mutter.h \
|
||||
meta/compositor.h \
|
||||
meta/device.h \
|
||||
meta/device-map.h \
|
||||
meta/display.h \
|
||||
meta/errors.h \
|
||||
meta/gradient.h \
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include "meta-background-actor.h"
|
||||
#include "window-private.h" /* to check window->hidden */
|
||||
#include "display-private.h" /* for meta_display_lookup_x_window() */
|
||||
#include "core.h" /* for meta_core_select_events() */
|
||||
#include "input-events.h"
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
@ -178,7 +180,6 @@ get_output_window (MetaScreen *screen)
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window output, xroot;
|
||||
XWindowAttributes attr;
|
||||
long event_mask;
|
||||
|
||||
xroot = meta_screen_get_xroot (screen);
|
||||
@ -192,13 +193,7 @@ get_output_window (MetaScreen *screen)
|
||||
KeyPressMask | KeyReleaseMask;
|
||||
|
||||
output = XCompositeGetOverlayWindow (xdisplay, xroot);
|
||||
|
||||
if (XGetWindowAttributes (xdisplay, output, &attr))
|
||||
{
|
||||
event_mask |= attr.your_event_mask;
|
||||
}
|
||||
|
||||
XSelectInput (xdisplay, output, event_mask);
|
||||
meta_core_select_events (xdisplay, output, event_mask, TRUE);
|
||||
|
||||
return output;
|
||||
}
|
||||
@ -364,26 +359,34 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
* merge the two.
|
||||
*/
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
gboolean pointer_grabbed = FALSE;
|
||||
gboolean keyboard_grabbed = FALSE;
|
||||
int result;
|
||||
gboolean result;
|
||||
MetaDevice *device;
|
||||
MetaGrabInfo *grab_info;
|
||||
|
||||
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
|
||||
/* FIXME: need a real device here, and probably
|
||||
* some exclusion mode for other devices */
|
||||
device = meta_device_map_lookup (display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
|
||||
grab_info = meta_display_get_grab_info (display, device);
|
||||
|
||||
if (compositor->modal_plugin != NULL || grab_info != NULL)
|
||||
return FALSE;
|
||||
|
||||
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
result = XGrabPointer (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
(ButtonPressMask | ButtonReleaseMask |
|
||||
EnterWindowMask | LeaveWindowMask | PointerMotionMask),
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
None, /* confine to */
|
||||
cursor,
|
||||
timestamp);
|
||||
if (result != Success)
|
||||
result = meta_device_grab (device,
|
||||
grab_window,
|
||||
(ButtonPressMask | ButtonReleaseMask |
|
||||
EnterWindowMask | LeaveWindowMask | PointerMotionMask),
|
||||
cursor,
|
||||
FALSE,
|
||||
FALSE,
|
||||
timestamp);
|
||||
if (!result)
|
||||
goto fail;
|
||||
|
||||
pointer_grabbed = TRUE;
|
||||
@ -391,22 +394,25 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
|
||||
{
|
||||
result = XGrabKeyboard (xdpy, grab_window,
|
||||
False, /* owner_events */
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
timestamp);
|
||||
|
||||
if (result != Success)
|
||||
result = meta_device_grab (meta_device_get_paired_device (device),
|
||||
grab_window,
|
||||
(KeyPressMask | KeyReleaseMask),
|
||||
META_CURSOR_DEFAULT,
|
||||
FALSE, FALSE,
|
||||
timestamp);
|
||||
if (!result)
|
||||
goto fail;
|
||||
|
||||
keyboard_grabbed = TRUE;
|
||||
}
|
||||
|
||||
display->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
display->grab_window = NULL;
|
||||
display->grab_screen = screen;
|
||||
display->grab_have_pointer = TRUE;
|
||||
display->grab_have_keyboard = TRUE;
|
||||
grab_info = meta_display_create_grab_info (display, device);
|
||||
|
||||
grab_info->grab_op = META_GRAB_OP_COMPOSITOR;
|
||||
grab_info->grab_window = NULL;
|
||||
grab_info->grab_screen = screen;
|
||||
grab_info->grab_have_pointer = TRUE;
|
||||
grab_info->grab_have_keyboard = TRUE;
|
||||
|
||||
compositor->modal_plugin = plugin;
|
||||
|
||||
@ -414,9 +420,9 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
|
||||
|
||||
fail:
|
||||
if (pointer_grabbed)
|
||||
XUngrabPointer (xdpy, timestamp);
|
||||
meta_device_ungrab (device, timestamp);
|
||||
if (keyboard_grabbed)
|
||||
XUngrabKeyboard (xdpy, timestamp);
|
||||
meta_device_ungrab (meta_device_get_paired_device (device), timestamp);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@ -427,20 +433,19 @@ meta_end_modal_for_plugin (MetaScreen *screen,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdpy = meta_display_get_xdisplay (display);
|
||||
MetaCompositor *compositor = display->compositor;
|
||||
MetaDevice *device;
|
||||
|
||||
g_return_if_fail (compositor->modal_plugin == plugin);
|
||||
|
||||
XUngrabPointer (xdpy, timestamp);
|
||||
XUngrabKeyboard (xdpy, timestamp);
|
||||
/* FIXME: need a real device here */
|
||||
device = meta_device_map_lookup (display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
display->grab_screen = NULL;
|
||||
display->grab_have_pointer = FALSE;
|
||||
display->grab_have_keyboard = FALSE;
|
||||
meta_device_ungrab (device, timestamp);
|
||||
meta_device_ungrab (meta_device_get_paired_device (device), timestamp);
|
||||
|
||||
meta_display_remove_grab_info (display, device);
|
||||
compositor->modal_plugin = NULL;
|
||||
}
|
||||
|
||||
@ -473,7 +478,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
Window xroot = meta_screen_get_xroot (screen);
|
||||
Window xwin;
|
||||
gint width, height;
|
||||
XWindowAttributes attr;
|
||||
long event_mask;
|
||||
guint n_retries;
|
||||
guint max_retries;
|
||||
@ -548,12 +552,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
StructureNotifyMask;
|
||||
|
||||
if (XGetWindowAttributes (xdisplay, xwin, &attr))
|
||||
{
|
||||
event_mask |= attr.your_event_mask;
|
||||
}
|
||||
|
||||
XSelectInput (xdisplay, xwin, event_mask);
|
||||
meta_core_select_events (xdisplay, xwin, event_mask, TRUE);
|
||||
|
||||
info->window_group = meta_window_group_new (screen);
|
||||
info->background_actor = meta_background_actor_new (screen);
|
||||
@ -658,9 +657,15 @@ meta_compositor_set_updates (MetaCompositor *compositor,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_grabbed_event (XEvent *event)
|
||||
is_grabbed_event (MetaDisplay *display,
|
||||
XEvent *event)
|
||||
{
|
||||
switch (event->xany.type)
|
||||
guint evtype;
|
||||
|
||||
if (!meta_input_event_get_type (display, event, &evtype))
|
||||
return FALSE;
|
||||
|
||||
switch (evtype)
|
||||
{
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
@ -683,7 +688,8 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
if (compositor->modal_plugin && is_grabbed_event (event))
|
||||
if (compositor->modal_plugin &&
|
||||
is_grabbed_event (compositor->display, event))
|
||||
{
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
|
||||
|
||||
|
@ -230,6 +230,35 @@ bell_flash_window_frame (MetaWindow *window)
|
||||
bell_unflash_frame, window->frame, NULL);
|
||||
}
|
||||
|
||||
static MetaWindow *
|
||||
get_flash_window (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event;
|
||||
MetaWindow *window;
|
||||
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
|
||||
xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
|
||||
if (!window &&
|
||||
g_hash_table_size (display->focus_info) == 1)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
MetaFocusInfo *info;
|
||||
|
||||
/* If there is only one focused window, use it */
|
||||
g_hash_table_iter_init (&iter, display->focus_info);
|
||||
|
||||
if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info) &&
|
||||
info->focus_window && info->focus_window->frame)
|
||||
window = info->focus_window;
|
||||
}
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flashes the frame of the focussed window. If there is no focussed window,
|
||||
* flashes the screen.
|
||||
@ -241,15 +270,11 @@ static void
|
||||
bell_flash_frame (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
MetaWindow *window;
|
||||
|
||||
g_assert (xkb_ev->xkb_type == XkbBellNotify);
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window))
|
||||
{
|
||||
window = display->focus_window;
|
||||
}
|
||||
window = get_flash_window (display, xkb_ev);
|
||||
|
||||
if (window && window->frame)
|
||||
{
|
||||
bell_flash_window_frame (window);
|
||||
@ -310,9 +335,7 @@ meta_bell_notify (MetaDisplay *display,
|
||||
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
|
||||
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
|
||||
|
||||
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
|
||||
if (!window && (display->focus_window) && (display->focus_window->frame))
|
||||
window = display->focus_window;
|
||||
window = get_flash_window (display, xkb_ev);
|
||||
|
||||
if (window)
|
||||
{
|
||||
|
@ -885,6 +885,7 @@ constrain_tiling (MetaWindow *window,
|
||||
gboolean hminbad, vminbad;
|
||||
gboolean horiz_equal, vert_equal;
|
||||
gboolean constraint_already_satisfied;
|
||||
MetaDevice *pointer;
|
||||
|
||||
if (priority > PRIORITY_TILING)
|
||||
return TRUE;
|
||||
@ -893,10 +894,12 @@ constrain_tiling (MetaWindow *window,
|
||||
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
|
||||
return TRUE;
|
||||
|
||||
pointer = meta_window_guess_grab_pointer (window);
|
||||
|
||||
/* Calculate target_size - as the tile previews need this as well, we
|
||||
* use an external function for the actual calculation
|
||||
*/
|
||||
meta_window_get_current_tile_area (window, &target_size);
|
||||
meta_window_get_current_tile_area (window, pointer, &target_size);
|
||||
unextend_by_frame (&target_size, info->fgeom);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored as for
|
||||
@ -1362,15 +1365,18 @@ constrain_titlebar_visible (MetaWindow *window,
|
||||
int bottom_amount;
|
||||
int horiz_amount_offscreen, vert_amount_offscreen;
|
||||
int horiz_amount_onscreen, vert_amount_onscreen;
|
||||
MetaGrabInfo *grab_info;
|
||||
|
||||
if (priority > PRIORITY_TITLEBAR_VISIBLE)
|
||||
return TRUE;
|
||||
|
||||
grab_info = window->cur_grab;
|
||||
|
||||
/* Allow the titlebar beyond the top of the screen only if the user wasn't
|
||||
* clicking on the frame to start the move.
|
||||
*/
|
||||
unconstrained_user_action =
|
||||
info->is_user_action && !window->display->grab_frame_action;
|
||||
info->is_user_action && (!grab_info || !grab_info->grab_frame_action);
|
||||
|
||||
/* Exit early if we know the constraint won't apply--note that this constraint
|
||||
* is only meant for normal windows (e.g. we don't want docks to be shoved
|
||||
|
200
src/core/core.c
200
src/core/core.c
@ -30,6 +30,11 @@
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/errors.h>
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include "devices-xi2.h"
|
||||
#endif
|
||||
|
||||
/* Looks up the MetaWindow representing the frame of the given X window.
|
||||
* Used as a helper function by a bunch of the functions below.
|
||||
*
|
||||
@ -245,9 +250,19 @@ lower_window_and_transients (MetaWindow *window,
|
||||
void
|
||||
meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
MetaDevice *pointer;
|
||||
|
||||
pointer = meta_device_map_lookup (window->display->device_map, device_id);
|
||||
|
||||
if (pointer == NULL)
|
||||
return;
|
||||
|
||||
if (!META_IS_DEVICE_POINTER (pointer))
|
||||
pointer = meta_device_get_paired_device (pointer);
|
||||
|
||||
lower_window_and_transients (window, NULL);
|
||||
|
||||
@ -256,6 +271,7 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
* this will be invoked via keyboard action or by a mouse action;
|
||||
* in either case the window or a modal child will have been focused.) */
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
pointer,
|
||||
NULL,
|
||||
timestamp);
|
||||
}
|
||||
@ -263,16 +279,21 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
void
|
||||
meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
int device_id,
|
||||
guint32 timestamp)
|
||||
{
|
||||
XWindowChanges changes;
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
MetaWindow *grab_window;
|
||||
MetaDevice *pointer;
|
||||
MetaGrabInfo *grab_info;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = meta_display_screen_for_xwindow (display, xwindow);
|
||||
grab_window = display->grab_window;
|
||||
pointer = meta_device_map_lookup (display->device_map, device_id);
|
||||
grab_info = meta_display_get_grab_info (display, pointer);
|
||||
grab_window = grab_info->grab_window;
|
||||
|
||||
if (grab_window == NULL)
|
||||
return;
|
||||
@ -491,18 +512,27 @@ meta_core_get_active_workspace (Screen *xscreen)
|
||||
void
|
||||
meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
MetaDevice *device;
|
||||
|
||||
/* There is already a menu popped up,
|
||||
* most likely from another device
|
||||
*/
|
||||
if (window->menu)
|
||||
return;
|
||||
|
||||
if (meta_prefs_get_raise_on_click ())
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
meta_window_show_menu (window, root_x, root_y, button, timestamp);
|
||||
device = meta_device_map_lookup (window->display->device_map, device_id);
|
||||
meta_window_show_menu (window, device, root_x, root_y, button, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
@ -638,6 +668,7 @@ meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
gboolean
|
||||
meta_core_begin_grab_op (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
MetaGrabOp op,
|
||||
gboolean pointer_already_grabbed,
|
||||
gboolean frame_action,
|
||||
@ -650,13 +681,16 @@ meta_core_begin_grab_op (Display *xdisplay,
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
|
||||
MetaDevice *device;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
screen = meta_display_screen_for_xwindow (display, frame_xwindow);
|
||||
|
||||
g_assert (screen != NULL);
|
||||
|
||||
return meta_display_begin_grab_op (display, screen, window,
|
||||
|
||||
device = meta_device_map_lookup (display->device_map, device_id);
|
||||
|
||||
return meta_display_begin_grab_op (display, screen, window, device,
|
||||
op, pointer_already_grabbed,
|
||||
frame_action,
|
||||
button, modmask,
|
||||
@ -665,57 +699,58 @@ meta_core_begin_grab_op (Display *xdisplay,
|
||||
|
||||
void
|
||||
meta_core_end_grab_op (Display *xdisplay,
|
||||
int device_id,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
MetaDevice *device;
|
||||
|
||||
meta_display_end_grab_op (display, timestamp);
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
device = meta_device_map_lookup (display->device_map, device_id);
|
||||
|
||||
meta_display_end_grab_op (display, device, timestamp);
|
||||
}
|
||||
|
||||
MetaGrabOp
|
||||
meta_core_get_grab_op (Display *xdisplay)
|
||||
meta_core_frame_has_grab (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
gint *device_id,
|
||||
gint *button_ret)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
MetaWindow *window;
|
||||
|
||||
return display->grab_op;
|
||||
window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
if (window != NULL &&
|
||||
window->cur_grab != NULL)
|
||||
{
|
||||
if (button_ret)
|
||||
*button_ret = window->cur_grab->grab_button;
|
||||
|
||||
if (device_id)
|
||||
*device_id = meta_device_get_id (window->cur_grab->grab_pointer);
|
||||
|
||||
return window->cur_grab->grab_op;
|
||||
}
|
||||
|
||||
return META_GRAB_OP_NONE;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_core_get_grab_frame (Display *xdisplay)
|
||||
meta_core_get_frame (Display *xdisplay,
|
||||
Window client_xwindow)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
MetaWindow *window;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
window = meta_display_lookup_x_window (display, client_xwindow);
|
||||
|
||||
g_assert (display != NULL);
|
||||
g_assert (display->grab_op == META_GRAB_OP_NONE ||
|
||||
display->grab_screen != NULL);
|
||||
g_assert (display->grab_op == META_GRAB_OP_NONE ||
|
||||
display->grab_screen->display->xdisplay == xdisplay);
|
||||
|
||||
if (display->grab_op != META_GRAB_OP_NONE &&
|
||||
display->grab_window &&
|
||||
display->grab_window->frame)
|
||||
return display->grab_window->frame->xwindow;
|
||||
else
|
||||
return None;
|
||||
}
|
||||
if (window &&
|
||||
window->frame)
|
||||
return window->frame->xwindow;
|
||||
|
||||
int
|
||||
meta_core_get_grab_button (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return -1;
|
||||
|
||||
return display->grab_button;
|
||||
return None;
|
||||
}
|
||||
|
||||
void
|
||||
@ -731,13 +766,24 @@ meta_core_grab_buttons (Display *xdisplay,
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor)
|
||||
meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
gint device_id,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaWindow *window = get_window (xdisplay, frame_on_screen);
|
||||
MetaDevice *pointer;
|
||||
|
||||
meta_frame_set_screen_cursor (window->frame, cursor);
|
||||
pointer = meta_device_map_lookup (window->display->device_map,
|
||||
device_id);
|
||||
|
||||
if (pointer == NULL)
|
||||
return;
|
||||
|
||||
if (!META_IS_DEVICE_POINTER (pointer))
|
||||
pointer = meta_device_get_paired_device (pointer);
|
||||
|
||||
meta_frame_set_screen_cursor (window->frame, pointer, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -775,3 +821,69 @@ meta_invalidate_default_icons (void)
|
||||
g_slist_free (windows);
|
||||
}
|
||||
|
||||
/* Selects events on an xwindow, using XInput2 if available/in use,
|
||||
* this function doesn't require the xwindow to have a backing
|
||||
* MetaWindow.
|
||||
*/
|
||||
void
|
||||
meta_core_select_events (Display *xdisplay,
|
||||
Window xwindow,
|
||||
gint evmask,
|
||||
gboolean preserve_old_mask)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (display->have_xinput2)
|
||||
{
|
||||
XIEventMask mask;
|
||||
|
||||
mask.deviceid = XIAllMasterDevices;
|
||||
mask.mask = meta_device_xi2_translate_event_mask (evmask,
|
||||
&mask.mask_len);
|
||||
|
||||
if (preserve_old_mask)
|
||||
{
|
||||
XIEventMask *prev;
|
||||
gint n_masks, i, j;
|
||||
|
||||
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
|
||||
|
||||
for (i = 0; i < n_masks; i++)
|
||||
{
|
||||
if (prev[i].deviceid != XIAllMasterDevices)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < MIN (mask.mask_len, prev[i].mask_len); j++)
|
||||
mask.mask[j] |= prev[i].mask[j];
|
||||
}
|
||||
|
||||
XFree (prev);
|
||||
}
|
||||
|
||||
XISelectEvents (xdisplay, xwindow, &mask, 1);
|
||||
|
||||
/* Unset any input event so they are only handled via XInput2 */
|
||||
evmask &= ~(KeyPressMask | KeyReleaseMask |
|
||||
ButtonPressMask | ButtonReleaseMask |
|
||||
EnterWindowMask | LeaveWindowMask |
|
||||
PointerMotionMask | PointerMotionHintMask |
|
||||
Button1MotionMask | Button2MotionMask |
|
||||
Button3MotionMask | Button4MotionMask |
|
||||
Button5MotionMask | ButtonMotionMask |
|
||||
FocusChangeMask);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (preserve_old_mask)
|
||||
{
|
||||
XWindowAttributes attr;
|
||||
|
||||
if (XGetWindowAttributes (xdisplay, xwindow, &attr))
|
||||
evmask |= attr.your_event_mask;
|
||||
}
|
||||
|
||||
XSelectInput (xdisplay, xwindow, evmask);
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ void meta_core_user_raise (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
void meta_core_user_lower_and_unfocus (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_user_focus (Display *xdisplay,
|
||||
@ -118,6 +119,7 @@ void meta_core_user_focus (Display *xdisplay,
|
||||
|
||||
void meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
Window xwindow,
|
||||
int device_id,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_core_minimize (Display *xdisplay,
|
||||
@ -163,6 +165,7 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
|
||||
void meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
@ -175,6 +178,7 @@ void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
|
||||
|
||||
gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int device_id,
|
||||
MetaGrabOp op,
|
||||
gboolean pointer_already_grabbed,
|
||||
gboolean frame_action,
|
||||
@ -184,18 +188,29 @@ gboolean meta_core_begin_grab_op (Display *xdisplay,
|
||||
int root_x,
|
||||
int root_y);
|
||||
void meta_core_end_grab_op (Display *xdisplay,
|
||||
int device_id,
|
||||
guint32 timestamp);
|
||||
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
|
||||
Window meta_core_get_grab_frame (Display *xdisplay);
|
||||
int meta_core_get_grab_button (Display *xdisplay);
|
||||
|
||||
MetaGrabOp meta_core_frame_has_grab (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
gint *device_id,
|
||||
gint *button_ret);
|
||||
Window meta_core_get_frame (Display *xdisplay,
|
||||
Window client_xwindow);
|
||||
|
||||
void meta_core_grab_buttons (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor);
|
||||
void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
int device_id,
|
||||
MetaCursor cursor);
|
||||
|
||||
void meta_core_select_events (Display *xdisplay,
|
||||
Window xwindow,
|
||||
gint evmask,
|
||||
gboolean preserve_old_mask);
|
||||
|
||||
|
||||
/* Used because we ignore EnterNotify when a window is unmapped that
|
||||
* really shouldn't cause focus changes, by comparing the event serial
|
||||
|
69
src/core/device-keyboard.c
Normal file
69
src/core/device-keyboard.c
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Keyboard device abstraction */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "device-keyboard.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaDeviceKeyboard,
|
||||
meta_device_keyboard,
|
||||
META_TYPE_DEVICE)
|
||||
|
||||
static void
|
||||
meta_device_keyboard_class_init (MetaDeviceKeyboardClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_init (MetaDeviceKeyboard *keyboard)
|
||||
{
|
||||
}
|
||||
|
||||
Window
|
||||
meta_device_keyboard_get_focus_window (MetaDeviceKeyboard *keyboard)
|
||||
{
|
||||
MetaDeviceKeyboardClass *klass;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_KEYBOARD (keyboard), None);
|
||||
|
||||
klass = META_DEVICE_KEYBOARD_GET_CLASS (keyboard);
|
||||
|
||||
if (!klass->get_focus_window)
|
||||
return None;
|
||||
|
||||
return (klass->get_focus_window) (keyboard);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_keyboard_set_focus_window (MetaDeviceKeyboard *keyboard,
|
||||
Window xwindow,
|
||||
Time timestamp)
|
||||
{
|
||||
MetaDeviceKeyboardClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE_KEYBOARD (keyboard));
|
||||
|
||||
klass = META_DEVICE_KEYBOARD_GET_CLASS (keyboard);
|
||||
|
||||
if (klass->set_focus_window)
|
||||
(klass->set_focus_window) (keyboard, xwindow, timestamp);
|
||||
}
|
69
src/core/device-keyboard.h
Normal file
69
src/core/device-keyboard.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device-keyboard.h Keyboard device abstraction
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the internal abstraction of keyboard devices so
|
||||
* XInput2/core events can be handled similarly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_KEYBOARD_H
|
||||
#define META_DEVICE_KEYBOARD_H
|
||||
|
||||
#include "display-private.h"
|
||||
#include "device-private.h"
|
||||
|
||||
#define META_TYPE_DEVICE_KEYBOARD (meta_device_keyboard_get_type ())
|
||||
#define META_DEVICE_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboard))
|
||||
#define META_DEVICE_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboardClass))
|
||||
#define META_IS_DEVICE_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD))
|
||||
#define META_IS_DEVICE_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD))
|
||||
#define META_DEVICE_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboardClass))
|
||||
|
||||
typedef struct _MetaDeviceKeyboard MetaDeviceKeyboard;
|
||||
typedef struct _MetaDeviceKeyboardClass MetaDeviceKeyboardClass;
|
||||
|
||||
struct _MetaDeviceKeyboard
|
||||
{
|
||||
MetaDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDeviceKeyboardClass
|
||||
{
|
||||
MetaDeviceClass parent_instance;
|
||||
|
||||
Window (* get_focus_window) (MetaDeviceKeyboard *keyboard);
|
||||
void (* set_focus_window) (MetaDeviceKeyboard *keyboard,
|
||||
Window xwindow,
|
||||
Time timestamp);
|
||||
};
|
||||
|
||||
GType meta_device_keyboard_get_type (void) G_GNUC_CONST;
|
||||
|
||||
Window meta_device_keyboard_get_focus_window (MetaDeviceKeyboard *keyboard);
|
||||
void meta_device_keyboard_set_focus_window (MetaDeviceKeyboard *keyboard,
|
||||
Window xwindow,
|
||||
Time timestamp);
|
||||
|
||||
|
||||
#endif /* META_DEVICE_KEYBOARD_H */
|
134
src/core/device-map-core.c
Normal file
134
src/core/device-map-core.c
Normal file
@ -0,0 +1,134 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Input device map, core protocol implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "device-map-core.h"
|
||||
#include "devices-core.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaDeviceMapCore, meta_device_map_core, META_TYPE_DEVICE_MAP)
|
||||
|
||||
static gboolean
|
||||
meta_device_map_core_grab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers,
|
||||
gboolean sync)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
gint retval;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
retval = XGrabKey (display->xdisplay, keycode, modifiers,
|
||||
xwindow, True,
|
||||
GrabModeAsync, /* Never care about the other device */
|
||||
(sync) ? GrabModeSync : GrabModeAsync);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_core_ungrab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
XUngrabKey (display->xdisplay, keycode, modifiers, xwindow);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_device_map_core_grab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers,
|
||||
guint evmask,
|
||||
gboolean sync)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
gint retval;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
retval = XGrabButton (display->xdisplay, n_button,
|
||||
modifiers, xwindow, False,
|
||||
evmask,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
GrabModeAsync, /* Never care about the other device */
|
||||
None, None);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_core_ungrab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
XUngrabButton (display->xdisplay, n_button, modifiers, xwindow);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_core_constructed (GObject *object)
|
||||
{
|
||||
MetaDeviceMap *device_map = META_DEVICE_MAP (object);
|
||||
MetaDevice *pointer, *keyboard;
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
|
||||
/* Insert core devices */
|
||||
pointer = meta_device_pointer_core_new (display);
|
||||
meta_device_map_add_device (device_map, pointer);
|
||||
|
||||
keyboard = meta_device_keyboard_core_new (display);
|
||||
meta_device_map_add_device (device_map, keyboard);
|
||||
|
||||
meta_device_pair_devices (pointer, keyboard);
|
||||
|
||||
g_object_unref (pointer);
|
||||
g_object_unref (keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_core_class_init (MetaDeviceMapCoreClass *klass)
|
||||
{
|
||||
MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_device_map_core_constructed;
|
||||
|
||||
device_map_class->grab_key = meta_device_map_core_grab_key;
|
||||
device_map_class->ungrab_key = meta_device_map_core_ungrab_key;
|
||||
device_map_class->grab_button = meta_device_map_core_grab_button;
|
||||
device_map_class->ungrab_button = meta_device_map_core_ungrab_button;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_core_init (MetaDeviceMapCore *device_map)
|
||||
{
|
||||
}
|
56
src/core/device-map-core.h
Normal file
56
src/core/device-map-core.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device-map-core.h device map for core devices
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the core protocol implementation of the device map
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_MAP_CORE_H
|
||||
#define META_DEVICE_MAP_CORE_H
|
||||
|
||||
typedef struct _MetaDeviceMapCore MetaDeviceMapCore;
|
||||
typedef struct _MetaDeviceMapCoreClass MetaDeviceMapCoreClass;
|
||||
|
||||
#include "device-map-private.h"
|
||||
|
||||
#define META_TYPE_DEVICE_MAP_CORE (meta_device_map_core_get_type ())
|
||||
#define META_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCore))
|
||||
#define META_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass))
|
||||
#define META_IS_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_CORE))
|
||||
#define META_IS_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_CORE))
|
||||
#define META_DEVICE_MAP_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass))
|
||||
|
||||
struct _MetaDeviceMapCore
|
||||
{
|
||||
MetaDeviceMap parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDeviceMapCoreClass
|
||||
{
|
||||
MetaDeviceMapClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_map_core_get_type (void) G_GNUC_CONST;
|
||||
|
||||
#endif /* META_DEVICE_MAP_CORE_H */
|
111
src/core/device-map-private.h
Normal file
111
src/core/device-map-private.h
Normal file
@ -0,0 +1,111 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device-map.h object containing input devices
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the device map, used to find out the device behind
|
||||
* XInput2/core events.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_MAP_PRIVATE_H
|
||||
#define META_DEVICE_MAP_PRIVATE_H
|
||||
|
||||
#include <meta/device-map.h>
|
||||
#include <meta/device.h>
|
||||
#include "display-private.h"
|
||||
#include "device-private.h"
|
||||
|
||||
/* Device IDs for Virtual Core Pointer/Keyboard,
|
||||
* use only in case of emergency.
|
||||
*/
|
||||
#define META_CORE_POINTER_ID 2
|
||||
#define META_CORE_KEYBOARD_ID 3
|
||||
|
||||
struct _MetaDeviceMap
|
||||
{
|
||||
GObject parent_instance;
|
||||
gpointer priv;
|
||||
};
|
||||
|
||||
struct _MetaDeviceMapClass
|
||||
{
|
||||
GObjectClass parent_instance;
|
||||
|
||||
void (* device_added) (MetaDeviceMap *device_map,
|
||||
MetaDevice *device);
|
||||
void (* device_removed) (MetaDeviceMap *device_map,
|
||||
MetaDevice *device);
|
||||
|
||||
gboolean (* grab_key) (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers,
|
||||
gboolean sync);
|
||||
void (* ungrab_key) (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers);
|
||||
|
||||
gboolean (* grab_button) (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers,
|
||||
guint evmask,
|
||||
gboolean sync);
|
||||
void (* ungrab_button) (MetaDeviceMap *pointer,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers);
|
||||
};
|
||||
|
||||
GType meta_device_map_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDeviceMap * meta_device_map_new (MetaDisplay *display,
|
||||
gboolean force_core);
|
||||
|
||||
void meta_device_map_add_device (MetaDeviceMap *device_map,
|
||||
MetaDevice *device);
|
||||
void meta_device_map_remove_device (MetaDeviceMap *device_map,
|
||||
MetaDevice *device);
|
||||
|
||||
gboolean meta_device_map_grab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers,
|
||||
gboolean sync);
|
||||
void meta_device_map_ungrab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers);
|
||||
gboolean meta_device_map_grab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers,
|
||||
guint evmask,
|
||||
gboolean sync);
|
||||
void meta_device_map_ungrab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers);
|
||||
|
||||
#endif /* META_DEVICE_MAP_PRIVATE_H */
|
269
src/core/device-map-xi2.c
Normal file
269
src/core/device-map-xi2.c
Normal file
@ -0,0 +1,269 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Input device map, XInput2 implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "device-map-xi2.h"
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include "devices-xi2.h"
|
||||
|
||||
#define XINPUT2_VERSION_MAJOR 2
|
||||
#define XINPUT2_VERSION_MINOR 0
|
||||
|
||||
G_DEFINE_TYPE (MetaDeviceMapXI2, meta_device_map_xi2, META_TYPE_DEVICE_MAP)
|
||||
|
||||
static gboolean
|
||||
meta_device_map_xi2_grab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers,
|
||||
gboolean sync)
|
||||
{
|
||||
XIGrabModifiers mods = { modifiers, 0 };
|
||||
MetaDisplay *display;
|
||||
XIEventMask mask;
|
||||
gint retval;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
|
||||
mask.deviceid = XIAllMasterDevices;
|
||||
mask.mask = meta_device_xi2_translate_event_mask (KeyPressMask |
|
||||
KeyReleaseMask,
|
||||
&mask.mask_len);
|
||||
/* FIXME: Doesn't seem to work with
|
||||
* XIAllMasterDevices, use the VCK
|
||||
* at the moment
|
||||
*/
|
||||
retval = XIGrabKeycode (display->xdisplay,
|
||||
META_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
GrabModeAsync, /* Never care about the other device */
|
||||
True, &mask, 1, &mods);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_xi2_ungrab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers)
|
||||
{
|
||||
XIGrabModifiers mods = { modifiers, 0 };
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
XIUngrabKeycode (display->xdisplay,
|
||||
META_CORE_KEYBOARD_ID,
|
||||
keycode, xwindow,
|
||||
1, &mods);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_device_map_xi2_grab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers,
|
||||
guint evmask,
|
||||
gboolean sync)
|
||||
{
|
||||
XIGrabModifiers mods = { modifiers, 0 };
|
||||
XIEventMask mask;
|
||||
MetaDisplay *display;
|
||||
int retval;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
|
||||
mask.deviceid = XIAllMasterDevices;
|
||||
mask.mask = meta_device_xi2_translate_event_mask (evmask, &mask.mask_len);
|
||||
|
||||
retval = XIGrabButton (display->xdisplay,
|
||||
XIAllMasterDevices,
|
||||
n_button, xwindow, None,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
GrabModeAsync, /* Never care about the other device */
|
||||
False, &mask, 1, &mods);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_xi2_ungrab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers)
|
||||
{
|
||||
XIGrabModifiers mods = { modifiers, 0 };
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
XIUngrabButton (display->xdisplay,
|
||||
META_CORE_POINTER_ID,
|
||||
//XIAllMasterDevices,
|
||||
n_button, xwindow, 1, &mods);
|
||||
}
|
||||
|
||||
static void
|
||||
add_device_from_info (MetaDeviceMap *device_map,
|
||||
gint use,
|
||||
gint device_id)
|
||||
{
|
||||
MetaDevice *device;
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
|
||||
if (use == XIMasterPointer)
|
||||
device = meta_device_pointer_xi2_new (display, device_id);
|
||||
else if (use == XIMasterKeyboard)
|
||||
device = meta_device_keyboard_xi2_new (display, device_id);
|
||||
|
||||
if (device)
|
||||
{
|
||||
meta_device_map_add_device (device_map, device);
|
||||
g_object_unref (device);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pair_devices (gpointer key,
|
||||
gpointer value,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaDevice *device1, *device2;
|
||||
MetaDeviceMap *device_map;
|
||||
|
||||
device_map = user_data;
|
||||
device1 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (key));
|
||||
device2 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (value));
|
||||
|
||||
meta_device_pair_devices (device1, device2);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_xi2_constructed (GObject *object)
|
||||
{
|
||||
MetaDeviceMap *device_map = META_DEVICE_MAP (object);
|
||||
MetaDisplay *display;
|
||||
XIDeviceInfo *info;
|
||||
GHashTable *pairs;
|
||||
int n_devices, i;
|
||||
|
||||
display = meta_device_map_get_display (device_map);
|
||||
|
||||
/* We're only interested in master devices,
|
||||
* detached slave devices are left for applications
|
||||
* to handle.
|
||||
*/
|
||||
info = XIQueryDevice (display->xdisplay, XIAllMasterDevices, &n_devices);
|
||||
pairs = g_hash_table_new (NULL, NULL);
|
||||
|
||||
for (i = 0; i < n_devices; i++)
|
||||
{
|
||||
add_device_from_info (device_map, info[i].use, info[i].deviceid);
|
||||
g_hash_table_insert (pairs,
|
||||
GINT_TO_POINTER (info[i].deviceid),
|
||||
GINT_TO_POINTER (info[i].attachment));
|
||||
}
|
||||
|
||||
g_hash_table_foreach (pairs, pair_devices, device_map);
|
||||
g_hash_table_destroy (pairs);
|
||||
|
||||
XIFreeDeviceInfo (info);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_xi2_class_init (MetaDeviceMapXI2Class *klass)
|
||||
{
|
||||
MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_device_map_xi2_constructed;
|
||||
|
||||
device_map_class->grab_key = meta_device_map_xi2_grab_key;
|
||||
device_map_class->ungrab_key = meta_device_map_xi2_ungrab_key;
|
||||
device_map_class->grab_button = meta_device_map_xi2_grab_button;
|
||||
device_map_class->ungrab_button = meta_device_map_xi2_ungrab_button;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_xi2_init (MetaDeviceMapXI2 *device_map)
|
||||
{
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
|
||||
XEvent *ev)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_map_get_display (META_DEVICE_MAP (device_map));
|
||||
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIHierarchyEvent *xev;
|
||||
GHashTable *pairs;
|
||||
gint i;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIHierarchyEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype != XI_HierarchyChanged)
|
||||
return FALSE;
|
||||
|
||||
pairs = g_hash_table_new (NULL, NULL);
|
||||
|
||||
for (i = 0; i < xev->num_info; i++)
|
||||
{
|
||||
if (xev->info[i].flags & XIMasterAdded)
|
||||
{
|
||||
add_device_from_info (META_DEVICE_MAP (device_map),
|
||||
xev->info[i].use,
|
||||
xev->info[i].deviceid);
|
||||
g_hash_table_insert (pairs,
|
||||
GINT_TO_POINTER (xev->info[i].deviceid),
|
||||
GINT_TO_POINTER (xev->info[i].attachment));
|
||||
}
|
||||
else if (xev->info[i].flags & XIMasterRemoved)
|
||||
{
|
||||
MetaDevice *device;
|
||||
|
||||
device = meta_device_map_lookup (META_DEVICE_MAP (device_map),
|
||||
xev->info[i].deviceid);
|
||||
|
||||
if (device)
|
||||
meta_device_map_remove_device (META_DEVICE_MAP (device_map),
|
||||
device);
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_foreach (pairs, pair_devices, device_map);
|
||||
g_hash_table_destroy (pairs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
59
src/core/device-map-xi2.h
Normal file
59
src/core/device-map-xi2.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device-map-xi2.h device map for XInput2 devices
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the XInput2 implementation of the device map
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_MAP_XI2_H
|
||||
#define META_DEVICE_MAP_XI2_H
|
||||
|
||||
typedef struct _MetaDeviceMapXI2 MetaDeviceMapXI2;
|
||||
typedef struct _MetaDeviceMapXI2Class MetaDeviceMapXI2Class;
|
||||
|
||||
#include "device-map-private.h"
|
||||
|
||||
#define META_TYPE_DEVICE_MAP_XI2 (meta_device_map_xi2_get_type ())
|
||||
#define META_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2))
|
||||
#define META_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
|
||||
#define META_IS_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_XI2))
|
||||
#define META_IS_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_XI2))
|
||||
#define META_DEVICE_MAP_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
|
||||
|
||||
struct _MetaDeviceMapXI2
|
||||
{
|
||||
MetaDeviceMap parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDeviceMapXI2Class
|
||||
{
|
||||
MetaDeviceMapClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_map_xi2_get_type (void) G_GNUC_CONST;
|
||||
|
||||
gboolean meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
|
||||
XEvent *ev);
|
||||
|
||||
#endif /* META_DEVICE_MAP_XI2_H */
|
390
src/core/device-map.c
Normal file
390
src/core/device-map.c
Normal file
@ -0,0 +1,390 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Input device map */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "device-map-private.h"
|
||||
#include "device-map-core.h"
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include "device-map-xi2.h"
|
||||
|
||||
#define XINPUT2_VERSION_MAJOR 2
|
||||
#define XINPUT2_VERSION_MINOR 0
|
||||
#endif
|
||||
|
||||
G_DEFINE_TYPE (MetaDeviceMap, meta_device_map, G_TYPE_OBJECT)
|
||||
|
||||
typedef struct MetaDeviceMapPrivate MetaDeviceMapPrivate;
|
||||
|
||||
struct MetaDeviceMapPrivate
|
||||
{
|
||||
MetaDisplay *display;
|
||||
GHashTable *devices;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DISPLAY
|
||||
};
|
||||
|
||||
enum {
|
||||
DEVICE_ADDED,
|
||||
DEVICE_REMOVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void
|
||||
meta_device_map_get_property (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
priv = META_DEVICE_MAP (object)->priv;
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value, priv->display);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_set_property (GObject *object,
|
||||
guint param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
priv = META_DEVICE_MAP (object)->priv;
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DISPLAY:
|
||||
priv->display = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_finalize (GObject *object)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
GHashTableIter iter;
|
||||
MetaDevice *device;
|
||||
|
||||
priv = META_DEVICE_MAP (object)->priv;
|
||||
g_hash_table_iter_init (&iter, priv->devices);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device))
|
||||
{
|
||||
/* Detach the device */
|
||||
g_hash_table_iter_steal (&iter);
|
||||
|
||||
g_signal_emit (object, signals[DEVICE_REMOVED], 0, device);
|
||||
g_object_unref (device);
|
||||
}
|
||||
|
||||
g_hash_table_destroy (priv->devices);
|
||||
G_OBJECT_CLASS (meta_device_map_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_class_init (MetaDeviceMapClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = meta_device_map_get_property;
|
||||
object_class->set_property = meta_device_map_set_property;
|
||||
object_class->finalize = meta_device_map_finalize;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DISPLAY,
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display",
|
||||
META_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
signals[DEVICE_ADDED] =
|
||||
g_signal_new ("device-added",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_DEVICE);
|
||||
signals[DEVICE_REMOVED] =
|
||||
g_signal_new ("device-removed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1, META_TYPE_DEVICE);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaDeviceMapPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_map_init (MetaDeviceMap *device_map)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
priv = device_map->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_map,
|
||||
META_TYPE_DEVICE_MAP,
|
||||
MetaDeviceMapPrivate);
|
||||
priv->devices = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_map_add_device (MetaDeviceMap *device_map,
|
||||
MetaDevice *device)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
priv = device_map->priv;
|
||||
g_hash_table_insert (priv->devices,
|
||||
GINT_TO_POINTER (meta_device_get_id (device)),
|
||||
g_object_ref (device));
|
||||
|
||||
g_signal_emit (device_map, signals[DEVICE_ADDED], 0, device);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_map_remove_device (MetaDeviceMap *device_map,
|
||||
MetaDevice *device)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
priv = device_map->priv;
|
||||
|
||||
if (g_hash_table_steal (priv->devices,
|
||||
GINT_TO_POINTER (meta_device_get_id (device))))
|
||||
{
|
||||
g_signal_emit (device_map, signals[DEVICE_REMOVED], 0, device);
|
||||
g_object_unref (device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
|
||||
static gboolean
|
||||
initialize_xinput (MetaDisplay *display)
|
||||
{
|
||||
int major, minor, opcode;
|
||||
int unused;
|
||||
|
||||
if (!XQueryExtension (display->xdisplay,
|
||||
"XInputExtension",
|
||||
&opcode, &unused, &unused))
|
||||
return FALSE;
|
||||
|
||||
major = XINPUT2_VERSION_MAJOR;
|
||||
minor = XINPUT2_VERSION_MINOR;
|
||||
|
||||
XIQueryVersion (display->xdisplay, &major, &minor);
|
||||
|
||||
if (major == XINPUT2_VERSION_MAJOR &&
|
||||
minor == XINPUT2_VERSION_MINOR)
|
||||
{
|
||||
display->have_xinput2 = TRUE;
|
||||
display->xinput2_opcode = opcode;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
|
||||
MetaDeviceMap *
|
||||
meta_device_map_new (MetaDisplay *display,
|
||||
gboolean force_core)
|
||||
{
|
||||
GType type = META_TYPE_DEVICE_MAP_CORE;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (!force_core &&
|
||||
initialize_xinput (display))
|
||||
type = META_TYPE_DEVICE_MAP_XI2;
|
||||
#endif
|
||||
|
||||
return g_object_new (type,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_device_map_lookup:
|
||||
* @device_map: a #MetaDeviceMap
|
||||
* @device_id: ID for a device
|
||||
*
|
||||
* returns the device corresponding to @device_id
|
||||
*
|
||||
* Returns: (transfer none): (allow-none): The matching device, or %NULL.
|
||||
**/
|
||||
MetaDevice *
|
||||
meta_device_map_lookup (MetaDeviceMap *device_map,
|
||||
gint device_id)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
|
||||
|
||||
priv = device_map->priv;
|
||||
return g_hash_table_lookup (priv->devices,
|
||||
GINT_TO_POINTER (device_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_device_map_get_display:
|
||||
* @device_map: a #MetaDeviceMap
|
||||
*
|
||||
* Returns the #MetaDisplay to which @device_map belongs to.
|
||||
*
|
||||
* Returns: (transfer none): The #MetaDisplay.
|
||||
**/
|
||||
MetaDisplay *
|
||||
meta_device_map_get_display (MetaDeviceMap *device_map)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
|
||||
|
||||
priv = device_map->priv;
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_device_map_list_devices:
|
||||
* @device_map: a #MetaDeviceMap
|
||||
*
|
||||
* Returns the list of devices that @device_map holds.
|
||||
*
|
||||
* Returns: (element-type Meta.Device) (transfer container): the list
|
||||
* of devices, the contained objects are owned by @device_map
|
||||
* and should not be unref'ed. The list must be freed with
|
||||
* g_list_free().
|
||||
**/
|
||||
GList *
|
||||
meta_device_map_list_devices (MetaDeviceMap *device_map)
|
||||
{
|
||||
MetaDeviceMapPrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
|
||||
|
||||
priv = device_map->priv;
|
||||
return g_hash_table_get_values (priv->devices);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_map_grab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers,
|
||||
gboolean sync)
|
||||
{
|
||||
MetaDeviceMapClass *klass;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
|
||||
klass = META_DEVICE_MAP_GET_CLASS (device_map);
|
||||
|
||||
if (!klass->grab_key)
|
||||
return FALSE;
|
||||
|
||||
return (klass->grab_key) (device_map, xwindow, keycode, modifiers, sync);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_map_ungrab_key (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint keycode,
|
||||
guint modifiers)
|
||||
{
|
||||
MetaDeviceMapClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE_MAP (device_map));
|
||||
g_return_if_fail (xwindow != None);
|
||||
|
||||
klass = META_DEVICE_MAP_GET_CLASS (device_map);
|
||||
|
||||
if (klass->ungrab_key)
|
||||
(klass->ungrab_key) (device_map, xwindow, keycode, modifiers);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_map_grab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers,
|
||||
guint evmask,
|
||||
gboolean sync)
|
||||
{
|
||||
MetaDeviceMapClass *klass;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
|
||||
klass = META_DEVICE_MAP_GET_CLASS (device_map);
|
||||
|
||||
if (!klass->grab_button)
|
||||
return FALSE;
|
||||
|
||||
return (klass->grab_button) (device_map, xwindow, n_button,
|
||||
modifiers, evmask, sync);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_map_ungrab_button (MetaDeviceMap *device_map,
|
||||
Window xwindow,
|
||||
guint n_button,
|
||||
guint modifiers)
|
||||
{
|
||||
MetaDeviceMapClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE_MAP (device_map));
|
||||
g_return_if_fail (xwindow != None);
|
||||
|
||||
klass = META_DEVICE_MAP_GET_CLASS (device_map);
|
||||
|
||||
if (klass->ungrab_button)
|
||||
(klass->ungrab_button) (device_map, xwindow, n_button, modifiers);
|
||||
}
|
124
src/core/device-pointer.c
Normal file
124
src/core/device-pointer.c
Normal file
@ -0,0 +1,124 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Pointer device abstraction */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "device-pointer.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaDevicePointer,
|
||||
meta_device_pointer,
|
||||
META_TYPE_DEVICE)
|
||||
|
||||
static void
|
||||
meta_device_pointer_class_init (MetaDevicePointerClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_init (MetaDevicePointer *pointer)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_pointer_warp (MetaDevicePointer *pointer,
|
||||
MetaScreen *screen,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
MetaDevicePointerClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE_POINTER (pointer));
|
||||
g_return_if_fail (META_IS_SCREEN (screen));
|
||||
|
||||
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
|
||||
|
||||
if (klass->warp)
|
||||
(klass->warp) (pointer, screen, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_pointer_set_window_cursor (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaDevicePointerClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE_POINTER (pointer));
|
||||
g_return_if_fail (xwindow != None);
|
||||
|
||||
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
|
||||
|
||||
if (klass->set_window_cursor)
|
||||
(klass->set_window_cursor) (pointer, xwindow, cursor);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_pointer_query_position (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
Window *root_ret,
|
||||
Window *child_ret,
|
||||
gint *root_x_ret,
|
||||
gint *root_y_ret,
|
||||
gint *x_ret,
|
||||
gint *y_ret,
|
||||
guint *mask_ret)
|
||||
{
|
||||
MetaDevicePointerClass *klass;
|
||||
gint root_x, root_y, x, y;
|
||||
Window root, child;
|
||||
gboolean retval;
|
||||
guint mask;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE_POINTER (pointer), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
|
||||
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
|
||||
|
||||
if (!klass->query_position)
|
||||
return FALSE;
|
||||
|
||||
retval = (klass->query_position) (pointer, xwindow, &root, &child,
|
||||
&root_x, &root_y, &x, &y, &mask);
|
||||
|
||||
if (root_ret)
|
||||
*root_ret = root;
|
||||
|
||||
if (child_ret)
|
||||
*child_ret = child;
|
||||
|
||||
if (root_x_ret)
|
||||
*root_x_ret = root_x;
|
||||
|
||||
if (root_y_ret)
|
||||
*root_y_ret = root_y;
|
||||
|
||||
if (x_ret)
|
||||
*x_ret = x;
|
||||
|
||||
if (y_ret)
|
||||
*y_ret = y;
|
||||
|
||||
if (mask_ret)
|
||||
*mask_ret = mask;
|
||||
|
||||
return retval;
|
||||
}
|
95
src/core/device-pointer.h
Normal file
95
src/core/device-pointer.h
Normal file
@ -0,0 +1,95 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device-pointer.h Pointer device abstraction
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the internal abstraction of pointer devices so
|
||||
* XInput2/core events can be handled similarly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_POINTER_H
|
||||
#define META_DEVICE_POINTER_H
|
||||
|
||||
#include "display-private.h"
|
||||
#include <meta/screen.h>
|
||||
#include "device-private.h"
|
||||
|
||||
#define META_TYPE_DEVICE_POINTER (meta_device_pointer_get_type ())
|
||||
#define META_DEVICE_POINTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER, MetaDevicePointer))
|
||||
#define META_DEVICE_POINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER, MetaDevicePointerClass))
|
||||
#define META_IS_DEVICE_POINTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER))
|
||||
#define META_IS_DEVICE_POINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER))
|
||||
#define META_DEVICE_POINTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER, MetaDevicePointerClass))
|
||||
|
||||
typedef struct _MetaDevicePointer MetaDevicePointer;
|
||||
typedef struct _MetaDevicePointerClass MetaDevicePointerClass;
|
||||
|
||||
struct _MetaDevicePointer
|
||||
{
|
||||
MetaDevice parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDevicePointerClass
|
||||
{
|
||||
MetaDeviceClass parent_instance;
|
||||
|
||||
void (* warp) (MetaDevicePointer *pointer,
|
||||
MetaScreen *screen,
|
||||
gint x,
|
||||
gint y);
|
||||
|
||||
void (* set_window_cursor) (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
MetaCursor cursor);
|
||||
gboolean (* query_position) (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
Window *root,
|
||||
Window *child,
|
||||
gint *root_x,
|
||||
gint *root_y,
|
||||
gint *x,
|
||||
gint *y,
|
||||
guint *mask);
|
||||
};
|
||||
|
||||
GType meta_device_pointer_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void meta_device_pointer_warp (MetaDevicePointer *pointer,
|
||||
MetaScreen *screen,
|
||||
gint x,
|
||||
gint y);
|
||||
void meta_device_pointer_set_window_cursor (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
MetaCursor cursor);
|
||||
|
||||
gboolean meta_device_pointer_query_position (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
Window *root,
|
||||
Window *child,
|
||||
gint *root_x,
|
||||
gint *root_y,
|
||||
gint *x,
|
||||
gint *y,
|
||||
guint *mask);
|
||||
|
||||
#endif /* META_DEVICE_POINTER_H */
|
80
src/core/device-private.h
Normal file
80
src/core/device-private.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file device.h Input device abstraction
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the internal abstraction of input devices so
|
||||
* XInput2/core events can be handled similarly.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_PRIVATE_H
|
||||
#define META_DEVICE_PRIVATE_H
|
||||
|
||||
#include <meta/device.h>
|
||||
#include "display-private.h"
|
||||
|
||||
struct _MetaDevice
|
||||
{
|
||||
GObject parent_instance;
|
||||
gpointer priv;
|
||||
};
|
||||
|
||||
struct _MetaDeviceClass
|
||||
{
|
||||
GObjectClass parent_instance;
|
||||
|
||||
void (* allow_events) (MetaDevice *device,
|
||||
int mode,
|
||||
Time time);
|
||||
|
||||
gboolean (* grab) (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time);
|
||||
void (* ungrab) (MetaDevice *device,
|
||||
Time time);
|
||||
};
|
||||
|
||||
GType meta_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void meta_device_allow_events (MetaDevice *device,
|
||||
int mode,
|
||||
Time time);
|
||||
|
||||
gboolean meta_device_grab (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time);
|
||||
void meta_device_ungrab (MetaDevice *device,
|
||||
Time time);
|
||||
|
||||
void meta_device_pair_devices (MetaDevice *device,
|
||||
MetaDevice *other_device);
|
||||
|
||||
#endif /* META_DEVICE_PRIVATE_H */
|
270
src/core/device.c
Normal file
270
src/core/device.c
Normal file
@ -0,0 +1,270 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Input device abstraction */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "device-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (MetaDevice, meta_device, G_TYPE_OBJECT)
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DEVICE_ID,
|
||||
PROP_DISPLAY,
|
||||
PROP_PAIRED_DEVICE
|
||||
};
|
||||
|
||||
typedef struct MetaDevicePrivate MetaDevicePrivate;
|
||||
|
||||
struct MetaDevicePrivate
|
||||
{
|
||||
MetaDisplay *display;
|
||||
MetaDevice *paired_device;
|
||||
gint device_id;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_device_get_property (GObject *object,
|
||||
guint param_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DEVICE_ID:
|
||||
g_value_set_int (value,
|
||||
meta_device_get_id (META_DEVICE (object)));
|
||||
break;
|
||||
case PROP_DISPLAY:
|
||||
g_value_set_object (value,
|
||||
meta_device_get_display (META_DEVICE (object)));
|
||||
break;
|
||||
case PROP_PAIRED_DEVICE:
|
||||
g_value_set_object (value,
|
||||
meta_device_get_paired_device (META_DEVICE (object)));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_set_property (GObject *object,
|
||||
guint param_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaDevicePrivate *priv = META_DEVICE (object)->priv;
|
||||
|
||||
switch (param_id)
|
||||
{
|
||||
case PROP_DEVICE_ID:
|
||||
priv->device_id = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_DISPLAY:
|
||||
priv->display = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_PAIRED_DEVICE:
|
||||
meta_device_pair_devices (META_DEVICE (object),
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_class_init (MetaDeviceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = meta_device_get_property;
|
||||
object_class->set_property = meta_device_set_property;
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DEVICE_ID,
|
||||
g_param_spec_int ("device-id",
|
||||
"Device ID",
|
||||
"Device ID",
|
||||
2, G_MAXINT, 2,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DISPLAY,
|
||||
g_param_spec_object ("display",
|
||||
"Display",
|
||||
"Display",
|
||||
META_TYPE_DISPLAY,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_PAIRED_DEVICE,
|
||||
g_param_spec_object ("paired-device",
|
||||
"Paired device",
|
||||
"Paired device",
|
||||
META_TYPE_DEVICE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaDevicePrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_init (MetaDevice *device)
|
||||
{
|
||||
device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
|
||||
META_TYPE_DEVICE,
|
||||
MetaDevicePrivate);
|
||||
}
|
||||
|
||||
int
|
||||
meta_device_get_id (MetaDevice *device)
|
||||
{
|
||||
MetaDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE (device), 0);
|
||||
|
||||
priv = device->priv;
|
||||
return priv->device_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_device_get_display:
|
||||
* @device: a #MetaDevice
|
||||
*
|
||||
* Returns the #MetaDisplay to which the device belongs
|
||||
*
|
||||
* Returns: (transfer none): the #MetaDisplay to which the device belongs
|
||||
**/
|
||||
MetaDisplay *
|
||||
meta_device_get_display (MetaDevice *device)
|
||||
{
|
||||
MetaDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE (device), NULL);
|
||||
|
||||
priv = device->priv;
|
||||
return priv->display;
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_allow_events (MetaDevice *device,
|
||||
int mode,
|
||||
Time time)
|
||||
{
|
||||
MetaDeviceClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE (device));
|
||||
|
||||
klass = META_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (klass->allow_events)
|
||||
(klass->allow_events) (device, mode, time);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_grab (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time)
|
||||
{
|
||||
MetaDeviceClass *klass;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (xwindow != None, FALSE);
|
||||
|
||||
klass = META_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (!klass->grab)
|
||||
return FALSE;
|
||||
|
||||
return (klass->grab) (device, xwindow, evmask, cursor,
|
||||
owner_events, sync, time);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_ungrab (MetaDevice *device,
|
||||
Time time)
|
||||
{
|
||||
MetaDeviceClass *klass;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE (device));
|
||||
|
||||
klass = META_DEVICE_GET_CLASS (device);
|
||||
|
||||
if (klass->ungrab)
|
||||
(klass->ungrab) (device, time);
|
||||
}
|
||||
|
||||
void
|
||||
meta_device_pair_devices (MetaDevice *device,
|
||||
MetaDevice *other_device)
|
||||
{
|
||||
MetaDevicePrivate *priv1, *priv2;
|
||||
|
||||
g_return_if_fail (META_IS_DEVICE (device));
|
||||
g_return_if_fail (META_IS_DEVICE (other_device));
|
||||
|
||||
priv1 = device->priv;
|
||||
priv2 = other_device->priv;
|
||||
|
||||
/* Consider safe multiple calls
|
||||
* on already paired devices
|
||||
*/
|
||||
if (priv1->paired_device != NULL &&
|
||||
priv2->paired_device != NULL &&
|
||||
priv1->paired_device == other_device &&
|
||||
priv2->paired_device == device)
|
||||
return;
|
||||
|
||||
g_return_if_fail (priv1->paired_device == NULL);
|
||||
g_return_if_fail (priv2->paired_device == NULL);
|
||||
|
||||
priv1->paired_device = g_object_ref (other_device);
|
||||
priv2->paired_device = g_object_ref (device);
|
||||
|
||||
g_object_notify (G_OBJECT (device), "paired-device");
|
||||
g_object_notify (G_OBJECT (other_device), "paired-device");
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_device_get_paired_device:
|
||||
* @device: a #MetaDevice
|
||||
*
|
||||
* Returns the paired device. Devices come in keyboard/pointer pairs.
|
||||
*
|
||||
* Returns: (transfer none): The paired device.
|
||||
**/
|
||||
MetaDevice *
|
||||
meta_device_get_paired_device (MetaDevice *device)
|
||||
{
|
||||
MetaDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (META_IS_DEVICE (device), NULL);
|
||||
|
||||
priv = device->priv;
|
||||
return priv->paired_device;
|
||||
}
|
256
src/core/devices-core.c
Normal file
256
src/core/devices-core.c
Normal file
@ -0,0 +1,256 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Core input devices implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "screen-private.h"
|
||||
#include "devices-core.h"
|
||||
#include "device-map-private.h"
|
||||
|
||||
/* Common functions */
|
||||
static void
|
||||
meta_device_core_common_allow_events (MetaDevice *device,
|
||||
int mode,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
XAllowEvents (display->xdisplay, mode, time);
|
||||
}
|
||||
|
||||
/* Core pointer */
|
||||
|
||||
G_DEFINE_TYPE (MetaDevicePointerCore,
|
||||
meta_device_pointer_core,
|
||||
META_TYPE_DEVICE_POINTER)
|
||||
|
||||
static gboolean
|
||||
meta_device_pointer_core_grab (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Cursor xcursor;
|
||||
int retval;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||
|
||||
retval = XGrabPointer (display->xdisplay,
|
||||
xwindow, owner_events,
|
||||
evmask,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
None, xcursor, time);
|
||||
|
||||
if (xcursor != None)
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_core_ungrab (MetaDevice *device,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
XUngrabPointer (display->xdisplay, time);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_core_warp (MetaDevicePointer *pointer,
|
||||
MetaScreen *screen,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
XWarpPointer (display->xdisplay,
|
||||
None, screen->xroot,
|
||||
0, 0, 0, 0, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_core_set_window_cursor (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Cursor xcursor;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||
|
||||
XDefineCursor (display->xdisplay, xwindow, xcursor);
|
||||
|
||||
if (xcursor != None)
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_device_pointer_core_query_position (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
Window *root,
|
||||
Window *child,
|
||||
gint *root_x,
|
||||
gint *root_y,
|
||||
gint *x,
|
||||
gint *y,
|
||||
guint *mask)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
return XQueryPointer (display->xdisplay, xwindow,
|
||||
root, child, root_x, root_y,
|
||||
x, y, mask);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_core_class_init (MetaDevicePointerCoreClass *klass)
|
||||
{
|
||||
MetaDevicePointerClass *pointer_class = META_DEVICE_POINTER_CLASS (klass);
|
||||
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->allow_events = meta_device_core_common_allow_events;
|
||||
device_class->grab = meta_device_pointer_core_grab;
|
||||
device_class->ungrab = meta_device_pointer_core_ungrab;
|
||||
|
||||
pointer_class->warp = meta_device_pointer_core_warp;
|
||||
pointer_class->set_window_cursor = meta_device_pointer_core_set_window_cursor;
|
||||
pointer_class->query_position = meta_device_pointer_core_query_position;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_core_init (MetaDevicePointerCore *pointer)
|
||||
{
|
||||
}
|
||||
|
||||
MetaDevice *
|
||||
meta_device_pointer_core_new (MetaDisplay *display)
|
||||
{
|
||||
return g_object_new (META_TYPE_DEVICE_POINTER_CORE,
|
||||
"device-id", META_CORE_POINTER_ID,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/* Core Keyboard */
|
||||
|
||||
G_DEFINE_TYPE (MetaDeviceKeyboardCore,
|
||||
meta_device_keyboard_core,
|
||||
META_TYPE_DEVICE_KEYBOARD)
|
||||
|
||||
static gboolean
|
||||
meta_device_keyboard_core_grab (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
gint retval;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
retval = XGrabKeyboard (display->xdisplay, xwindow, owner_events,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
time);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_core_ungrab (MetaDevice *device,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
XUngrabKeyboard (display->xdisplay, time);
|
||||
}
|
||||
|
||||
static Window
|
||||
meta_device_keyboard_core_get_focus_window (MetaDeviceKeyboard *keyboard)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Window xwindow;
|
||||
int unused;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (keyboard));
|
||||
XGetInputFocus (display->xdisplay, &xwindow, &unused);
|
||||
|
||||
return xwindow;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_core_set_focus_window (MetaDeviceKeyboard *keyboard,
|
||||
Window xwindow,
|
||||
Time timestamp)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (keyboard));
|
||||
XSetInputFocus (display->xdisplay,
|
||||
xwindow,
|
||||
RevertToPointerRoot,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_core_class_init (MetaDeviceKeyboardCoreClass *klass)
|
||||
{
|
||||
MetaDeviceKeyboardClass *keyboard_class = META_DEVICE_KEYBOARD_CLASS (klass);
|
||||
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
|
||||
|
||||
keyboard_class->get_focus_window = meta_device_keyboard_core_get_focus_window;
|
||||
keyboard_class->set_focus_window = meta_device_keyboard_core_set_focus_window;
|
||||
|
||||
device_class->allow_events = meta_device_core_common_allow_events;
|
||||
device_class->grab = meta_device_keyboard_core_grab;
|
||||
device_class->ungrab = meta_device_keyboard_core_ungrab;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_core_init (MetaDeviceKeyboardCore *keyboard)
|
||||
{
|
||||
}
|
||||
|
||||
MetaDevice *
|
||||
meta_device_keyboard_core_new (MetaDisplay *display)
|
||||
{
|
||||
return g_object_new (META_TYPE_DEVICE_KEYBOARD_CORE,
|
||||
"device-id", META_CORE_KEYBOARD_ID,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
85
src/core/devices-core.h
Normal file
85
src/core/devices-core.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file devices-core.h Core input devices implementation
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the core X protocol implementation of input devices.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICES_CORE_H
|
||||
#define META_DEVICES_CORE_H
|
||||
|
||||
#include "device-pointer.h"
|
||||
#include "device-keyboard.h"
|
||||
|
||||
/* Pointer */
|
||||
#define META_TYPE_DEVICE_POINTER_CORE (meta_device_pointer_core_get_type ())
|
||||
#define META_DEVICE_POINTER_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCore))
|
||||
#define META_DEVICE_POINTER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCoreClass))
|
||||
#define META_IS_DEVICE_POINTER_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER_CORE))
|
||||
#define META_IS_DEVICE_POINTER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER_CORE))
|
||||
#define META_DEVICE_POINTER_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCoreClass))
|
||||
|
||||
typedef struct _MetaDevicePointerCore MetaDevicePointerCore;
|
||||
typedef struct _MetaDevicePointerCoreClass MetaDevicePointerCoreClass;
|
||||
|
||||
struct _MetaDevicePointerCore
|
||||
{
|
||||
MetaDevicePointer parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDevicePointerCoreClass
|
||||
{
|
||||
MetaDevicePointerClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_pointer_core_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDevice *meta_device_pointer_core_new (MetaDisplay *display);
|
||||
|
||||
/* Keyboard */
|
||||
#define META_TYPE_DEVICE_KEYBOARD_CORE (meta_device_keyboard_core_get_type ())
|
||||
#define META_DEVICE_KEYBOARD_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCore))
|
||||
#define META_DEVICE_KEYBOARD_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCoreClass))
|
||||
#define META_IS_DEVICE_KEYBOARD_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD_CORE))
|
||||
#define META_IS_DEVICE_KEYBOARD_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD_CORE))
|
||||
#define META_DEVICE_KEYBOARD_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCoreClass))
|
||||
|
||||
typedef struct _MetaDeviceKeyboardCore MetaDeviceKeyboardCore;
|
||||
typedef struct _MetaDeviceKeyboardCoreClass MetaDeviceKeyboardCoreClass;
|
||||
|
||||
struct _MetaDeviceKeyboardCore
|
||||
{
|
||||
MetaDeviceKeyboard parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDeviceKeyboardCoreClass
|
||||
{
|
||||
MetaDeviceKeyboardClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_keyboard_core_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDevice *meta_device_keyboard_core_new (MetaDisplay *display);
|
||||
|
||||
#endif /* META_DEVICES_CORE_H */
|
343
src/core/devices-xi2.c
Normal file
343
src/core/devices-xi2.c
Normal file
@ -0,0 +1,343 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* XInput2 devices implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "devices-xi2.h"
|
||||
#include "display-private.h"
|
||||
#include "screen-private.h"
|
||||
#include <X11/extensions/XInput2.h>
|
||||
|
||||
/* Common functions */
|
||||
static void
|
||||
meta_device_xi2_common_allow_events (MetaDevice *device,
|
||||
int mode,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
gint device_id;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
device_id = meta_device_get_id (device);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case AsyncPointer:
|
||||
case AsyncKeyboard:
|
||||
mode = XIAsyncDevice;
|
||||
break;
|
||||
case SyncPointer:
|
||||
case SyncKeyboard:
|
||||
mode = XISyncDevice;
|
||||
break;
|
||||
case ReplayPointer:
|
||||
case ReplayKeyboard:
|
||||
mode = XIReplayDevice;
|
||||
break;
|
||||
case AsyncBoth:
|
||||
mode = XIAsyncPair;
|
||||
break;
|
||||
case SyncBoth:
|
||||
mode = XISyncPair;
|
||||
break;
|
||||
}
|
||||
|
||||
XIAllowEvents (display->xdisplay, device_id, mode, time);
|
||||
}
|
||||
|
||||
guchar *
|
||||
meta_device_xi2_translate_event_mask (guint evmask,
|
||||
gint *len)
|
||||
{
|
||||
guchar *mask;
|
||||
|
||||
*len = XIMaskLen (XI_LASTEVENT);
|
||||
mask = g_new0 (guchar, *len);
|
||||
|
||||
if (evmask & KeyPressMask)
|
||||
XISetMask (mask, XI_KeyPress);
|
||||
if (evmask & KeyReleaseMask)
|
||||
XISetMask (mask, XI_KeyRelease);
|
||||
if (evmask & ButtonPressMask)
|
||||
XISetMask (mask, XI_ButtonPress);
|
||||
if (evmask & ButtonReleaseMask)
|
||||
XISetMask (mask, XI_ButtonRelease);
|
||||
if (evmask & EnterWindowMask)
|
||||
XISetMask (mask, XI_Enter);
|
||||
if (evmask & LeaveWindowMask)
|
||||
XISetMask (mask, XI_Leave);
|
||||
|
||||
/* No motion hints in XI2 at the moment... */
|
||||
if (evmask & PointerMotionMask ||
|
||||
evmask & PointerMotionHintMask)
|
||||
XISetMask (mask, XI_Motion);
|
||||
|
||||
if (evmask & FocusChangeMask)
|
||||
{
|
||||
XISetMask (mask, XI_FocusIn);
|
||||
XISetMask (mask, XI_FocusOut);
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_device_xi2_common_grab (MetaDevice *device,
|
||||
Window xwindow,
|
||||
guint evmask,
|
||||
MetaCursor cursor,
|
||||
gboolean owner_events,
|
||||
gboolean sync,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
XIEventMask mask;
|
||||
gint device_id, retval;
|
||||
Cursor xcursor;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
device_id = meta_device_get_id (device);
|
||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||
|
||||
mask.deviceid = device_id;
|
||||
mask.mask = meta_device_xi2_translate_event_mask (evmask, &mask.mask_len);
|
||||
|
||||
retval = XIGrabDevice (display->xdisplay,
|
||||
device_id, xwindow,
|
||||
time, xcursor,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
(sync) ? GrabModeSync : GrabModeAsync,
|
||||
owner_events, &mask);
|
||||
|
||||
if (xcursor != None)
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
|
||||
return (retval == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_xi2_common_ungrab (MetaDevice *device,
|
||||
Time time)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
gint device_id;
|
||||
|
||||
display = meta_device_get_display (device);
|
||||
device_id = meta_device_get_id (device);
|
||||
|
||||
XIUngrabDevice (display->xdisplay, device_id, time);
|
||||
}
|
||||
|
||||
/* Pointer */
|
||||
|
||||
G_DEFINE_TYPE (MetaDevicePointerXI2,
|
||||
meta_device_pointer_xi2,
|
||||
META_TYPE_DEVICE_POINTER)
|
||||
|
||||
static void
|
||||
meta_device_pointer_xi2_warp (MetaDevicePointer *pointer,
|
||||
MetaScreen *screen,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
int device_id;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
device_id = meta_device_get_id (META_DEVICE (pointer));
|
||||
|
||||
XIWarpPointer (display->xdisplay,
|
||||
device_id,
|
||||
None, screen->xroot,
|
||||
0, 0, 0, 0, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_xi2_set_window_cursor (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Cursor xcursor;
|
||||
int device_id;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
device_id = meta_device_get_id (META_DEVICE (pointer));
|
||||
xcursor = meta_display_create_x_cursor (display, cursor);
|
||||
|
||||
if (xcursor != None)
|
||||
{
|
||||
XIDefineCursor (display->xdisplay, device_id, xwindow, xcursor);
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
}
|
||||
else
|
||||
XIUndefineCursor (display->xdisplay, device_id, xwindow);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_device_pointer_xi2_query_position (MetaDevicePointer *pointer,
|
||||
Window xwindow,
|
||||
Window *root_ret,
|
||||
Window *child_ret,
|
||||
gint *root_x_ret,
|
||||
gint *root_y_ret,
|
||||
gint *x_ret,
|
||||
gint *y_ret,
|
||||
guint *mask_ret)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
XIModifierState mods;
|
||||
XIGroupState group_unused;
|
||||
XIButtonState buttons;
|
||||
gdouble root_x, root_y, x, y;
|
||||
int device_id;
|
||||
gboolean retval;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (pointer));
|
||||
device_id = meta_device_get_id (META_DEVICE (pointer));
|
||||
|
||||
retval = XIQueryPointer (display->xdisplay,
|
||||
device_id, xwindow,
|
||||
root_ret, child_ret,
|
||||
&root_x, &root_y, &x, &y,
|
||||
&buttons, &mods,
|
||||
&group_unused);
|
||||
if (mask_ret)
|
||||
{
|
||||
*mask_ret = mods.effective;
|
||||
|
||||
if (XIMaskIsSet (buttons.mask, 1))
|
||||
*mask_ret |= Button1Mask;
|
||||
else if (XIMaskIsSet (buttons.mask, 2))
|
||||
*mask_ret |= Button2Mask;
|
||||
else if (XIMaskIsSet (buttons.mask, 3))
|
||||
*mask_ret |= Button3Mask;
|
||||
}
|
||||
|
||||
if (root_x_ret)
|
||||
*root_x_ret = (int) root_x;
|
||||
|
||||
if (root_y_ret)
|
||||
*root_y_ret = (int) root_y;
|
||||
|
||||
if (x_ret)
|
||||
*x_ret = (int) x;
|
||||
|
||||
if (y_ret)
|
||||
*y_ret = (int) y;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_xi2_class_init (MetaDevicePointerXI2Class *klass)
|
||||
{
|
||||
MetaDevicePointerClass *pointer_class = META_DEVICE_POINTER_CLASS (klass);
|
||||
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
|
||||
|
||||
device_class->allow_events = meta_device_xi2_common_allow_events;
|
||||
device_class->grab = meta_device_xi2_common_grab;
|
||||
device_class->ungrab = meta_device_xi2_common_ungrab;
|
||||
|
||||
pointer_class->warp = meta_device_pointer_xi2_warp;
|
||||
pointer_class->set_window_cursor = meta_device_pointer_xi2_set_window_cursor;
|
||||
pointer_class->query_position = meta_device_pointer_xi2_query_position;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_pointer_xi2_init (MetaDevicePointerXI2 *pointer)
|
||||
{
|
||||
}
|
||||
|
||||
MetaDevice *
|
||||
meta_device_pointer_xi2_new (MetaDisplay *display,
|
||||
gint device_id)
|
||||
{
|
||||
return g_object_new (META_TYPE_DEVICE_POINTER_XI2,
|
||||
"device-id", device_id,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Keyboard */
|
||||
|
||||
G_DEFINE_TYPE (MetaDeviceKeyboardXI2,
|
||||
meta_device_keyboard_xi2,
|
||||
META_TYPE_DEVICE_KEYBOARD)
|
||||
|
||||
static Window
|
||||
meta_device_keyboard_xi2_get_focus_window (MetaDeviceKeyboard *keyboard)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Window xwindow;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (keyboard));
|
||||
XIGetFocus (display->xdisplay,
|
||||
meta_device_get_id (META_DEVICE (keyboard)),
|
||||
&xwindow);
|
||||
|
||||
return xwindow;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_xi2_set_focus_window (MetaDeviceKeyboard *keyboard,
|
||||
Window xwindow,
|
||||
Time timestamp)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_device_get_display (META_DEVICE (keyboard));
|
||||
|
||||
XISetFocus (display->xdisplay,
|
||||
meta_device_get_id (META_DEVICE (keyboard)),
|
||||
xwindow,
|
||||
timestamp);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_xi2_class_init (MetaDeviceKeyboardXI2Class *klass)
|
||||
{
|
||||
MetaDeviceKeyboardClass *keyboard_class = META_DEVICE_KEYBOARD_CLASS (klass);
|
||||
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
|
||||
|
||||
keyboard_class->get_focus_window = meta_device_keyboard_xi2_get_focus_window;
|
||||
keyboard_class->set_focus_window = meta_device_keyboard_xi2_set_focus_window;
|
||||
|
||||
device_class->allow_events = meta_device_xi2_common_allow_events;
|
||||
device_class->grab = meta_device_xi2_common_grab;
|
||||
device_class->ungrab = meta_device_xi2_common_ungrab;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_device_keyboard_xi2_init (MetaDeviceKeyboardXI2 *keyboard)
|
||||
{
|
||||
}
|
||||
|
||||
MetaDevice *
|
||||
meta_device_keyboard_xi2_new (MetaDisplay *display,
|
||||
gint device_id)
|
||||
{
|
||||
return g_object_new (META_TYPE_DEVICE_KEYBOARD_XI2,
|
||||
"device-id", device_id,
|
||||
"display", display,
|
||||
NULL);
|
||||
}
|
92
src/core/devices-xi2.h
Normal file
92
src/core/devices-xi2.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file devices-xi2.h XInput2 input devices implementation
|
||||
*
|
||||
* Input devices.
|
||||
* This file contains the XInput2 implementation of input devices.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICES_XI2_H
|
||||
#define META_DEVICES_XI2_H
|
||||
|
||||
#include "device-pointer.h"
|
||||
#include "device-keyboard.h"
|
||||
|
||||
/* Pointer */
|
||||
#define META_TYPE_DEVICE_POINTER_XI2 (meta_device_pointer_xi2_get_type ())
|
||||
#define META_DEVICE_POINTER_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2))
|
||||
#define META_DEVICE_POINTER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2Class))
|
||||
#define META_IS_DEVICE_POINTER_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER_XI2))
|
||||
#define META_IS_DEVICE_POINTER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER_XI2))
|
||||
#define META_DEVICE_POINTER_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2Class))
|
||||
|
||||
typedef struct _MetaDevicePointerXI2 MetaDevicePointerXI2;
|
||||
typedef struct _MetaDevicePointerXI2Class MetaDevicePointerXI2Class;
|
||||
|
||||
struct _MetaDevicePointerXI2
|
||||
{
|
||||
MetaDevicePointer parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDevicePointerXI2Class
|
||||
{
|
||||
MetaDevicePointerClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_pointer_xi2_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDevice *meta_device_pointer_xi2_new (MetaDisplay *display,
|
||||
gint device_id);
|
||||
|
||||
/* Keyboard */
|
||||
#define META_TYPE_DEVICE_KEYBOARD_XI2 (meta_device_keyboard_xi2_get_type ())
|
||||
#define META_DEVICE_KEYBOARD_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2))
|
||||
#define META_DEVICE_KEYBOARD_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2Class))
|
||||
#define META_IS_DEVICE_KEYBOARD_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD_XI2))
|
||||
#define META_IS_DEVICE_KEYBOARD_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD_XI2))
|
||||
#define META_DEVICE_KEYBOARD_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2Class))
|
||||
|
||||
typedef struct _MetaDeviceKeyboardXI2 MetaDeviceKeyboardXI2;
|
||||
typedef struct _MetaDeviceKeyboardXI2Class MetaDeviceKeyboardXI2Class;
|
||||
|
||||
struct _MetaDeviceKeyboardXI2
|
||||
{
|
||||
MetaDeviceKeyboard parent_instance;
|
||||
};
|
||||
|
||||
struct _MetaDeviceKeyboardXI2Class
|
||||
{
|
||||
MetaDeviceKeyboardClass parent_class;
|
||||
};
|
||||
|
||||
GType meta_device_keyboard_xi2_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDevice *meta_device_keyboard_xi2_new (MetaDisplay *display,
|
||||
gint device_id);
|
||||
|
||||
/* Helper function for translating event masks */
|
||||
guchar * meta_device_xi2_translate_event_mask (guint evmask,
|
||||
gint *len);
|
||||
|
||||
|
||||
#endif /* META_DEVICES_XI2_H */
|
@ -38,6 +38,7 @@
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/display.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "device-map-private.h"
|
||||
#include <meta/prefs.h>
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
@ -56,6 +57,9 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
|
||||
|
||||
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
|
||||
|
||||
typedef struct _MetaGrabInfo MetaGrabInfo;
|
||||
typedef struct _MetaFocusInfo MetaFocusInfo;
|
||||
|
||||
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
guint32 timestamp,
|
||||
@ -84,6 +88,65 @@ typedef enum {
|
||||
META_TILE_MAXIMIZED
|
||||
} MetaTileMode;
|
||||
|
||||
struct _MetaGrabInfo
|
||||
{
|
||||
MetaDevice *grab_pointer;
|
||||
MetaDevice *grab_keyboard;
|
||||
|
||||
MetaGrabOp grab_op;
|
||||
MetaScreen *grab_screen;
|
||||
MetaWindow *grab_window;
|
||||
Window grab_xwindow;
|
||||
int grab_button;
|
||||
int grab_anchor_root_x;
|
||||
int grab_anchor_root_y;
|
||||
MetaRectangle grab_anchor_window_pos;
|
||||
MetaTileMode grab_tile_mode;
|
||||
int grab_latest_motion_x;
|
||||
int grab_latest_motion_y;
|
||||
gulong grab_mask;
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_frame_action : 1;
|
||||
/* During a resize operation, the directions in which we've broken
|
||||
* out of the initial maximization state */
|
||||
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
|
||||
XSyncAlarm grab_sync_request_alarm;
|
||||
#endif
|
||||
int grab_resize_timeout_id;
|
||||
};
|
||||
|
||||
struct _MetaFocusInfo
|
||||
{
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
*/
|
||||
MetaWindow *focus_window;
|
||||
|
||||
/* window we are expecting a FocusIn event for or the current focus
|
||||
* window if we are not expecting any FocusIn/FocusOut events; not
|
||||
* perfect because applications can call XSetInputFocus directly.
|
||||
* (It could also be messed up if a timestamp later than current
|
||||
* time is sent to meta_display_set_input_focus_window, though that
|
||||
* would be a programming error). See bug 154598 for more info.
|
||||
*/
|
||||
MetaWindow *expected_focus_window;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
guint32 last_focus_time;
|
||||
};
|
||||
|
||||
struct _MetaDisplay
|
||||
{
|
||||
GObject parent_instance;
|
||||
@ -102,22 +165,8 @@ struct _MetaDisplay
|
||||
#include <meta/atomnames.h>
|
||||
#undef item
|
||||
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
*/
|
||||
MetaWindow *focus_window;
|
||||
|
||||
/* window we are expecting a FocusIn event for or the current focus
|
||||
* window if we are not expecting any FocusIn/FocusOut events; not
|
||||
* perfect because applications can call XSetInputFocus directly.
|
||||
* (It could also be messed up if a timestamp later than current
|
||||
* time is sent to meta_display_set_input_focus_window, though that
|
||||
* would be a programming error). See bug 154598 for more info.
|
||||
*/
|
||||
MetaWindow *expected_focus_window;
|
||||
|
||||
/* last timestamp passed to XSetInputFocus */
|
||||
guint32 last_focus_time;
|
||||
/* keyboard -> MetaFocusInfo hashtable */
|
||||
GHashTable *focus_info;
|
||||
|
||||
/* last user interaction time in any app */
|
||||
guint32 last_user_time;
|
||||
@ -177,34 +226,11 @@ struct _MetaDisplay
|
||||
/* Alt+click button grabs */
|
||||
unsigned int window_grab_modifiers;
|
||||
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
MetaScreen *grab_screen;
|
||||
MetaWindow *grab_window;
|
||||
Window grab_xwindow;
|
||||
int grab_button;
|
||||
int grab_anchor_root_x;
|
||||
int grab_anchor_root_y;
|
||||
MetaRectangle grab_anchor_window_pos;
|
||||
MetaTileMode grab_tile_mode;
|
||||
int grab_latest_motion_x;
|
||||
int grab_latest_motion_y;
|
||||
gulong grab_mask;
|
||||
guint grab_have_pointer : 1;
|
||||
guint grab_have_keyboard : 1;
|
||||
guint grab_frame_action : 1;
|
||||
/* During a resize operation, the directions in which we've broken
|
||||
* out of the initial maximization state */
|
||||
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
|
||||
MetaRectangle grab_initial_window_pos;
|
||||
int grab_initial_x, grab_initial_y; /* These are only relevant for */
|
||||
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
|
||||
MetaResizePopup *grab_resize_popup;
|
||||
GTimeVal grab_last_moveresize_time;
|
||||
guint32 grab_motion_notify_time;
|
||||
GList* grab_old_window_stacking;
|
||||
MetaEdgeResistanceData *grab_edge_resistance_data;
|
||||
unsigned int grab_last_user_action_was_snap;
|
||||
/* per-device current window operation */
|
||||
GHashTable *current_grabs;
|
||||
|
||||
/* per-screen edge resistance cache */
|
||||
GHashTable *edge_resistance_info;
|
||||
|
||||
/* we use property updates as sentinels for certain window focus events
|
||||
* to avoid some race conditions on EnterNotify events
|
||||
@ -215,11 +241,6 @@ struct _MetaDisplay
|
||||
int xkb_base_event_type;
|
||||
guint32 last_bell_time;
|
||||
#endif
|
||||
#ifdef HAVE_XSYNC
|
||||
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
|
||||
XSyncAlarm grab_sync_request_alarm;
|
||||
#endif
|
||||
int grab_resize_timeout_id;
|
||||
|
||||
/* Keybindings stuff */
|
||||
MetaKeyBinding *key_bindings;
|
||||
@ -266,6 +287,9 @@ struct _MetaDisplay
|
||||
/* Managed by compositor.c */
|
||||
MetaCompositor *compositor;
|
||||
|
||||
/* Managed by device-map.c */
|
||||
MetaDeviceMap *device_map;
|
||||
|
||||
int render_event_base;
|
||||
int render_error_base;
|
||||
|
||||
@ -289,6 +313,12 @@ struct _MetaDisplay
|
||||
int shape_event_base;
|
||||
int shape_error_base;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
int xinput2_opcode;
|
||||
unsigned int have_xinput2 : 1;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XSYNC
|
||||
unsigned int have_xsync : 1;
|
||||
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
|
||||
@ -378,12 +408,14 @@ Cursor meta_display_create_x_cursor (MetaDisplay *display,
|
||||
|
||||
void meta_display_set_grab_op_cursor (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaDevice *device,
|
||||
MetaGrabOp op,
|
||||
gboolean change_pointer,
|
||||
Window grab_xwindow,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_display_check_threshold_reached (MetaDisplay *display,
|
||||
MetaDevice *device,
|
||||
int x,
|
||||
int y);
|
||||
void meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
@ -397,7 +429,8 @@ void meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window);
|
||||
|
||||
/* Next function is defined in edge-resistance.c */
|
||||
void meta_display_cleanup_edges (MetaDisplay *display);
|
||||
void meta_display_cleanup_edges (MetaDisplay *display,
|
||||
MetaScreen *screen);
|
||||
|
||||
/* make a request to ensure the event serial has changed */
|
||||
void meta_display_increment_event_serial (MetaDisplay *display);
|
||||
@ -445,4 +478,15 @@ void meta_display_overlay_key_activate (MetaDisplay *display);
|
||||
/* In above-tab-keycode.c */
|
||||
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
||||
|
||||
MetaGrabInfo * meta_display_create_grab_info (MetaDisplay *display,
|
||||
MetaDevice *device);
|
||||
void meta_display_remove_grab_info (MetaDisplay *display,
|
||||
MetaDevice *device);
|
||||
|
||||
MetaGrabInfo * meta_display_get_grab_info (MetaDisplay *display,
|
||||
MetaDevice *device);
|
||||
MetaFocusInfo * meta_display_get_focus_info (MetaDisplay *display,
|
||||
MetaDevice *device);
|
||||
|
||||
|
||||
#endif
|
||||
|
2920
src/core/display.c
2920
src/core/display.c
File diff suppressed because it is too large
Load Diff
@ -30,12 +30,12 @@
|
||||
/* A simple macro for whether a given window's edges are potentially
|
||||
* relevant for resistance/snapping during a move/resize operation
|
||||
*/
|
||||
#define WINDOW_EDGES_RELEVANT(window, display) \
|
||||
meta_window_should_be_showing (window) && \
|
||||
window->screen == display->grab_screen && \
|
||||
window != display->grab_window && \
|
||||
window->type != META_WINDOW_DESKTOP && \
|
||||
window->type != META_WINDOW_MENU && \
|
||||
#define WINDOW_EDGES_RELEVANT(window, display, screen) \
|
||||
meta_window_should_be_showing (window) && \
|
||||
window->screen == screen && \
|
||||
window->cur_grab == NULL && \
|
||||
window->type != META_WINDOW_DESKTOP && \
|
||||
window->type != META_WINDOW_MENU && \
|
||||
window->type != META_WINDOW_SPLASHSCREEN
|
||||
|
||||
struct ResistanceDataForAnEdge
|
||||
@ -44,8 +44,9 @@ struct ResistanceDataForAnEdge
|
||||
guint timeout_id;
|
||||
int timeout_edge_pos;
|
||||
gboolean timeout_over;
|
||||
GSourceFunc timeout_func;
|
||||
MetaEdgeResistanceFunc timeout_func;
|
||||
MetaWindow *window;
|
||||
MetaDevice *device;
|
||||
int keyboard_buildup;
|
||||
};
|
||||
typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge;
|
||||
@ -63,7 +64,9 @@ struct MetaEdgeResistanceData
|
||||
ResistanceDataForAnEdge bottom_data;
|
||||
};
|
||||
|
||||
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
|
||||
static MetaEdgeResistanceData *
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display,
|
||||
MetaScreen *screen);
|
||||
|
||||
/* !WARNING!: this function can return invalid indices (namely, either -1 or
|
||||
* edges->len); this is by design, but you need to remember this.
|
||||
@ -318,20 +321,22 @@ edge_resistance_timeout (gpointer data)
|
||||
|
||||
resistance_data->timeout_over = TRUE;
|
||||
resistance_data->timeout_id = 0;
|
||||
(*resistance_data->timeout_func)(resistance_data->window);
|
||||
(*resistance_data->timeout_func) (resistance_data->window,
|
||||
resistance_data->device);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
apply_edge_resistance (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int old_pos,
|
||||
int new_pos,
|
||||
const MetaRectangle *old_rect,
|
||||
const MetaRectangle *new_rect,
|
||||
GArray *edges,
|
||||
ResistanceDataForAnEdge *resistance_data,
|
||||
GSourceFunc timeout_func,
|
||||
MetaEdgeResistanceFunc timeout_func,
|
||||
gboolean xdir,
|
||||
gboolean keyboard_op)
|
||||
{
|
||||
@ -445,6 +450,7 @@ apply_edge_resistance (MetaWindow *window,
|
||||
resistance_data->timeout_over = FALSE;
|
||||
resistance_data->timeout_func = timeout_func;
|
||||
resistance_data->window = window;
|
||||
resistance_data->device = device;
|
||||
}
|
||||
if (!resistance_data->timeout_over &&
|
||||
timeout_length_ms != 0)
|
||||
@ -533,29 +539,28 @@ apply_edge_snapping (int old_pos,
|
||||
* a proposed new position (ignoring edge resistance/snapping), and then
|
||||
* applies edge resistance to EACH edge (separately) updating new_outer.
|
||||
* It returns true if new_outer is modified, false otherwise.
|
||||
*
|
||||
* display->grab_edge_resistance_data MUST already be setup or calling this
|
||||
* function will cause a crash.
|
||||
*/
|
||||
static gboolean
|
||||
apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
const MetaRectangle *old_outer,
|
||||
MetaRectangle *new_outer,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean auto_snap,
|
||||
gboolean keyboard_op,
|
||||
gboolean is_resize)
|
||||
apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
const MetaRectangle *old_outer,
|
||||
MetaRectangle *new_outer,
|
||||
MetaEdgeResistanceFunc timeout_func,
|
||||
gboolean auto_snap,
|
||||
gboolean keyboard_op,
|
||||
gboolean is_resize)
|
||||
{
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
MetaRectangle modified_rect;
|
||||
gboolean modified;
|
||||
int new_left, new_right, new_top, new_bottom;
|
||||
|
||||
if (display->grab_edge_resistance_data == NULL)
|
||||
compute_resistance_and_snapping_edges (display);
|
||||
edge_data = g_hash_table_lookup (display->edge_resistance_info,
|
||||
window->screen);
|
||||
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
if (!edge_data)
|
||||
edge_data = compute_resistance_and_snapping_edges (display, window->screen);
|
||||
|
||||
if (auto_snap)
|
||||
{
|
||||
@ -601,7 +606,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
if (!is_resize || window->size_hints.width_inc == 1)
|
||||
{
|
||||
/* Now, apply the normal horizontal edge resistance */
|
||||
new_left = apply_edge_resistance (window,
|
||||
new_left = apply_edge_resistance (window, device,
|
||||
BOX_LEFT (*old_outer),
|
||||
BOX_LEFT (*new_outer),
|
||||
old_outer,
|
||||
@ -611,7 +616,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
timeout_func,
|
||||
TRUE,
|
||||
keyboard_op);
|
||||
new_right = apply_edge_resistance (window,
|
||||
new_right = apply_edge_resistance (window, device,
|
||||
BOX_RIGHT (*old_outer),
|
||||
BOX_RIGHT (*new_outer),
|
||||
old_outer,
|
||||
@ -630,7 +635,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
/* Same for vertical resizes... */
|
||||
if (!is_resize || window->size_hints.height_inc == 1)
|
||||
{
|
||||
new_top = apply_edge_resistance (window,
|
||||
new_top = apply_edge_resistance (window, device,
|
||||
BOX_TOP (*old_outer),
|
||||
BOX_TOP (*new_outer),
|
||||
old_outer,
|
||||
@ -640,7 +645,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
timeout_func,
|
||||
FALSE,
|
||||
keyboard_op);
|
||||
new_bottom = apply_edge_resistance (window,
|
||||
new_bottom = apply_edge_resistance (window, device,
|
||||
BOX_BOTTOM (*old_outer),
|
||||
BOX_BOTTOM (*new_outer),
|
||||
old_outer,
|
||||
@ -669,15 +674,20 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_cleanup_edges (MetaDisplay *display)
|
||||
meta_display_cleanup_edges (MetaDisplay *display,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
guint i,j;
|
||||
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
GHashTable *edges_to_be_freed;
|
||||
|
||||
edge_data = g_hash_table_lookup (display->edge_resistance_info, screen);
|
||||
|
||||
if (edge_data == NULL) /* Not currently cached */
|
||||
return;
|
||||
|
||||
g_hash_table_steal (display->edge_resistance_info, screen);
|
||||
|
||||
/* We first need to clean out any window edges */
|
||||
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||
g_free, NULL);
|
||||
@ -750,8 +760,7 @@ meta_display_cleanup_edges (MetaDisplay *display)
|
||||
edge_data->bottom_data.timeout_id != 0)
|
||||
g_source_remove (edge_data->bottom_data.timeout_id);
|
||||
|
||||
g_free (display->grab_edge_resistance_data);
|
||||
display->grab_edge_resistance_data = NULL;
|
||||
g_free (edge_data);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -763,8 +772,9 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
|
||||
return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge);
|
||||
}
|
||||
|
||||
static void
|
||||
static MetaEdgeResistanceData *
|
||||
cache_edges (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
GList *window_edges,
|
||||
GList *monitor_edges,
|
||||
GList *screen_edges)
|
||||
@ -848,9 +858,8 @@ cache_edges (MetaDisplay *display,
|
||||
/*
|
||||
* 2nd: Allocate the edges
|
||||
*/
|
||||
g_assert (display->grab_edge_resistance_data == NULL);
|
||||
display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1);
|
||||
edge_data = display->grab_edge_resistance_data;
|
||||
edge_data = g_new0 (MetaEdgeResistanceData, 1);
|
||||
|
||||
edge_data->left_edges = g_array_sized_new (FALSE,
|
||||
FALSE,
|
||||
sizeof(MetaEdge*),
|
||||
@ -917,21 +926,21 @@ cache_edges (MetaDisplay *display,
|
||||
* avoided this sort by sticking them into the array with some simple
|
||||
* merging of the lists).
|
||||
*/
|
||||
g_array_sort (display->grab_edge_resistance_data->left_edges,
|
||||
g_array_sort (edge_data->left_edges,
|
||||
stupid_sort_requiring_extra_pointer_dereference);
|
||||
g_array_sort (display->grab_edge_resistance_data->right_edges,
|
||||
g_array_sort (edge_data->right_edges,
|
||||
stupid_sort_requiring_extra_pointer_dereference);
|
||||
g_array_sort (display->grab_edge_resistance_data->top_edges,
|
||||
g_array_sort (edge_data->top_edges,
|
||||
stupid_sort_requiring_extra_pointer_dereference);
|
||||
g_array_sort (display->grab_edge_resistance_data->bottom_edges,
|
||||
g_array_sort (edge_data->bottom_edges,
|
||||
stupid_sort_requiring_extra_pointer_dereference);
|
||||
|
||||
return edge_data;
|
||||
}
|
||||
|
||||
static void
|
||||
initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
initialize_grab_edge_resistance_data (MetaEdgeResistanceData *edge_data)
|
||||
{
|
||||
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
|
||||
|
||||
edge_data->left_data.timeout_setup = FALSE;
|
||||
edge_data->right_data.timeout_setup = FALSE;
|
||||
edge_data->top_data.timeout_setup = FALSE;
|
||||
@ -943,8 +952,9 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
|
||||
edge_data->bottom_data.keyboard_buildup = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
static MetaEdgeResistanceData *
|
||||
compute_resistance_and_snapping_edges (MetaDisplay *display,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
GList *stacked_windows;
|
||||
GList *cur_window_iter;
|
||||
@ -956,18 +966,17 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
* in the layer that we are working on
|
||||
*/
|
||||
GSList *rem_windows, *rem_win_stacking;
|
||||
MetaEdgeResistanceData *edge_data;
|
||||
|
||||
g_assert (display->grab_window != NULL);
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Computing edges to resist-movement or snap-to for %s.\n",
|
||||
display->grab_window->desc);
|
||||
"Computing edges to resist-movement or snap-to for screen %s.\n",
|
||||
screen->screen_name);
|
||||
|
||||
/*
|
||||
* 1st: Get the list of relevant windows, from bottom to top
|
||||
*/
|
||||
stacked_windows =
|
||||
meta_stack_list_windows (display->grab_screen->stack,
|
||||
display->grab_screen->active_workspace);
|
||||
meta_stack_list_windows (screen->stack, screen->active_workspace);
|
||||
|
||||
/*
|
||||
* 2nd: we need to separate that stacked list into a list of windows that
|
||||
@ -981,7 +990,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
while (cur_window_iter != NULL)
|
||||
{
|
||||
MetaWindow *cur_window = cur_window_iter->data;
|
||||
if (WINDOW_EDGES_RELEVANT (cur_window, display))
|
||||
if (WINDOW_EDGES_RELEVANT (cur_window, display, screen))
|
||||
{
|
||||
MetaRectangle *new_rect;
|
||||
new_rect = g_new (MetaRectangle, 1);
|
||||
@ -1016,7 +1025,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
* resistance (note that dock edges are considered screen edges
|
||||
* which are handled separately
|
||||
*/
|
||||
if (WINDOW_EDGES_RELEVANT (cur_window, display) &&
|
||||
if (WINDOW_EDGES_RELEVANT (cur_window, display, screen) &&
|
||||
cur_window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
GList *new_edges;
|
||||
@ -1028,7 +1037,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
* by other windows or DOCKS, but that's handled below).
|
||||
*/
|
||||
meta_rectangle_intersect (&cur_rect,
|
||||
&display->grab_screen->rect,
|
||||
&screen->rect,
|
||||
&reduced);
|
||||
|
||||
new_edges = NULL;
|
||||
@ -1123,32 +1132,36 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
* monitor edges in an array for quick access. Free the edges since
|
||||
* they've been cached elsewhere.
|
||||
*/
|
||||
cache_edges (display,
|
||||
edges,
|
||||
display->grab_screen->active_workspace->monitor_edges,
|
||||
display->grab_screen->active_workspace->screen_edges);
|
||||
edge_data = cache_edges (display, screen,
|
||||
edges,
|
||||
screen->active_workspace->monitor_edges,
|
||||
screen->active_workspace->screen_edges);
|
||||
g_list_free (edges);
|
||||
|
||||
/*
|
||||
* 6th: Initialize the resistance timeouts and buildups
|
||||
*/
|
||||
initialize_grab_edge_resistance_data (display);
|
||||
initialize_grab_edge_resistance_data (edge_data);
|
||||
|
||||
return edge_data;
|
||||
}
|
||||
|
||||
/* Note that old_[xy] and new_[xy] are with respect to inner positions of
|
||||
* the window.
|
||||
*/
|
||||
void
|
||||
meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op)
|
||||
meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
MetaEdgeResistanceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op)
|
||||
{
|
||||
MetaRectangle old_outer, proposed_outer, new_outer;
|
||||
MetaGrabInfo *grab_info;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
@ -1158,10 +1171,14 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
proposed_outer.y += (*new_y - old_y);
|
||||
new_outer = proposed_outer;
|
||||
|
||||
window->display->grab_last_user_action_was_snap = snap;
|
||||
grab_info = meta_display_get_grab_info (window->display, device);
|
||||
g_assert (grab_info != NULL);
|
||||
|
||||
grab_info->grab_last_user_action_was_snap = snap;
|
||||
is_resize = FALSE;
|
||||
if (apply_edge_resistance_to_each_side (window->display,
|
||||
window,
|
||||
device,
|
||||
&old_outer,
|
||||
&new_outer,
|
||||
timeout_func,
|
||||
@ -1223,18 +1240,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
* sizes of the inner window.
|
||||
*/
|
||||
void
|
||||
meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op)
|
||||
meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
MetaEdgeResistanceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op)
|
||||
{
|
||||
MetaRectangle old_outer, new_outer;
|
||||
int proposed_outer_width, proposed_outer_height;
|
||||
MetaGrabInfo *grab_info;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
@ -1246,10 +1265,14 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
proposed_outer_width,
|
||||
proposed_outer_height);
|
||||
|
||||
window->display->grab_last_user_action_was_snap = snap;
|
||||
grab_info = meta_display_get_grab_info (window->display, device);
|
||||
g_assert (grab_info != NULL);
|
||||
|
||||
grab_info->grab_last_user_action_was_snap = snap;
|
||||
is_resize = TRUE;
|
||||
if (apply_edge_resistance_to_each_side (window->display,
|
||||
window,
|
||||
device,
|
||||
&old_outer,
|
||||
&new_outer,
|
||||
timeout_func,
|
||||
|
@ -26,23 +26,28 @@
|
||||
|
||||
#include "window-private.h"
|
||||
|
||||
void meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op);
|
||||
void meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
GSourceFunc timeout_func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op);
|
||||
typedef gboolean (* MetaEdgeResistanceFunc) (MetaWindow *window,
|
||||
MetaDevice *device);
|
||||
|
||||
void meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int old_x,
|
||||
int old_y,
|
||||
int *new_x,
|
||||
int *new_y,
|
||||
MetaEdgeResistanceFunc func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op);
|
||||
void meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int old_width,
|
||||
int old_height,
|
||||
int *new_width,
|
||||
int *new_height,
|
||||
int gravity,
|
||||
MetaEdgeResistanceFunc func,
|
||||
gboolean snap,
|
||||
gboolean is_keyboard_op);
|
||||
|
||||
#endif /* META_EDGE_RESISTANCE_H */
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "bell.h"
|
||||
#include <meta/errors.h>
|
||||
#include "keybindings-private.h"
|
||||
#include "device-pointer.h"
|
||||
|
||||
#include <X11/extensions/Xrender.h>
|
||||
|
||||
@ -64,7 +65,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->child_y = 0;
|
||||
frame->bottom_height = 0;
|
||||
frame->right_width = 0;
|
||||
frame->current_cursor = 0;
|
||||
frame->cursors = g_hash_table_new (NULL, NULL);
|
||||
|
||||
frame->mapped = FALSE;
|
||||
frame->need_reapply_frame_shape = TRUE;
|
||||
@ -229,9 +230,10 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
|
||||
/* Move keybindings to window instead of frame */
|
||||
meta_window_grab_keys (window);
|
||||
|
||||
|
||||
g_hash_table_destroy (frame->cursors);
|
||||
g_free (frame);
|
||||
|
||||
|
||||
/* Put our state back where it should be */
|
||||
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
@ -245,6 +247,12 @@ meta_frame_get_flags (MetaFrame *frame)
|
||||
|
||||
flags = 0;
|
||||
|
||||
/* Disallow frame operations
|
||||
* while the popup menu is open.
|
||||
*/
|
||||
if (frame->window->menu)
|
||||
return flags;
|
||||
|
||||
if (frame->window->border_only)
|
||||
{
|
||||
; /* FIXME this may disable the _function_ as well as decor
|
||||
@ -400,8 +408,7 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
/* If we're interactively resizing the frame, repaint
|
||||
* it immediately so we don't start to lag.
|
||||
*/
|
||||
if (frame->window->display->grab_window ==
|
||||
frame->window)
|
||||
if (frame->window->cur_grab != NULL)
|
||||
meta_ui_repaint_frame (frame->window->screen->ui,
|
||||
frame->xwindow);
|
||||
}
|
||||
@ -426,22 +433,22 @@ meta_frame_queue_draw (MetaFrame *frame)
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaCursor cursor)
|
||||
meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaDevice *pointer,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
if (cursor == frame->current_cursor)
|
||||
MetaCursor old_cursor;
|
||||
|
||||
old_cursor = GPOINTER_TO_UINT (g_hash_table_lookup (frame->cursors, pointer));
|
||||
|
||||
if (cursor == old_cursor)
|
||||
return;
|
||||
frame->current_cursor = cursor;
|
||||
if (cursor == META_CURSOR_DEFAULT)
|
||||
XUndefineCursor (frame->window->display->xdisplay, frame->xwindow);
|
||||
else
|
||||
{
|
||||
xcursor = meta_display_create_x_cursor (frame->window->display, cursor);
|
||||
XDefineCursor (frame->window->display->xdisplay, frame->xwindow, xcursor);
|
||||
XFlush (frame->window->display->xdisplay);
|
||||
XFreeCursor (frame->window->display->xdisplay, xcursor);
|
||||
}
|
||||
|
||||
g_hash_table_insert (frame->cursors, pointer,
|
||||
GUINT_TO_POINTER (cursor));
|
||||
meta_device_pointer_set_window_cursor (META_DEVICE_POINTER (pointer),
|
||||
frame->xwindow, cursor);
|
||||
XFlush (frame->window->display->xdisplay);
|
||||
}
|
||||
|
||||
Window
|
||||
|
@ -45,7 +45,7 @@ struct _MetaFrame
|
||||
/* reparent window */
|
||||
Window xwindow;
|
||||
|
||||
MetaCursor current_cursor;
|
||||
GHashTable *cursors;
|
||||
|
||||
/* This rect is trusted info from where we put the
|
||||
* frame, not the result of ConfigureNotify
|
||||
@ -80,7 +80,8 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
||||
|
||||
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
|
||||
|
||||
void meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
void meta_frame_set_screen_cursor (MetaFrame *frame,
|
||||
MetaDevice *pointer,
|
||||
MetaCursor cursor);
|
||||
|
||||
#endif
|
||||
|
677
src/core/input-events.c
Normal file
677
src/core/input-events.c
Normal file
@ -0,0 +1,677 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* XEvent utility methods */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "input-events.h"
|
||||
#include "devices-core.h"
|
||||
#include "device-map-private.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#endif
|
||||
|
||||
/* Quite a hack: normalizes XI2 events to their
|
||||
* core event equivalent, so most code is shared
|
||||
* for both implementations, code handling input
|
||||
* events should use the helper functions so
|
||||
* the actual event is treated correctly.
|
||||
*/
|
||||
gboolean
|
||||
meta_input_event_get_type (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *ev_type)
|
||||
{
|
||||
guint type = 0; /* Silence gcc */
|
||||
gboolean retval = TRUE;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (display->have_xinput2 &&
|
||||
ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
/* NB: GDK event filters already have generic events
|
||||
* allocated, so no need to do XGetEventData() on our own
|
||||
*/
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
type = MotionNotify;
|
||||
break;
|
||||
case XI_ButtonPress:
|
||||
type = ButtonPress;
|
||||
break;
|
||||
case XI_ButtonRelease:
|
||||
type = ButtonRelease;
|
||||
break;
|
||||
case XI_KeyPress:
|
||||
type = KeyPress;
|
||||
break;
|
||||
case XI_KeyRelease:
|
||||
type = KeyRelease;
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
type = FocusIn;
|
||||
break;
|
||||
case XI_FocusOut:
|
||||
type = FocusOut;
|
||||
break;
|
||||
case XI_Enter:
|
||||
type = EnterNotify;
|
||||
break;
|
||||
case XI_Leave:
|
||||
type = LeaveNotify;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case MotionNotify:
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
type = ev->type;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval)
|
||||
{
|
||||
if (ev_type)
|
||||
*ev_type = type;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_event_is_type (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint ev_type)
|
||||
{
|
||||
guint type;
|
||||
|
||||
if (!meta_input_event_get_type (display, ev, &type))
|
||||
return FALSE;
|
||||
|
||||
return (type == ev_type);
|
||||
}
|
||||
|
||||
Window
|
||||
meta_input_event_get_window (MetaDisplay *display,
|
||||
XEvent *ev)
|
||||
{
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
/* GDK event filters already have generic events allocated */
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
return ((XIDeviceEvent *) xev)->event;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
return ((XIEnterEvent *) xev)->event;
|
||||
default:
|
||||
return None;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
return ev->xany.window;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_input_event_get_root_window (MetaDisplay *display,
|
||||
XEvent *ev)
|
||||
{
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
return ((XIDeviceEvent *) xev)->root;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
return ((XIEnterEvent *) xev)->root;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
return ev->xkey.root;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
return ev->xbutton.root;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
return ev->xcrossing.root;
|
||||
case MotionNotify:
|
||||
return ev->xbutton.root;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
Time
|
||||
meta_input_event_get_time (MetaDisplay *display,
|
||||
XEvent *ev)
|
||||
{
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
return ((XIDeviceEvent *) xev)->time;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
return ((XIEnterEvent *) xev)->time;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
return ev->xkey.time;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
return ev->xbutton.time;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
return ev->xcrossing.time;
|
||||
case MotionNotify:
|
||||
return ev->xmotion.time;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return CurrentTime;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_event_get_coordinates (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
gdouble *x_ret,
|
||||
gdouble *y_ret,
|
||||
gdouble *x_root_ret,
|
||||
gdouble *y_root_ret)
|
||||
{
|
||||
gdouble x, y, x_root, y_root;
|
||||
gboolean retval = TRUE;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
{
|
||||
XIDeviceEvent *event = (XIDeviceEvent *) xev;
|
||||
|
||||
x = event->event_x;
|
||||
y = event->event_y;
|
||||
x_root = event->root_x;
|
||||
y_root = event->root_y;
|
||||
}
|
||||
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
{
|
||||
XIEnterEvent *event = (XIEnterEvent *) xev;
|
||||
|
||||
x = event->event_x;
|
||||
y = event->event_y;
|
||||
x_root = event->root_x;
|
||||
y_root = event->root_y;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
x = ev->xkey.x;
|
||||
y = ev->xkey.y;
|
||||
x_root = ev->xkey.x_root;
|
||||
y_root = ev->xkey.y_root;
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
x = ev->xbutton.x;
|
||||
y = ev->xbutton.y;
|
||||
x_root = ev->xbutton.x_root;
|
||||
y_root = ev->xbutton.y_root;
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
x = ev->xcrossing.x;
|
||||
y = ev->xcrossing.y;
|
||||
x_root = ev->xcrossing.x_root;
|
||||
y_root = ev->xcrossing.y_root;
|
||||
break;
|
||||
case MotionNotify:
|
||||
x = ev->xmotion.x;
|
||||
y = ev->xmotion.y;
|
||||
x_root = ev->xmotion.x_root;
|
||||
y_root = ev->xmotion.y_root;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval)
|
||||
{
|
||||
if (x_ret)
|
||||
*x_ret = x;
|
||||
|
||||
if (y_ret)
|
||||
*y_ret = y;
|
||||
|
||||
if (x_root_ret)
|
||||
*x_root_ret = x_root;
|
||||
|
||||
if (y_root_ret)
|
||||
*y_root_ret = y_root;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_event_get_state (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *state)
|
||||
{
|
||||
gboolean retval = TRUE;
|
||||
guint s;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
s = ((XIDeviceEvent *) xev)->mods.effective;
|
||||
break;
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
s = ((XIDeviceEvent *) xev)->mods.effective;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
s = ev->xkey.state;
|
||||
break;
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
s = ev->xbutton.state;
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
s = ev->xcrossing.state;
|
||||
break;
|
||||
case MotionNotify:
|
||||
s = ev->xmotion.state;
|
||||
break;
|
||||
default:
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (retval && state)
|
||||
*state = s;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_event_get_keycode (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *keycode)
|
||||
{
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype == XI_KeyPress ||
|
||||
xev->evtype == XI_KeyRelease)
|
||||
{
|
||||
if (keycode)
|
||||
{
|
||||
/* The detail field contains keycode for key events */
|
||||
*keycode = ((XIDeviceEvent *) xev)->detail;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
if (ev->type == KeyPress ||
|
||||
ev->type == KeyRelease)
|
||||
{
|
||||
if (keycode)
|
||||
*keycode = ev->xkey.keycode;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_event_get_button (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *button)
|
||||
{
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype == XI_ButtonPress ||
|
||||
xev->evtype == XI_ButtonRelease)
|
||||
{
|
||||
if (button)
|
||||
{
|
||||
/* The detail field contains
|
||||
* button number for button events
|
||||
*/
|
||||
*button = ((XIDeviceEvent *) xev)->detail;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
if (ev->type == ButtonPress ||
|
||||
ev->type == ButtonRelease)
|
||||
{
|
||||
if (button)
|
||||
*button = ev->xbutton.button;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* NB: Also works for focus in/out events */
|
||||
gboolean
|
||||
meta_input_event_get_crossing_details (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *mode_out,
|
||||
guint *detail_out)
|
||||
{
|
||||
gboolean retval = TRUE;
|
||||
guint mode, detail;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype == XI_Enter ||
|
||||
xev->evtype == XI_Leave ||
|
||||
xev->evtype == XI_FocusIn ||
|
||||
xev->evtype == XI_FocusOut)
|
||||
{
|
||||
mode = ((XIEnterEvent *) xev)->mode;
|
||||
detail = ((XIEnterEvent *) xev)->detail;
|
||||
}
|
||||
else
|
||||
retval = FALSE;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_XINPUT2 */
|
||||
{
|
||||
if (ev->type == EnterNotify ||
|
||||
ev->type == LeaveNotify)
|
||||
{
|
||||
mode = ev->xcrossing.mode;
|
||||
detail = ev->xcrossing.detail;
|
||||
}
|
||||
else if (ev->type == FocusIn ||
|
||||
ev->type == FocusOut)
|
||||
{
|
||||
mode = ev->xfocus.mode;
|
||||
detail = ev->xfocus.detail;
|
||||
}
|
||||
else
|
||||
retval = FALSE;
|
||||
}
|
||||
|
||||
if (retval)
|
||||
{
|
||||
if (mode_out)
|
||||
*mode_out = mode;
|
||||
|
||||
if (detail_out)
|
||||
*detail_out = detail;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
MetaDevice *
|
||||
meta_input_event_get_device (MetaDisplay *display,
|
||||
XEvent *ev)
|
||||
{
|
||||
guint evtype;
|
||||
|
||||
if (!meta_input_event_get_type (display, ev, &evtype))
|
||||
return NULL;
|
||||
|
||||
#ifdef HAVE_XINPUT2
|
||||
if (ev->type == GenericEvent &&
|
||||
ev->xcookie.extension == display->xinput2_opcode)
|
||||
{
|
||||
XIEvent *xev;
|
||||
|
||||
g_assert (display->have_xinput2 == TRUE);
|
||||
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
switch (evtype)
|
||||
{
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
return meta_device_map_lookup (display->device_map,
|
||||
((XIDeviceEvent *) xev)->deviceid);
|
||||
case XI_FocusIn:
|
||||
case XI_FocusOut:
|
||||
case XI_Enter:
|
||||
case XI_Leave:
|
||||
return meta_device_map_lookup (display->device_map,
|
||||
((XIEnterEvent *) xev)->deviceid);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
switch (ev->type)
|
||||
{
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
return meta_device_map_lookup (display->device_map,
|
||||
META_CORE_KEYBOARD_ID);
|
||||
default:
|
||||
/* All other events are pointers' */
|
||||
return meta_device_map_lookup (display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
78
src/core/input-events.h
Normal file
78
src/core/input-events.h
Normal file
@ -0,0 +1,78 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file event.h Utility functions for handling events
|
||||
*
|
||||
* Handling events.
|
||||
* This file contains helper methods to handle events, specially
|
||||
* input events, which can be either core or XInput2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_EVENT_H
|
||||
#define META_EVENT_H
|
||||
|
||||
#include <config.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include "display-private.h"
|
||||
#include <meta/device-map.h>
|
||||
|
||||
gboolean meta_input_event_get_type (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *ev_type);
|
||||
gboolean meta_input_event_is_type (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint ev_type);
|
||||
|
||||
Window meta_input_event_get_window (MetaDisplay *display,
|
||||
XEvent *ev);
|
||||
Window meta_input_event_get_root_window (MetaDisplay *display,
|
||||
XEvent *ev);
|
||||
|
||||
Time meta_input_event_get_time (MetaDisplay *display,
|
||||
XEvent *ev);
|
||||
|
||||
gboolean meta_input_event_get_coordinates (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
gdouble *x_ret,
|
||||
gdouble *y_ret,
|
||||
gdouble *x_root_ret,
|
||||
gdouble *y_root_ret);
|
||||
|
||||
gboolean meta_input_event_get_state (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *state);
|
||||
gboolean meta_input_event_get_keycode (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *keycode);
|
||||
gboolean meta_input_event_get_button (MetaDisplay *display,
|
||||
XEvent *event,
|
||||
guint *button);
|
||||
gboolean meta_input_event_get_crossing_details (MetaDisplay *display,
|
||||
XEvent *ev,
|
||||
guint *mode_out,
|
||||
guint *detail_out);
|
||||
|
||||
MetaDevice *meta_input_event_get_device (MetaDisplay *display,
|
||||
XEvent *ev);
|
||||
|
||||
|
||||
#endif /* META_EVENT_H */
|
@ -36,14 +36,18 @@ void meta_display_shutdown_keys (MetaDisplay *display);
|
||||
void meta_screen_grab_keys (MetaScreen *screen);
|
||||
void meta_screen_ungrab_keys (MetaScreen *screen);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen,
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
void meta_window_grab_keys (MetaWindow *window);
|
||||
void meta_window_ungrab_keys (MetaWindow *window);
|
||||
gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -311,9 +311,12 @@ static GSourceFuncs event_funcs = {
|
||||
static void
|
||||
meta_clutter_init (void)
|
||||
{
|
||||
if (!meta_get_use_core_devices ())
|
||||
clutter_x11_enable_xinput ();
|
||||
|
||||
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
|
||||
clutter_x11_disable_event_retrieval ();
|
||||
|
||||
|
||||
if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
|
||||
{
|
||||
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
|
||||
@ -424,6 +427,8 @@ meta_init (void)
|
||||
meta_set_verbose (TRUE);
|
||||
if (g_getenv ("MUTTER_DEBUG"))
|
||||
meta_set_debugging (TRUE);
|
||||
if (g_getenv ("MUTTER_USE_CORE_DEVICES"))
|
||||
meta_set_use_core_devices (TRUE);
|
||||
|
||||
if (g_get_home_dir ())
|
||||
if (chdir (g_get_home_dir ()) < 0)
|
||||
|
@ -90,6 +90,7 @@ northwestcmp (gconstpointer a, gconstpointer b)
|
||||
|
||||
static void
|
||||
find_next_cascade (MetaWindow *window,
|
||||
MetaDevice *pointer,
|
||||
MetaFrameGeometry *fgeom,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
@ -136,7 +137,7 @@ find_next_cascade (MetaWindow *window,
|
||||
* of NW corner of window frame.
|
||||
*/
|
||||
|
||||
current = meta_screen_get_current_monitor (window->screen);
|
||||
current = meta_screen_get_current_monitor (window->screen, pointer);
|
||||
meta_window_get_work_area_for_monitor (window, current->number, &work_area);
|
||||
|
||||
cascade_x = MAX (0, work_area.x);
|
||||
@ -354,10 +355,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
* know about the modal-to-the-main-window part.
|
||||
*/
|
||||
|
||||
MetaWindow *focus_window;
|
||||
MetaWindow *focus_window = NULL;
|
||||
MetaFocusInfo *focus_info;
|
||||
MetaRectangle overlap;
|
||||
MetaDevice *pointer, *keyboard;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
pointer = meta_window_guess_grab_pointer (window);
|
||||
keyboard = meta_device_get_paired_device (pointer);
|
||||
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||
|
||||
if (focus_window)
|
||||
focus_window = focus_info->focus_window;
|
||||
|
||||
if (window->denied_focus_and_not_transient &&
|
||||
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||
@ -660,6 +668,7 @@ meta_window_place (MetaWindow *window,
|
||||
{
|
||||
GList *windows;
|
||||
const MetaMonitorInfo *xi;
|
||||
MetaDevice *pointer, *keyboard;
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameGeometry. But remember fgeom == NULL
|
||||
@ -671,7 +680,9 @@ meta_window_place (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||
|
||||
windows = NULL;
|
||||
|
||||
pointer = meta_window_guess_grab_pointer (window);
|
||||
keyboard = meta_device_get_paired_device (pointer);
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
/* Run placement algorithm on these. */
|
||||
@ -815,7 +826,7 @@ meta_window_place (MetaWindow *window,
|
||||
int w, h;
|
||||
|
||||
/* Warning, this function is a round trip! */
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
xi = meta_screen_get_current_monitor (window->screen, pointer);
|
||||
|
||||
w = xi->rect.width;
|
||||
h = xi->rect.height;
|
||||
@ -860,8 +871,8 @@ meta_window_place (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Warning, this is a round trip! */
|
||||
xi = meta_screen_get_current_monitor (window->screen);
|
||||
|
||||
xi = meta_screen_get_current_monitor (window->screen, pointer);
|
||||
|
||||
/* "Origin" placement algorithm */
|
||||
x = xi->rect.x;
|
||||
y = xi->rect.y;
|
||||
@ -899,8 +910,8 @@ meta_window_place (MetaWindow *window,
|
||||
/* If no placement has been done, revert to cascade to avoid
|
||||
* fully overlapping window (e.g. starting multiple terminals)
|
||||
* */
|
||||
if (x == xi->rect.x && y == xi->rect.y)
|
||||
find_next_cascade (window, fgeom, windows, x, y, &x, &y);
|
||||
if (x == xi->rect.x && y == xi->rect.y)
|
||||
find_next_cascade (window, pointer, fgeom, windows, x, y, &x, &y);
|
||||
|
||||
done_check_denied_focus:
|
||||
/* If the window is being denied focus and isn't a transient of the
|
||||
@ -913,8 +924,12 @@ meta_window_place (MetaWindow *window,
|
||||
gboolean found_fit;
|
||||
MetaWindow *focus_window;
|
||||
MetaRectangle overlap;
|
||||
MetaFocusInfo *focus_info;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||
g_assert (focus_info != NULL);
|
||||
|
||||
focus_window = focus_info->focus_window;
|
||||
g_assert (focus_window != NULL);
|
||||
|
||||
/* No need to do anything if the window doesn't overlap at all */
|
||||
|
@ -90,7 +90,8 @@ struct _MetaScreen
|
||||
MetaStack *stack;
|
||||
MetaStackTracker *stack_tracker;
|
||||
|
||||
MetaCursor current_cursor;
|
||||
/* per-pointer cursors */
|
||||
GHashTable *cursors;
|
||||
|
||||
Window flash_window;
|
||||
|
||||
@ -158,8 +159,10 @@ void meta_screen_queue_frame_redraws (MetaScreen *scree
|
||||
void meta_screen_queue_window_resizes (MetaScreen *screen);
|
||||
|
||||
void meta_screen_set_cursor (MetaScreen *screen,
|
||||
MetaDevice *pointer,
|
||||
MetaCursor cursor);
|
||||
void meta_screen_update_cursor (MetaScreen *screen);
|
||||
void meta_screen_update_cursor (MetaScreen *screen,
|
||||
MetaDevice *pointer);
|
||||
|
||||
void meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
MetaTabList list_type,
|
||||
@ -182,9 +185,11 @@ void meta_screen_tile_preview_update (MetaScreen *screen,
|
||||
void meta_screen_tile_preview_hide (MetaScreen *screen);
|
||||
|
||||
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaDevice *pointer,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor (MetaScreen *screen);
|
||||
const MetaMonitorInfo* meta_screen_get_current_monitor (MetaScreen *screen,
|
||||
MetaDevice *pointer);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
|
||||
MetaRectangle *rect);
|
||||
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
|
@ -37,10 +37,12 @@
|
||||
#include "workspace-private.h"
|
||||
#include "keybindings-private.h"
|
||||
#include "stack.h"
|
||||
#include "core.h"
|
||||
#include "xprops.h"
|
||||
#include <meta/compositor.h>
|
||||
#include "mutter-marshal.h"
|
||||
#include "mutter-enum-types.h"
|
||||
#include "device-pointer.h"
|
||||
|
||||
#ifdef HAVE_SOLARIS_XINERAMA
|
||||
#include <X11/extensions/xinerama.h>
|
||||
@ -632,7 +634,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
MetaScreen *screen;
|
||||
Window xroot;
|
||||
Display *xdisplay;
|
||||
XWindowAttributes attr;
|
||||
Window new_wm_sn_owner;
|
||||
Window current_wm_sn_owner;
|
||||
gboolean replace_current_wm;
|
||||
@ -747,15 +748,15 @@ meta_screen_new (MetaDisplay *display,
|
||||
/* We need to or with the existing event mask since
|
||||
* gtk+ may be interested in other events.
|
||||
*/
|
||||
XGetWindowAttributes (xdisplay, xroot, &attr);
|
||||
XSelectInput (xdisplay,
|
||||
xroot,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
ColormapChangeMask | PropertyChangeMask |
|
||||
LeaveWindowMask | EnterWindowMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
FocusChangeMask | StructureNotifyMask |
|
||||
ExposureMask | attr.your_event_mask);
|
||||
meta_core_select_events (xdisplay, xroot,
|
||||
(SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
ColormapChangeMask | PropertyChangeMask |
|
||||
LeaveWindowMask | EnterWindowMask |
|
||||
KeyPressMask | KeyReleaseMask |
|
||||
FocusChangeMask | StructureNotifyMask |
|
||||
ExposureMask),
|
||||
TRUE);
|
||||
|
||||
if (meta_error_trap_pop_with_return (display) != Success)
|
||||
{
|
||||
meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"),
|
||||
@ -777,10 +778,10 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
screen->rect.width = WidthOfScreen (screen->xscreen);
|
||||
screen->rect.height = HeightOfScreen (screen->xscreen);
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
screen->flash_window = None;
|
||||
screen->cursors = g_hash_table_new (NULL, NULL);
|
||||
|
||||
screen->wm_sn_selection_window = new_wm_sn_owner;
|
||||
screen->wm_sn_atom = wm_sn_atom;
|
||||
@ -805,8 +806,6 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->last_monitor_index = 0;
|
||||
|
||||
reload_monitor_infos (screen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
|
||||
/* Handle creating a no_focus_window for this screen */
|
||||
screen->no_focus_window =
|
||||
@ -941,7 +940,10 @@ meta_screen_free (MetaScreen *screen,
|
||||
meta_stack_tracker_free (screen->stack_tracker);
|
||||
|
||||
meta_error_trap_push_with_return (screen->display);
|
||||
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
|
||||
meta_core_select_events (screen->display->xdisplay,
|
||||
screen->xroot, NoEventMask,
|
||||
FALSE);
|
||||
|
||||
if (meta_error_trap_pop_with_return (screen->display) != Success)
|
||||
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
|
||||
screen->number, screen->display->name);
|
||||
@ -965,6 +967,8 @@ meta_screen_free (MetaScreen *screen,
|
||||
|
||||
g_free (screen->screen_name);
|
||||
|
||||
g_hash_table_destroy (screen->cursors);
|
||||
|
||||
g_object_unref (screen);
|
||||
|
||||
XFlush (display->xdisplay);
|
||||
@ -1578,31 +1582,33 @@ update_focus_mode (MetaScreen *screen)
|
||||
|
||||
void
|
||||
meta_screen_set_cursor (MetaScreen *screen,
|
||||
MetaDevice *pointer,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
MetaCursor old_cursor;
|
||||
|
||||
if (cursor == screen->current_cursor)
|
||||
old_cursor = GPOINTER_TO_UINT (g_hash_table_lookup (screen->cursors, pointer));
|
||||
|
||||
if (cursor == old_cursor)
|
||||
return;
|
||||
|
||||
screen->current_cursor = cursor;
|
||||
|
||||
xcursor = meta_display_create_x_cursor (screen->display, cursor);
|
||||
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
|
||||
XFlush (screen->display->xdisplay);
|
||||
XFreeCursor (screen->display->xdisplay, xcursor);
|
||||
g_hash_table_insert (screen->cursors, pointer,
|
||||
GUINT_TO_POINTER (cursor));
|
||||
|
||||
meta_screen_update_cursor (screen, pointer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_update_cursor (MetaScreen *screen)
|
||||
meta_screen_update_cursor (MetaScreen *screen,
|
||||
MetaDevice *pointer)
|
||||
{
|
||||
Cursor xcursor;
|
||||
MetaCursor cursor;
|
||||
|
||||
xcursor = meta_display_create_x_cursor (screen->display,
|
||||
screen->current_cursor);
|
||||
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
|
||||
cursor = GPOINTER_TO_UINT (g_hash_table_lookup (screen->cursors, pointer));
|
||||
meta_device_pointer_set_window_cursor (META_DEVICE_POINTER (pointer),
|
||||
screen->xroot,
|
||||
cursor);
|
||||
XFlush (screen->display->xdisplay);
|
||||
XFreeCursor (screen->display->xdisplay, xcursor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1856,9 +1862,21 @@ static gboolean
|
||||
meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
{
|
||||
MetaScreen *screen = data;
|
||||
MetaWindow *window = screen->display->grab_window;
|
||||
MetaWindow *window = NULL;
|
||||
gboolean composited = screen->display->compositor != NULL;
|
||||
gboolean needs_preview = FALSE;
|
||||
MetaGrabInfo *grab_info;
|
||||
MetaDevice *pointer = NULL;
|
||||
GHashTableIter iter;
|
||||
|
||||
/* FIXME: we're just handling the first grab we find */
|
||||
g_hash_table_iter_init (&iter, screen->display->current_grabs);
|
||||
|
||||
if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info))
|
||||
{
|
||||
window = grab_info->grab_window;
|
||||
pointer = grab_info->grab_pointer;
|
||||
}
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
@ -1901,8 +1919,8 @@ meta_screen_tile_preview_update_timeout (gpointer data)
|
||||
{
|
||||
MetaRectangle tile_rect;
|
||||
|
||||
meta_window_get_current_tile_area (window, &tile_rect);
|
||||
meta_tile_preview_show (screen->tile_preview, &tile_rect);
|
||||
meta_window_get_current_tile_area (window, pointer, &tile_rect);
|
||||
meta_tile_preview_show (screen->tile_preview, pointer, &tile_rect);
|
||||
}
|
||||
else
|
||||
meta_tile_preview_hide (screen->tile_preview);
|
||||
@ -1947,28 +1965,23 @@ meta_screen_tile_preview_hide (MetaScreen *screen)
|
||||
|
||||
MetaWindow*
|
||||
meta_screen_get_mouse_window (MetaScreen *screen,
|
||||
MetaDevice *pointer,
|
||||
MetaWindow *not_this_one)
|
||||
{
|
||||
MetaWindow *window;
|
||||
Window root_return, child_return;
|
||||
int root_x_return, root_y_return;
|
||||
int win_x_return, win_y_return;
|
||||
unsigned int mask_return;
|
||||
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_error_trap_push (screen->display);
|
||||
XQueryPointer (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&mask_return);
|
||||
meta_device_pointer_query_position (META_DEVICE_POINTER (pointer),
|
||||
screen->xroot,
|
||||
NULL, NULL,
|
||||
&root_x_return,
|
||||
&root_y_return,
|
||||
NULL, NULL, NULL);
|
||||
meta_error_trap_pop (screen->display);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
@ -2064,6 +2077,7 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
const MetaMonitorInfo* current;
|
||||
const MetaMonitorInfo* tmp;
|
||||
GQueue* monitor_queue;
|
||||
MetaDevice *pointer;
|
||||
int* visited;
|
||||
int cur = 0;
|
||||
int i;
|
||||
@ -2071,6 +2085,9 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
*n_monitors = screen->n_monitor_infos;
|
||||
*monitors_list = g_new (int, screen->n_monitor_infos);
|
||||
|
||||
pointer = meta_device_map_lookup (screen->display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
|
||||
/* we calculate a natural ordering by which to choose monitors for
|
||||
* window placement. We start at the current monitor, and perform
|
||||
* a breadth-first search of the monitors starting from that
|
||||
@ -2085,7 +2102,7 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
visited[i] = FALSE;
|
||||
}
|
||||
|
||||
current = meta_screen_get_current_monitor (screen);
|
||||
current = meta_screen_get_current_monitor (screen, pointer);
|
||||
monitor_queue = g_queue_new ();
|
||||
g_queue_push_tail (monitor_queue, (gpointer) current);
|
||||
visited[current->number] = TRUE;
|
||||
@ -2152,7 +2169,8 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
|
||||
}
|
||||
|
||||
const MetaMonitorInfo*
|
||||
meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
meta_screen_get_current_monitor (MetaScreen *screen,
|
||||
MetaDevice *pointer)
|
||||
{
|
||||
if (screen->n_monitor_infos == 1)
|
||||
return &screen->monitor_infos[0];
|
||||
@ -2162,24 +2180,18 @@ meta_screen_get_current_monitor (MetaScreen *screen)
|
||||
|
||||
if (screen->display->monitor_cache_invalidated)
|
||||
{
|
||||
Window root_return, child_return;
|
||||
int win_x_return, win_y_return;
|
||||
unsigned int mask_return;
|
||||
int i;
|
||||
MetaRectangle pointer_position;
|
||||
|
||||
screen->display->monitor_cache_invalidated = FALSE;
|
||||
|
||||
pointer_position.width = pointer_position.height = 1;
|
||||
XQueryPointer (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
&root_return,
|
||||
&child_return,
|
||||
&pointer_position.x,
|
||||
&pointer_position.y,
|
||||
&win_x_return,
|
||||
&win_y_return,
|
||||
&mask_return);
|
||||
meta_device_pointer_query_position (META_DEVICE_POINTER (pointer),
|
||||
screen->xroot,
|
||||
NULL, NULL,
|
||||
&pointer_position.x,
|
||||
&pointer_position.y,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
screen->last_monitor_index = 0;
|
||||
for (i = 0; i < screen->n_monitor_infos; i++)
|
||||
@ -3046,17 +3058,22 @@ static gboolean startup_sequence_timeout (void *data);
|
||||
static void
|
||||
update_startup_feedback (MetaScreen *screen)
|
||||
{
|
||||
MetaDevice *pointer;
|
||||
|
||||
pointer = meta_device_map_lookup (screen->display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
|
||||
if (screen->startup_sequences != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_STARTUP,
|
||||
"Setting busy cursor\n");
|
||||
meta_screen_set_cursor (screen, META_CURSOR_BUSY);
|
||||
meta_screen_set_cursor (screen, pointer, META_CURSOR_BUSY);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_STARTUP,
|
||||
"Setting default cursor\n");
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
meta_screen_set_cursor (screen, pointer, META_CURSOR_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -211,13 +211,23 @@ meta_stack_thaw (MetaStack *stack)
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
typedef struct _FocusedForeachData FocusedForeachData;
|
||||
|
||||
struct _FocusedForeachData
|
||||
{
|
||||
MetaWindow *window;
|
||||
gboolean focused_transient;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
is_focused_foreach (MetaWindow *window,
|
||||
void *data)
|
||||
{
|
||||
if (window == window->display->expected_focus_window)
|
||||
FocusedForeachData *focused_data = data;
|
||||
|
||||
if (window == focused_data->window)
|
||||
{
|
||||
*((gboolean*) data) = TRUE;
|
||||
focused_data->focused_transient = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
@ -240,6 +250,9 @@ get_standalone_layer (MetaWindow *window)
|
||||
{
|
||||
MetaStackLayer layer;
|
||||
gboolean focused_transient = FALSE;
|
||||
MetaFocusInfo *focus_info;
|
||||
MetaDevice *keyboard;
|
||||
FocusedForeachData focused_data = { 0 };
|
||||
|
||||
switch (window->type)
|
||||
{
|
||||
@ -263,20 +276,30 @@ get_standalone_layer (MetaWindow *window)
|
||||
case META_WINDOW_OVERRIDE_OTHER:
|
||||
layer = META_LAYER_OVERRIDE_REDIRECT;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
/* FIXME: How about other keyboards? should
|
||||
* we allow fullscreen for non-VCP/K anyway?
|
||||
*/
|
||||
keyboard = meta_device_map_lookup (window->display->device_map,
|
||||
META_CORE_KEYBOARD_ID);
|
||||
|
||||
focus_info = meta_display_get_focus_info (window->display, keyboard);
|
||||
focused_data.window = focus_info->expected_focus_window;
|
||||
|
||||
meta_window_foreach_transient (window,
|
||||
is_focused_foreach,
|
||||
&focused_transient);
|
||||
&focused_data);
|
||||
|
||||
if (window->wm_state_below)
|
||||
layer = META_LAYER_BOTTOM;
|
||||
else if (window->fullscreen &&
|
||||
(focused_transient ||
|
||||
window == window->display->expected_focus_window ||
|
||||
window->display->expected_focus_window == NULL ||
|
||||
(window->display->expected_focus_window != NULL &&
|
||||
!focus_info ||
|
||||
window == focus_info->expected_focus_window ||
|
||||
focus_info->expected_focus_window == NULL ||
|
||||
(focus_info->expected_focus_window != NULL &&
|
||||
windows_on_different_monitor (window,
|
||||
window->display->expected_focus_window))))
|
||||
focus_info->expected_focus_window))))
|
||||
layer = META_LAYER_FULLSCREEN;
|
||||
else if (window->wm_state_above)
|
||||
layer = META_LAYER_TOP;
|
||||
|
@ -81,6 +81,7 @@ meta_print_backtrace (void)
|
||||
static gint verbose_topics = 0;
|
||||
static gboolean is_debugging = FALSE;
|
||||
static gboolean replace_current = FALSE;
|
||||
static gboolean use_core_devices = FALSE;
|
||||
static int no_prefix = 0;
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
@ -209,6 +210,18 @@ meta_set_debugging (gboolean setting)
|
||||
is_debugging = setting;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_get_use_core_devices (void)
|
||||
{
|
||||
return use_core_devices;
|
||||
}
|
||||
|
||||
void
|
||||
meta_set_use_core_devices (gboolean setting)
|
||||
{
|
||||
use_core_devices = setting;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_get_replace_current_wm (void)
|
||||
{
|
||||
|
@ -107,6 +107,10 @@ struct _MetaWindow
|
||||
Window xgroup_leader;
|
||||
Window xclient_leader;
|
||||
|
||||
/* window menu if any, and the pointer that popped it up */
|
||||
MetaWindowMenu *menu;
|
||||
MetaDevice *menu_device;
|
||||
|
||||
/* Initial workspace property */
|
||||
int initial_workspace;
|
||||
|
||||
@ -318,6 +322,12 @@ struct _MetaWindow
|
||||
/* if TRUE, application is buggy and SYNC resizing is turned off */
|
||||
guint disable_sync : 1;
|
||||
|
||||
/* if TRUE, window didn't yet get the FocusIn for window->focus_keyboard */
|
||||
guint expecting_focus_in : 1;
|
||||
|
||||
/* Keyboard currently owning the window focus, or NULL */
|
||||
MetaDevice *focus_keyboard;
|
||||
|
||||
/* if non-NULL, the bounds of the window frame */
|
||||
cairo_region_t *frame_bounds;
|
||||
|
||||
@ -395,6 +405,12 @@ struct _MetaWindow
|
||||
|
||||
/* Focused window that is (directly or indirectly) attached to this one */
|
||||
MetaWindow *attached_focus_window;
|
||||
|
||||
/* Current grab op for this window, or NULL */
|
||||
MetaGrabInfo *cur_grab;
|
||||
|
||||
/* Focus info if the window is focused, or NULL */
|
||||
MetaFocusInfo *cur_focus;
|
||||
};
|
||||
|
||||
struct _MetaWindowClass
|
||||
@ -564,6 +580,7 @@ void meta_window_set_current_workspace_hint (MetaWindow *window);
|
||||
unsigned long meta_window_get_net_wm_desktop (MetaWindow *window);
|
||||
|
||||
void meta_window_show_menu (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
@ -592,6 +609,7 @@ void meta_window_get_work_area_all_monitors (MetaWindow *window,
|
||||
MetaRectangle *area);
|
||||
|
||||
void meta_window_get_current_tile_area (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
MetaRectangle *tile_area);
|
||||
|
||||
|
||||
@ -613,13 +631,16 @@ void meta_window_free_delete_dialog (MetaWindow *window);
|
||||
|
||||
|
||||
void meta_window_begin_grab_op (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
MetaGrabOp op,
|
||||
gboolean frame_action,
|
||||
guint32 timestamp);
|
||||
|
||||
void meta_window_update_keyboard_resize (MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
gboolean update_cursor);
|
||||
void meta_window_update_keyboard_move (MetaWindow *window);
|
||||
void meta_window_update_keyboard_move (MetaWindow *window,
|
||||
MetaDevice *device);
|
||||
|
||||
void meta_window_update_layer (MetaWindow *window);
|
||||
|
||||
@ -641,6 +662,13 @@ void meta_window_update_monitor (MetaWindow *window);
|
||||
void meta_window_update_on_all_workspaces (MetaWindow *window);
|
||||
|
||||
void meta_window_propagate_focus_appearance (MetaWindow *window,
|
||||
MetaDevice *keyboard,
|
||||
gboolean focused);
|
||||
|
||||
void meta_window_set_client_pointer (MetaWindow *window,
|
||||
MetaDevice *pointer);
|
||||
MetaDevice * meta_window_get_client_pointer (MetaWindow *window);
|
||||
|
||||
MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
@ -1471,7 +1471,9 @@ reload_transient_for (MetaWindow *window,
|
||||
MetaWindow *parent = NULL;
|
||||
|
||||
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
||||
meta_window_propagate_focus_appearance (window, FALSE);
|
||||
meta_window_propagate_focus_appearance (window,
|
||||
window->focus_keyboard,
|
||||
FALSE);
|
||||
|
||||
window->xtransient_for = None;
|
||||
|
||||
@ -1537,7 +1539,9 @@ reload_transient_for (MetaWindow *window,
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
|
||||
if (meta_window_appears_focused (window) && window->xtransient_for != None)
|
||||
meta_window_propagate_focus_appearance (window, TRUE);
|
||||
meta_window_propagate_focus_appearance (window,
|
||||
window->focus_keyboard,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -85,6 +85,7 @@ GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
|
||||
int which_monitor);
|
||||
|
||||
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
MetaDevice *pointer,
|
||||
MetaWindow *not_this_one,
|
||||
guint32 timestamp);
|
||||
|
||||
|
@ -538,7 +538,9 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
MetaWorkspaceLayout layout1, layout2;
|
||||
gint num_workspaces, current_space, new_space;
|
||||
MetaMotionDirection direction;
|
||||
|
||||
MetaGrabInfo *grab_info;
|
||||
GHashTableIter iter;
|
||||
|
||||
meta_verbose ("Activating workspace %d\n",
|
||||
meta_workspace_index (workspace));
|
||||
|
||||
@ -547,7 +549,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
|
||||
/* Free any cached pointers to the workspaces's edges from
|
||||
* a current resize or move operation */
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
meta_display_cleanup_edges (workspace->screen->display, workspace->screen);
|
||||
|
||||
if (workspace->screen->active_workspace)
|
||||
workspace_switch_sound (workspace->screen->active_workspace, workspace);
|
||||
@ -570,10 +572,22 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
return;
|
||||
|
||||
move_window = NULL;
|
||||
if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
|
||||
workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
|
||||
move_window = workspace->screen->display->grab_window;
|
||||
|
||||
|
||||
/* FIXME: not quite multidevice friendly, but the whole
|
||||
* "move window to another workspace" isn't.
|
||||
*/
|
||||
g_hash_table_iter_init (&iter, workspace->screen->display->current_grabs);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info))
|
||||
{
|
||||
if (grab_info->grab_op == META_GRAB_OP_MOVING ||
|
||||
grab_info->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
|
||||
{
|
||||
move_window = grab_info->grab_window;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (move_window != NULL)
|
||||
{
|
||||
if (move_window->on_all_workspaces)
|
||||
@ -673,8 +687,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaDevice *pointer;
|
||||
|
||||
pointer = meta_device_map_lookup (screen->display->device_map,
|
||||
META_CORE_POINTER_ID);
|
||||
meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
|
||||
meta_workspace_focus_default_window (workspace, NULL, timestamp);
|
||||
meta_workspace_focus_default_window (workspace, pointer,
|
||||
NULL, timestamp);
|
||||
}
|
||||
|
||||
/* Emit switched signal from screen.c */
|
||||
@ -774,7 +793,7 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
|
||||
/* If we are in the middle of a resize or move operation, we
|
||||
* might have cached pointers to the workspace's edges */
|
||||
if (workspace == workspace->screen->active_workspace)
|
||||
meta_display_cleanup_edges (workspace->screen->display);
|
||||
meta_display_cleanup_edges (workspace->screen->display, workspace->screen);
|
||||
|
||||
g_free (workspace->work_area_monitor);
|
||||
workspace->work_area_monitor = NULL;
|
||||
@ -1191,6 +1210,7 @@ meta_workspace_get_name (MetaWorkspace *workspace)
|
||||
|
||||
void
|
||||
meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
MetaDevice *pointer,
|
||||
MetaWindow *not_this_one,
|
||||
guint32 timestamp)
|
||||
{
|
||||
@ -1207,7 +1227,8 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
|
||||
else
|
||||
{
|
||||
MetaWindow * window;
|
||||
window = meta_screen_get_mouse_window (workspace->screen, not_this_one);
|
||||
window = meta_screen_get_mouse_window (workspace->screen,
|
||||
pointer, not_this_one);
|
||||
if (window &&
|
||||
window->type != META_WINDOW_DOCK &&
|
||||
window->type != META_WINDOW_DESKTOP)
|
||||
|
46
src/meta/device-map.h
Normal file
46
src/meta/device-map.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_MAP_H
|
||||
#define META_DEVICE_MAP_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <meta/types.h>
|
||||
#include <meta/device.h>
|
||||
|
||||
#define META_TYPE_DEVICE_MAP (meta_device_map_get_type ())
|
||||
#define META_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMap))
|
||||
#define META_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP, MetaDeviceMapClass))
|
||||
#define META_IS_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP))
|
||||
#define META_IS_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP))
|
||||
#define META_DEVICE_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMapClass))
|
||||
|
||||
typedef struct _MetaDeviceMapClass MetaDeviceMapClass;
|
||||
|
||||
GType meta_device_map_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaDevice * meta_device_map_lookup (MetaDeviceMap *device_map,
|
||||
gint device_id);
|
||||
|
||||
MetaDisplay * meta_device_map_get_display (MetaDeviceMap *device_map);
|
||||
GList * meta_device_map_list_devices (MetaDeviceMap *device_map);
|
||||
|
||||
#endif
|
44
src/meta/device.h
Normal file
44
src/meta/device.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2011 Carlos Garnacho
|
||||
*
|
||||
* 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 of the
|
||||
* License, 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., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef META_DEVICE_H
|
||||
#define META_DEVICE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <meta/types.h>
|
||||
|
||||
#define META_TYPE_DEVICE (meta_device_get_type ())
|
||||
#define META_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE, MetaDevice))
|
||||
#define META_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE, MetaDeviceClass))
|
||||
#define META_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE))
|
||||
#define META_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE))
|
||||
#define META_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE, MetaDeviceClass))
|
||||
|
||||
typedef struct _MetaDeviceClass MetaDeviceClass;
|
||||
|
||||
GType meta_device_get_type (void) G_GNUC_CONST;
|
||||
|
||||
int meta_device_get_id (MetaDevice *device);
|
||||
MetaDisplay *meta_device_get_display (MetaDevice *device);
|
||||
|
||||
MetaDevice * meta_device_get_paired_device (MetaDevice *device);
|
||||
|
||||
#endif
|
@ -28,6 +28,7 @@
|
||||
#include <meta/types.h>
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/common.h>
|
||||
#include <meta/device-map.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@ -74,6 +75,9 @@ gboolean meta_display_has_shape (MetaDisplay *display);
|
||||
|
||||
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
|
||||
Window xroot);
|
||||
|
||||
MetaWindow *meta_display_get_keyboard_focus_window (MetaDisplay *display,
|
||||
MetaDevice *keyboard);
|
||||
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
||||
@ -108,9 +112,30 @@ MetaWindow* meta_display_get_tab_current (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
GList* meta_display_get_device_tab_list (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace,
|
||||
MetaDevice *device);
|
||||
|
||||
MetaWindow* meta_display_get_device_tab_next (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
gboolean backward);
|
||||
|
||||
MetaWindow* meta_display_get_device_tab_current (MetaDisplay *display,
|
||||
MetaTabList type,
|
||||
MetaScreen *screen,
|
||||
MetaWorkspace *workspace,
|
||||
MetaDevice *device);
|
||||
|
||||
gboolean meta_display_begin_grab_op (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
MetaDevice *device,
|
||||
MetaGrabOp op,
|
||||
gboolean pointer_already_grabbed,
|
||||
gboolean frame_action,
|
||||
@ -120,14 +145,28 @@ gboolean meta_display_begin_grab_op (MetaDisplay *display,
|
||||
int root_x,
|
||||
int root_y);
|
||||
void meta_display_end_grab_op (MetaDisplay *display,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
|
||||
MetaGrabOp meta_display_get_grab_op (MetaDisplay *display);
|
||||
|
||||
MetaGrabOp meta_display_get_device_grab_op (MetaDisplay *display,
|
||||
MetaDevice *device);
|
||||
|
||||
MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display,
|
||||
unsigned int keycode,
|
||||
unsigned long mask);
|
||||
|
||||
void meta_display_set_keyboard_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
MetaDevice *keyboard,
|
||||
gboolean focus_frame,
|
||||
guint32 timestamp);
|
||||
void meta_display_unset_keyboard_focus (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaDevice *keyboard,
|
||||
guint32 timestamp);
|
||||
|
||||
/* meta_display_set_input_focus_window is like XSetInputFocus, except
|
||||
* that (a) it can't detect timestamps later than the current time,
|
||||
* since Mutter isn't part of the XServer, and thus gives erroneous
|
||||
@ -155,4 +194,6 @@ GSList *meta_display_sort_windows_by_stacking (MetaDisplay *display,
|
||||
|
||||
Window meta_display_get_leader_window (MetaDisplay *display);
|
||||
|
||||
MetaDeviceMap * meta_display_get_device_map (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
@ -67,6 +67,10 @@ void meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen,
|
||||
MetaDevice *device,
|
||||
guint32 timestamp);
|
||||
#endif
|
||||
|
@ -32,6 +32,8 @@ typedef struct _MetaFrame MetaFrame;
|
||||
typedef struct _MetaScreen MetaScreen;
|
||||
typedef struct _MetaWindow MetaWindow;
|
||||
typedef struct _MetaWorkspace MetaWorkspace;
|
||||
typedef struct _MetaDevice MetaDevice;
|
||||
typedef struct _MetaDeviceMap MetaDeviceMap;
|
||||
/**
|
||||
* MetaGroup: (skip)
|
||||
*
|
||||
|
@ -38,6 +38,9 @@ gboolean meta_is_syncing (void);
|
||||
void meta_set_syncing (gboolean setting);
|
||||
void meta_set_replace_current_wm (gboolean setting);
|
||||
|
||||
gboolean meta_get_use_core_devices (void);
|
||||
void meta_set_use_core_devices (gboolean setting);
|
||||
|
||||
void meta_debug_spew_real (const char *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
void meta_verbose_real (const char *format,
|
||||
|
159
src/ui/frames.c
159
src/ui/frames.c
@ -52,6 +52,7 @@ static void meta_frames_unmap (GtkWidget *widget);
|
||||
|
||||
static void meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
GdkDevice *device,
|
||||
MetaFrameControl control);
|
||||
static gboolean meta_frames_button_press_event (GtkWidget *widget,
|
||||
GdkEventButton *event);
|
||||
@ -725,10 +726,18 @@ meta_frames_unmanage_window (MetaFrames *frames,
|
||||
*/
|
||||
invalidate_all_caches (frames);
|
||||
|
||||
#if 0
|
||||
/* This function is only called when destroying the frame
|
||||
* in core/frame.c, ideally this should be done for every
|
||||
* device with a cursor on the frame, but in practical
|
||||
* effects it doesn't matter.
|
||||
*/
|
||||
|
||||
/* restore the cursor */
|
||||
meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow,
|
||||
META_CURSOR_DEFAULT);
|
||||
#endif
|
||||
|
||||
gdk_window_set_user_data (frame->window, NULL);
|
||||
|
||||
@ -1416,10 +1425,12 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
|
||||
int action)
|
||||
{
|
||||
MetaFrameFlags flags;
|
||||
GdkDevice *pointer;
|
||||
Display *display;
|
||||
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
pointer = gdk_event_get_device ((GdkEvent *) event);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case META_ACTION_TITLEBAR_TOGGLE_SHADE:
|
||||
@ -1501,12 +1512,14 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
|
||||
case META_ACTION_TITLEBAR_LOWER:
|
||||
meta_core_user_lower_and_unfocus (display,
|
||||
frame->xwindow,
|
||||
gdk_x11_device_get_id (pointer),
|
||||
event->time);
|
||||
break;
|
||||
|
||||
case META_ACTION_TITLEBAR_MENU:
|
||||
meta_core_show_window_menu (display,
|
||||
frame->xwindow,
|
||||
gdk_x11_device_get_id (pointer),
|
||||
event->x_root,
|
||||
event->y_root,
|
||||
event->button,
|
||||
@ -1555,7 +1568,9 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
MetaFrames *frames;
|
||||
MetaFrameControl control;
|
||||
Display *display;
|
||||
|
||||
GdkDevice *device;
|
||||
int device_id;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
@ -1588,7 +1603,10 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
/* don't do the rest of this if on client area */
|
||||
if (control == META_FRAME_CONTROL_CLIENT_AREA)
|
||||
return FALSE; /* not on the frame, just passed through from client */
|
||||
|
||||
|
||||
device = gdk_event_get_device ((GdkEvent *) event);
|
||||
device_id = gdk_x11_device_get_id (device);
|
||||
|
||||
/* We want to shade even if we have a GrabOp, since we'll have a move grab
|
||||
* if we double click the titlebar.
|
||||
*/
|
||||
@ -1596,13 +1614,13 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
event->button == 1 &&
|
||||
event->type == GDK_2BUTTON_PRESS)
|
||||
{
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
return meta_frame_double_click_event (frame, event);
|
||||
}
|
||||
|
||||
if (meta_core_get_grab_op (display) !=
|
||||
if (meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL) !=
|
||||
META_GRAB_OP_NONE)
|
||||
return FALSE; /* already up to something */
|
||||
return FALSE; /* already up to something */
|
||||
|
||||
if (event->button == 1 &&
|
||||
(control == META_FRAME_CONTROL_MAXIMIZE ||
|
||||
@ -1661,6 +1679,7 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
|
||||
meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
device_id,
|
||||
op,
|
||||
TRUE,
|
||||
TRUE,
|
||||
@ -1693,6 +1712,7 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
|
||||
meta_core_show_window_menu (display,
|
||||
frame->xwindow,
|
||||
device_id,
|
||||
rect->x + dx,
|
||||
rect->y + rect->height + dy,
|
||||
event->button,
|
||||
@ -1746,6 +1766,7 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
|
||||
meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
device_id,
|
||||
op,
|
||||
TRUE,
|
||||
TRUE,
|
||||
@ -1768,6 +1789,7 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
{
|
||||
meta_core_begin_grab_op (display,
|
||||
frame->xwindow,
|
||||
device_id,
|
||||
META_GRAB_OP_MOVING,
|
||||
TRUE,
|
||||
TRUE,
|
||||
@ -1791,28 +1813,28 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_notify_menu_hide (MetaFrames *frames)
|
||||
meta_frames_notify_menu_hide (MetaFrames *frames,
|
||||
Window client_xwindow)
|
||||
{
|
||||
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
if (meta_core_get_grab_op (display) ==
|
||||
Window frame_xwindow;
|
||||
int device_id;
|
||||
|
||||
frame_xwindow = meta_core_get_frame (display, client_xwindow);
|
||||
|
||||
if (frame_xwindow != None &&
|
||||
meta_core_frame_has_grab (display, frame_xwindow, &device_id, NULL) ==
|
||||
META_GRAB_OP_CLICKING_MENU)
|
||||
{
|
||||
Window grab_frame;
|
||||
MetaUIFrame *frame;
|
||||
|
||||
grab_frame = meta_core_get_grab_frame (display);
|
||||
frame = meta_frames_lookup_window (frames, frame_xwindow);
|
||||
|
||||
if (grab_frame != None)
|
||||
if (frame)
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
|
||||
frame = meta_frames_lookup_window (frames, grab_frame);
|
||||
|
||||
if (frame)
|
||||
{
|
||||
redraw_control (frames, frame,
|
||||
META_FRAME_CONTROL_MENU);
|
||||
meta_core_end_grab_op (display, CurrentTime);
|
||||
}
|
||||
redraw_control (frames, frame,
|
||||
META_FRAME_CONTROL_MENU);
|
||||
meta_core_end_grab_op (display, device_id, CurrentTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1825,7 +1847,10 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
MetaFrames *frames;
|
||||
MetaGrabOp op;
|
||||
Display *display;
|
||||
|
||||
int grab_button;
|
||||
GdkDevice *device;
|
||||
int device_id, grab_device_id;
|
||||
|
||||
frames = META_FRAMES (widget);
|
||||
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||
|
||||
@ -1835,17 +1860,21 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
|
||||
clear_tip (frames);
|
||||
|
||||
op = meta_core_get_grab_op (display);
|
||||
op = meta_core_frame_has_grab (display, frame->xwindow,
|
||||
&grab_device_id, &grab_button);
|
||||
|
||||
if (op == META_GRAB_OP_NONE)
|
||||
device = gdk_event_get_device ((GdkEvent *) event);
|
||||
device_id = gdk_x11_device_get_id (device);
|
||||
|
||||
if (op == META_GRAB_OP_NONE ||
|
||||
grab_device_id != device_id)
|
||||
return FALSE;
|
||||
|
||||
/* We only handle the releases we handled the presses for (things
|
||||
* involving frame controls). Window ops that don't require a
|
||||
* frame are handled in the Xlib part of the code, display.c/window.c
|
||||
*/
|
||||
if (frame->xwindow == meta_core_get_grab_frame (display) &&
|
||||
((int) event->button) == meta_core_get_grab_button (display))
|
||||
if (((int) event->button) == grab_button)
|
||||
{
|
||||
MetaFrameControl control;
|
||||
|
||||
@ -1856,8 +1885,8 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
if (control == META_FRAME_CONTROL_MINIMIZE)
|
||||
meta_core_minimize (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
@ -1869,67 +1898,67 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
event->time);
|
||||
meta_core_maximize (display, frame->xwindow);
|
||||
}
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
if (control == META_FRAME_CONTROL_UNMAXIMIZE)
|
||||
meta_core_unmaximize (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
if (control == META_FRAME_CONTROL_DELETE)
|
||||
meta_core_delete (display, frame->xwindow, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_SHADE:
|
||||
if (control == META_FRAME_CONTROL_SHADE)
|
||||
meta_core_shade (display, frame->xwindow, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_UNSHADE:
|
||||
if (control == META_FRAME_CONTROL_UNSHADE)
|
||||
meta_core_unshade (display, frame->xwindow, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_ABOVE:
|
||||
if (control == META_FRAME_CONTROL_ABOVE)
|
||||
meta_core_make_above (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_UNABOVE:
|
||||
if (control == META_FRAME_CONTROL_UNABOVE)
|
||||
meta_core_unmake_above (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_STICK:
|
||||
if (control == META_FRAME_CONTROL_STICK)
|
||||
meta_core_stick (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
if (control == META_FRAME_CONTROL_UNSTICK)
|
||||
meta_core_unstick (display, frame->xwindow);
|
||||
|
||||
meta_core_end_grab_op (display, event->time);
|
||||
meta_core_end_grab_op (display, device_id, event->time);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1941,7 +1970,9 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
* prelit so to let the user know that it can now be pressed.
|
||||
* :)
|
||||
*/
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
meta_frames_update_prelit_control (frames, frame,
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
control);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1950,12 +1981,12 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
static void
|
||||
meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
MetaUIFrame *frame,
|
||||
GdkDevice *device,
|
||||
MetaFrameControl control)
|
||||
{
|
||||
MetaFrameControl old_control;
|
||||
MetaCursor cursor;
|
||||
|
||||
|
||||
meta_verbose ("Updating prelit control from %u to %u\n",
|
||||
frame->prelit_control, control);
|
||||
|
||||
@ -2020,6 +2051,7 @@ meta_frames_update_prelit_control (MetaFrames *frames,
|
||||
/* set/unset the prelight cursor */
|
||||
meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
frame->xwindow,
|
||||
gdk_x11_device_get_id (device),
|
||||
cursor);
|
||||
|
||||
switch (control)
|
||||
@ -2075,8 +2107,8 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
|
||||
frames->last_motion_frame = frame;
|
||||
|
||||
grab_op = meta_core_get_grab_op (display);
|
||||
|
||||
grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL);
|
||||
|
||||
switch (grab_op)
|
||||
{
|
||||
case META_GRAB_OP_CLICKING_MENU:
|
||||
@ -2092,9 +2124,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
case META_GRAB_OP_CLICKING_UNSTICK:
|
||||
{
|
||||
MetaFrameControl control;
|
||||
int x, y;
|
||||
|
||||
gdk_window_get_pointer (frame->window, &x, &y, NULL);
|
||||
gdouble x, y;
|
||||
|
||||
gdk_event_get_coords ((GdkEvent *) event, &x, &y);
|
||||
|
||||
/* Control is set to none unless it matches
|
||||
* the current grab
|
||||
@ -2125,7 +2157,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
control = META_FRAME_CONTROL_NONE;
|
||||
|
||||
/* Update prelit control and cursor */
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
meta_frames_update_prelit_control (frames, frame,
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
control);
|
||||
|
||||
/* No tooltip while in the process of clicking */
|
||||
}
|
||||
@ -2133,14 +2167,15 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
case META_GRAB_OP_NONE:
|
||||
{
|
||||
MetaFrameControl control;
|
||||
int x, y;
|
||||
|
||||
gdk_window_get_pointer (frame->window, &x, &y, NULL);
|
||||
gdouble x, y;
|
||||
|
||||
gdk_event_get_coords ((GdkEvent *) event, &x, &y);
|
||||
control = get_control (frames, frame, x, y);
|
||||
|
||||
/* Update prelit control and cursor */
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
meta_frames_update_prelit_control (frames, frame,
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
control);
|
||||
|
||||
queue_tip (frames);
|
||||
}
|
||||
@ -2472,7 +2507,6 @@ meta_frames_paint (MetaFrames *frames,
|
||||
GdkPixbuf *icon;
|
||||
int w, h;
|
||||
MetaButtonState button_states[META_BUTTON_TYPE_LAST];
|
||||
Window grab_frame;
|
||||
int i;
|
||||
MetaButtonLayout button_layout;
|
||||
MetaGrabOp grab_op;
|
||||
@ -2484,11 +2518,8 @@ meta_frames_paint (MetaFrames *frames,
|
||||
for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
|
||||
button_states[i] = META_BUTTON_STATE_NORMAL;
|
||||
|
||||
grab_frame = meta_core_get_grab_frame (display);
|
||||
grab_op = meta_core_get_grab_op (display);
|
||||
if (grab_frame != frame->xwindow)
|
||||
grab_op = META_GRAB_OP_NONE;
|
||||
|
||||
grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL);
|
||||
|
||||
/* Set prelight state */
|
||||
switch (frame->prelit_control)
|
||||
{
|
||||
@ -2650,7 +2681,9 @@ meta_frames_enter_notify_event (GtkWidget *widget,
|
||||
return FALSE;
|
||||
|
||||
control = get_control (frames, frame, event->x, event->y);
|
||||
meta_frames_update_prelit_control (frames, frame, control);
|
||||
meta_frames_update_prelit_control (frames, frame,
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
control);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -2668,7 +2701,9 @@ meta_frames_leave_notify_event (GtkWidget *widget,
|
||||
if (frame == NULL)
|
||||
return FALSE;
|
||||
|
||||
meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
|
||||
meta_frames_update_prelit_control (frames, frame,
|
||||
gdk_event_get_device ((GdkEvent *) event),
|
||||
META_FRAME_CONTROL_NONE);
|
||||
|
||||
clear_tip (frames);
|
||||
|
||||
|
@ -163,7 +163,8 @@ void meta_frames_move_resize_frame (MetaFrames *frames,
|
||||
void meta_frames_queue_draw (MetaFrames *frames,
|
||||
Window xwindow);
|
||||
|
||||
void meta_frames_notify_menu_hide (MetaFrames *frames);
|
||||
void meta_frames_notify_menu_hide (MetaFrames *frames,
|
||||
Window client_xwindow);
|
||||
|
||||
Window meta_frames_get_moving_frame (MetaFrames *frames);
|
||||
|
||||
|
@ -137,7 +137,7 @@ menu_closed (GtkMenu *widget,
|
||||
|
||||
menu = data;
|
||||
|
||||
meta_frames_notify_menu_hide (menu->frames);
|
||||
meta_frames_notify_menu_hide (menu->frames, menu->client_xwindow);
|
||||
(* menu->func) (menu,
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
menu->client_xwindow,
|
||||
@ -157,7 +157,7 @@ activate_cb (GtkWidget *menuitem, gpointer data)
|
||||
|
||||
md = data;
|
||||
|
||||
meta_frames_notify_menu_hide (md->menu->frames);
|
||||
meta_frames_notify_menu_hide (md->menu->frames, md->menu->client_xwindow);
|
||||
(* md->menu->func) (md->menu,
|
||||
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
md->menu->client_xwindow,
|
||||
@ -498,13 +498,17 @@ meta_window_menu_new (MetaFrames *frames,
|
||||
|
||||
void
|
||||
meta_window_menu_popup (MetaWindowMenu *menu,
|
||||
MetaDevice *device,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp)
|
||||
{
|
||||
GdkDeviceManager *device_manager;
|
||||
GdkDevice *gdkdevice;
|
||||
GdkDisplay *display;
|
||||
GdkPoint *pt;
|
||||
|
||||
|
||||
pt = g_new (GdkPoint, 1);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (menu->menu),
|
||||
@ -514,12 +518,18 @@ meta_window_menu_popup (MetaWindowMenu *menu,
|
||||
|
||||
pt->x = root_x;
|
||||
pt->y = root_y;
|
||||
|
||||
gtk_menu_popup (GTK_MENU (menu->menu),
|
||||
NULL, NULL,
|
||||
popup_position_func, pt,
|
||||
button,
|
||||
timestamp);
|
||||
|
||||
display = gtk_widget_get_display (menu->menu);
|
||||
device_manager = gdk_display_get_device_manager (display);
|
||||
gdkdevice = gdk_x11_device_manager_lookup (device_manager,
|
||||
meta_device_get_id (device));
|
||||
|
||||
gtk_menu_popup_for_device (GTK_MENU (menu->menu),
|
||||
gdkdevice,
|
||||
NULL, NULL,
|
||||
popup_position_func, pt, NULL,
|
||||
button,
|
||||
timestamp);
|
||||
|
||||
if (!gtk_widget_get_visible (menu->menu))
|
||||
meta_warning ("GtkMenu failed to grab the pointer\n");
|
||||
|
@ -25,6 +25,7 @@
|
||||
#define META_MENU_H
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <meta/device.h>
|
||||
#include "frames.h"
|
||||
|
||||
/* Stock icons */
|
||||
@ -52,6 +53,7 @@ MetaWindowMenu* meta_window_menu_new (MetaFrames *frames,
|
||||
MetaWindowMenuFunc func,
|
||||
gpointer data);
|
||||
void meta_window_menu_popup (MetaWindowMenu *menu,
|
||||
MetaDevice *device,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
|
@ -858,12 +858,21 @@ static WnckWindowDisplayInfo
|
||||
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
|
||||
{
|
||||
WnckWindowDisplayInfo wnck_window;
|
||||
MetaFocusInfo *focus_info;
|
||||
GHashTableIter iter;
|
||||
|
||||
wnck_window.icon = window->icon;
|
||||
wnck_window.mini_icon = window->mini_icon;
|
||||
|
||||
wnck_window.is_active = FALSE;
|
||||
if (window == window->display->expected_focus_window)
|
||||
wnck_window.is_active = TRUE;
|
||||
|
||||
g_hash_table_iter_init (&iter, window->display->focus_info);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &focus_info))
|
||||
{
|
||||
if (window == focus_info->expected_focus_window)
|
||||
wnck_window.is_active = TRUE;
|
||||
}
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
|
@ -171,6 +171,7 @@ meta_tile_preview_free (MetaTilePreview *preview)
|
||||
|
||||
void
|
||||
meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaDevice *pointer,
|
||||
MetaRectangle *tile_rect)
|
||||
{
|
||||
GdkWindow *window;
|
||||
@ -187,6 +188,7 @@ meta_tile_preview_show (MetaTilePreview *preview,
|
||||
window = gtk_widget_get_window (preview->preview_window);
|
||||
meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
|
||||
GDK_WINDOW_XID (window),
|
||||
meta_device_get_id (pointer),
|
||||
gtk_get_current_event_time ());
|
||||
|
||||
old_rect.x = old_rect.y = 0;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define META_TILE_PREVIEW_H
|
||||
|
||||
#include <meta/boxes.h>
|
||||
#include <meta/device.h>
|
||||
|
||||
typedef struct _MetaTilePreview MetaTilePreview;
|
||||
|
||||
@ -31,6 +32,7 @@ MetaTilePreview *meta_tile_preview_new (int screen_number,
|
||||
gboolean composited);
|
||||
void meta_tile_preview_free (MetaTilePreview *preview);
|
||||
void meta_tile_preview_show (MetaTilePreview *preview,
|
||||
MetaDevice *pointer,
|
||||
MetaRectangle *rect);
|
||||
void meta_tile_preview_hide (MetaTilePreview *preview);
|
||||
Window meta_tile_preview_get_xwindow (MetaTilePreview *preview,
|
||||
|
118
src/ui/ui.c
118
src/ui/ui.c
@ -30,6 +30,7 @@
|
||||
#include "menu.h"
|
||||
#include "core.h"
|
||||
#include "theme-private.h"
|
||||
#include "input-events.h"
|
||||
|
||||
#include "inlinepixbufs.h"
|
||||
|
||||
@ -60,15 +61,8 @@ struct _MetaUI
|
||||
void
|
||||
meta_ui_init (void)
|
||||
{
|
||||
/* As of 2.91.7, Gdk uses XI2 by default, which conflicts with the
|
||||
* direct X calls we use - in particular, events caused by calls to
|
||||
* XGrabPointer/XGrabKeyboard are no longer understood by GDK, while
|
||||
* GDK will no longer generate the core XEvents we process.
|
||||
* So at least for now, enforce the previous behavior.
|
||||
*/
|
||||
#if GTK_CHECK_VERSION(2, 91, 7)
|
||||
gdk_disable_multidevice ();
|
||||
#endif
|
||||
if (meta_get_use_core_devices ())
|
||||
gdk_disable_multidevice ();
|
||||
|
||||
if (!gtk_init_check (NULL, NULL))
|
||||
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
||||
@ -102,27 +96,30 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
{
|
||||
GdkDisplay *gdisplay;
|
||||
GdkDeviceManager *gmanager;
|
||||
GdkDevice *gdevice;
|
||||
MetaUI *ui;
|
||||
GdkEvent *gevent;
|
||||
GdkWindow *gdk_window;
|
||||
Window window;
|
||||
MetaDisplay *display;
|
||||
MetaDevice *device;
|
||||
gdouble x, y, x_root, y_root;
|
||||
guint evtype, n_button;
|
||||
Time evtime;
|
||||
|
||||
switch (xevent->type)
|
||||
{
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
window = xevent->xbutton.window;
|
||||
break;
|
||||
case MotionNotify:
|
||||
window = xevent->xmotion.window;
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
window = xevent->xcrossing.window;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
display = meta_display_for_x_display (xevent->xany.display);
|
||||
|
||||
if (!meta_input_event_get_type (display, xevent, &evtype))
|
||||
return FALSE;
|
||||
|
||||
if (evtype != ButtonPress &&
|
||||
evtype != ButtonRelease &&
|
||||
evtype != EnterNotify &&
|
||||
evtype != LeaveNotify &&
|
||||
evtype != MotionNotify)
|
||||
return FALSE;
|
||||
|
||||
window = meta_input_event_get_window (display, xevent);
|
||||
|
||||
gdisplay = gdk_x11_lookup_xdisplay (xevent->xany.display);
|
||||
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
|
||||
@ -133,18 +130,32 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
if (gdk_window == NULL)
|
||||
return FALSE;
|
||||
|
||||
device = meta_input_event_get_device (display, xevent);
|
||||
|
||||
if (!device)
|
||||
return FALSE;
|
||||
|
||||
gmanager = gdk_display_get_device_manager (gdisplay);
|
||||
gdevice = gdk_x11_device_manager_lookup (gmanager,
|
||||
meta_device_get_id (device));
|
||||
|
||||
/* If GDK already thinks it has a grab, we better let it see events; this
|
||||
* is the menu-navigation case and events need to get sent to the appropriate
|
||||
* (client-side) subwindow for individual menu items.
|
||||
*/
|
||||
if (gdk_display_pointer_is_grabbed (gdisplay))
|
||||
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
|
||||
return FALSE;
|
||||
|
||||
switch (xevent->type)
|
||||
evtime = meta_input_event_get_time (display, xevent);
|
||||
meta_input_event_get_coordinates (display, xevent,
|
||||
&x, &y, &x_root, &y_root);
|
||||
switch (evtype)
|
||||
{
|
||||
case ButtonPress:
|
||||
case ButtonRelease:
|
||||
if (xevent->type == ButtonPress)
|
||||
meta_input_event_get_button (display, xevent, &n_button);
|
||||
|
||||
if (evtype == ButtonPress)
|
||||
{
|
||||
GtkSettings *settings = gtk_settings_get_default ();
|
||||
int double_click_time;
|
||||
@ -155,11 +166,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
"gtk-double-click-distance", &double_click_distance,
|
||||
NULL);
|
||||
|
||||
if (xevent->xbutton.button == ui->button_click_number &&
|
||||
xevent->xbutton.window == ui->button_click_window &&
|
||||
xevent->xbutton.time < ui->button_click_time + double_click_time &&
|
||||
ABS (xevent->xbutton.x - ui->button_click_x) <= double_click_distance &&
|
||||
ABS (xevent->xbutton.y - ui->button_click_y) <= double_click_distance)
|
||||
if (n_button == ui->button_click_number &&
|
||||
window == ui->button_click_window &&
|
||||
evtime < ui->button_click_time + double_click_time &&
|
||||
ABS ((int) x - ui->button_click_x) <= double_click_distance &&
|
||||
ABS ((int) y - ui->button_click_y) <= double_click_distance)
|
||||
{
|
||||
gevent = gdk_event_new (GDK_2BUTTON_PRESS);
|
||||
|
||||
@ -168,11 +179,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
else
|
||||
{
|
||||
gevent = gdk_event_new (GDK_BUTTON_PRESS);
|
||||
ui->button_click_number = xevent->xbutton.button;
|
||||
ui->button_click_window = xevent->xbutton.window;
|
||||
ui->button_click_time = xevent->xbutton.time;
|
||||
ui->button_click_x = xevent->xbutton.x;
|
||||
ui->button_click_y = xevent->xbutton.y;
|
||||
ui->button_click_number = n_button;
|
||||
ui->button_click_window = window;
|
||||
ui->button_click_time = evtime;
|
||||
ui->button_click_x = (int) x;
|
||||
ui->button_click_y = (int) y;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -181,25 +192,29 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
}
|
||||
|
||||
gevent->button.window = g_object_ref (gdk_window);
|
||||
gevent->button.button = xevent->xbutton.button;
|
||||
gevent->button.time = xevent->xbutton.time;
|
||||
gevent->button.x = xevent->xbutton.x;
|
||||
gevent->button.y = xevent->xbutton.y;
|
||||
gevent->button.x_root = xevent->xbutton.x_root;
|
||||
gevent->button.y_root = xevent->xbutton.y_root;
|
||||
gevent->button.button = n_button;
|
||||
gevent->button.time = evtime;
|
||||
gevent->button.x = x;
|
||||
gevent->button.y = y;
|
||||
gevent->button.x_root = x_root;
|
||||
gevent->button.y_root = y_root;
|
||||
|
||||
break;
|
||||
case MotionNotify:
|
||||
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
|
||||
gevent->motion.type = GDK_MOTION_NOTIFY;
|
||||
gevent->motion.window = g_object_ref (gdk_window);
|
||||
gevent->motion.x = x;
|
||||
gevent->motion.y = y;
|
||||
gevent->motion.x_root = x_root;
|
||||
gevent->motion.y_root = y_root;
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
gevent = gdk_event_new (xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
|
||||
gevent = gdk_event_new (evtype == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
|
||||
gevent->crossing.window = g_object_ref (gdk_window);
|
||||
gevent->crossing.x = xevent->xcrossing.x;
|
||||
gevent->crossing.y = xevent->xcrossing.y;
|
||||
gevent->crossing.x = x;
|
||||
gevent->crossing.y = y;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
@ -207,8 +222,7 @@ maybe_redirect_mouse_event (XEvent *xevent)
|
||||
}
|
||||
|
||||
/* If we've gotten here, we've created the gdk_event and should send it on */
|
||||
gmanager = gdk_display_get_device_manager (gdisplay);
|
||||
gdk_event_set_device (gevent, gdk_device_manager_get_client_pointer (gmanager));
|
||||
gdk_event_set_device (gevent, gdevice);
|
||||
gtk_main_do_event (gevent);
|
||||
gdk_event_free (gevent);
|
||||
|
||||
@ -382,7 +396,8 @@ meta_ui_create_frame_window (MetaUI *ui,
|
||||
&attrs, attributes_mask);
|
||||
|
||||
gdk_window_resize (window, width, height);
|
||||
|
||||
gdk_window_set_support_multidevice (window, TRUE);
|
||||
|
||||
meta_frames_manage_window (ui->frames, GDK_WINDOW_XID (window), window);
|
||||
|
||||
return GDK_WINDOW_XID (window);
|
||||
@ -523,12 +538,13 @@ meta_ui_window_menu_new (MetaUI *ui,
|
||||
|
||||
void
|
||||
meta_ui_window_menu_popup (MetaWindowMenu *menu,
|
||||
MetaDevice *device,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_window_menu_popup (menu, root_x, root_y, button, timestamp);
|
||||
meta_window_menu_popup (menu, device, root_x, root_y, button, timestamp);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include <meta/common.h>
|
||||
#include <meta/device.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <cairo.h>
|
||||
@ -132,6 +133,7 @@ MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui,
|
||||
MetaWindowMenuFunc func,
|
||||
gpointer data);
|
||||
void meta_ui_window_menu_popup (MetaWindowMenu *menu,
|
||||
MetaDevice *device,
|
||||
int root_x,
|
||||
int root_y,
|
||||
int button,
|
||||
|
Reference in New Issue
Block a user