mirror of
https://github.com/brl/mutter.git
synced 2024-12-02 12:50:53 -05:00
7851e69bbf
Instead of from ClutterX11. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2014>
277 lines
11 KiB
C
277 lines
11 KiB
C
/*
|
|
* Copyright (C) 2016 Red Hat Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Jonas Ådahl <jadahl@gmail.com>
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "backends/x11/meta-virtual-input-device-x11.h"
|
|
|
|
#include <glib-object.h>
|
|
|
|
#include <X11/extensions/XTest.h>
|
|
|
|
#include "backends/x11/meta-backend-x11.h"
|
|
#include "backends/x11/meta-clutter-backend-x11.h"
|
|
#include "backends/x11/meta-keymap-x11.h"
|
|
#include "backends/x11/meta-seat-x11.h"
|
|
#include "clutter/clutter.h"
|
|
|
|
#define DISCRETE_SCROLL_STEP 10.0
|
|
|
|
struct _MetaVirtualInputDeviceX11
|
|
{
|
|
ClutterVirtualInputDevice parent;
|
|
|
|
double accum_scroll_dx;
|
|
double accum_scroll_dy;
|
|
};
|
|
|
|
G_DEFINE_TYPE (MetaVirtualInputDeviceX11,
|
|
meta_virtual_input_device_x11,
|
|
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
|
|
|
|
static Display *
|
|
xdisplay_from_virtual_input_device (ClutterVirtualInputDevice *virtual_device)
|
|
{
|
|
ClutterSeat *seat = clutter_virtual_input_device_get_seat (virtual_device);
|
|
MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
|
|
MetaBackend *backend = meta_seat_x11_get_backend (seat_x11);
|
|
|
|
return meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
double dx,
|
|
double dy)
|
|
{
|
|
Display *xdisplay = xdisplay_from_virtual_input_device (virtual_device);
|
|
|
|
XTestFakeRelativeMotionEvent (xdisplay, (int) dx, (int) dy, 0);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
double x,
|
|
double y)
|
|
{
|
|
ClutterSeat *seat = clutter_virtual_input_device_get_seat (virtual_device);
|
|
MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
|
|
MetaBackend *backend = meta_seat_x11_get_backend (seat_x11);
|
|
Display *xdisplay;
|
|
Screen *xscreen;
|
|
|
|
xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
|
xscreen = meta_backend_x11_get_xscreen (META_BACKEND_X11 (backend));
|
|
|
|
XTestFakeMotionEvent (xdisplay, XScreenNumberOfScreen (xscreen),
|
|
(int) x, (int) y, 0);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_button (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
uint32_t button,
|
|
ClutterButtonState button_state)
|
|
{
|
|
Display *xdisplay = xdisplay_from_virtual_input_device (virtual_device);
|
|
|
|
XTestFakeButtonEvent (xdisplay,
|
|
button, button_state == CLUTTER_BUTTON_STATE_PRESSED, 0);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
ClutterScrollDirection direction,
|
|
ClutterScrollSource scroll_source)
|
|
{
|
|
Display *xdisplay = xdisplay_from_virtual_input_device (virtual_device);
|
|
int button;
|
|
|
|
switch (direction)
|
|
{
|
|
case CLUTTER_SCROLL_UP:
|
|
button = 4;
|
|
break;
|
|
case CLUTTER_SCROLL_DOWN:
|
|
button = 5;
|
|
break;
|
|
case CLUTTER_SCROLL_LEFT:
|
|
button = 6;
|
|
break;
|
|
case CLUTTER_SCROLL_RIGHT:
|
|
button = 7;
|
|
break;
|
|
default:
|
|
g_warn_if_reached ();
|
|
return;
|
|
}
|
|
|
|
XTestFakeButtonEvent (xdisplay, button, True, 0);
|
|
XTestFakeButtonEvent (xdisplay, button, False, 0);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_scroll_continuous (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
double dx,
|
|
double dy,
|
|
ClutterScrollSource scroll_source,
|
|
ClutterScrollFinishFlags finish_flags)
|
|
{
|
|
MetaVirtualInputDeviceX11 *virtual_device_x11;
|
|
ClutterScrollDirection direction;
|
|
int i, n_xscrolls, n_yscrolls;
|
|
|
|
virtual_device_x11 = META_VIRTUAL_INPUT_DEVICE_X11 (virtual_device);
|
|
|
|
virtual_device_x11->accum_scroll_dx += dx;
|
|
virtual_device_x11->accum_scroll_dy += dy;
|
|
n_xscrolls = floor ((fabs (virtual_device_x11->accum_scroll_dx) + DBL_EPSILON) /
|
|
DISCRETE_SCROLL_STEP);
|
|
n_yscrolls = floor ((fabs (virtual_device_x11->accum_scroll_dy) + DBL_EPSILON) /
|
|
DISCRETE_SCROLL_STEP);
|
|
|
|
direction = virtual_device_x11->accum_scroll_dx > 0 ? CLUTTER_SCROLL_RIGHT
|
|
: CLUTTER_SCROLL_LEFT;
|
|
for (i = 0; i < n_xscrolls; ++i)
|
|
{
|
|
meta_virtual_input_device_x11_notify_discrete_scroll (
|
|
virtual_device, time_us, direction, CLUTTER_SCROLL_SOURCE_WHEEL);
|
|
}
|
|
|
|
direction = virtual_device_x11->accum_scroll_dy > 0 ? CLUTTER_SCROLL_DOWN
|
|
: CLUTTER_SCROLL_UP;
|
|
for (i = 0; i < n_yscrolls; ++i)
|
|
{
|
|
meta_virtual_input_device_x11_notify_discrete_scroll (
|
|
virtual_device, time_us, direction, CLUTTER_SCROLL_SOURCE_WHEEL);
|
|
}
|
|
|
|
virtual_device_x11->accum_scroll_dx =
|
|
fmod (virtual_device_x11->accum_scroll_dx, DISCRETE_SCROLL_STEP);
|
|
virtual_device_x11->accum_scroll_dy =
|
|
fmod (virtual_device_x11->accum_scroll_dy, DISCRETE_SCROLL_STEP);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
uint32_t key,
|
|
ClutterKeyState key_state)
|
|
{
|
|
Display *xdisplay = xdisplay_from_virtual_input_device (virtual_device);
|
|
|
|
XTestFakeKeyEvent (xdisplay,
|
|
key + 8, key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
uint32_t keyval,
|
|
ClutterKeyState key_state)
|
|
{
|
|
ClutterBackend *backend = clutter_get_default_backend ();
|
|
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
|
MetaKeymapX11 *keymap = META_KEYMAP_X11 (clutter_seat_get_keymap (seat));
|
|
Display *xdisplay = xdisplay_from_virtual_input_device (virtual_device);
|
|
uint32_t keycode, level;
|
|
|
|
if (!meta_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level))
|
|
{
|
|
level = 0;
|
|
|
|
if (!meta_keymap_x11_reserve_keycode (keymap, keyval, &keycode))
|
|
{
|
|
g_warning ("No keycode found for keyval %x in current group", keyval);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!meta_keymap_x11_get_is_modifier (keymap, keycode) &&
|
|
key_state == CLUTTER_KEY_STATE_PRESSED)
|
|
meta_keymap_x11_lock_modifiers (keymap, level, TRUE);
|
|
|
|
XTestFakeKeyEvent (xdisplay,
|
|
(KeyCode) keycode,
|
|
key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
|
|
|
|
|
if (key_state == CLUTTER_KEY_STATE_RELEASED)
|
|
{
|
|
if (!meta_keymap_x11_get_is_modifier (keymap, keycode))
|
|
meta_keymap_x11_lock_modifiers (keymap, level, FALSE);
|
|
meta_keymap_x11_release_keycode_if_needed (keymap, keycode);
|
|
}
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_touch_down (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
int device_slot,
|
|
double x,
|
|
double y)
|
|
{
|
|
g_warning ("Virtual touch motion not implemented under X11");
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_touch_motion (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
int device_slot,
|
|
double x,
|
|
double y)
|
|
{
|
|
g_warning ("Virtual touch motion not implemented under X11");
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_notify_touch_up (ClutterVirtualInputDevice *virtual_device,
|
|
uint64_t time_us,
|
|
int device_slot)
|
|
{
|
|
g_warning ("Virtual touch motion not implemented under X11");
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_init (MetaVirtualInputDeviceX11 *virtual_device_x11)
|
|
{
|
|
}
|
|
|
|
static void
|
|
meta_virtual_input_device_x11_class_init (MetaVirtualInputDeviceX11Class *klass)
|
|
{
|
|
ClutterVirtualInputDeviceClass *virtual_input_device_class =
|
|
CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass);
|
|
|
|
virtual_input_device_class->notify_relative_motion = meta_virtual_input_device_x11_notify_relative_motion;
|
|
virtual_input_device_class->notify_absolute_motion = meta_virtual_input_device_x11_notify_absolute_motion;
|
|
virtual_input_device_class->notify_button = meta_virtual_input_device_x11_notify_button;
|
|
virtual_input_device_class->notify_discrete_scroll = meta_virtual_input_device_x11_notify_discrete_scroll;
|
|
virtual_input_device_class->notify_scroll_continuous = meta_virtual_input_device_x11_notify_scroll_continuous;
|
|
virtual_input_device_class->notify_key = meta_virtual_input_device_x11_notify_key;
|
|
virtual_input_device_class->notify_keyval = meta_virtual_input_device_x11_notify_keyval;
|
|
virtual_input_device_class->notify_touch_down = meta_virtual_input_device_x11_notify_touch_down;
|
|
virtual_input_device_class->notify_touch_motion = meta_virtual_input_device_x11_notify_touch_motion;
|
|
virtual_input_device_class->notify_touch_up = meta_virtual_input_device_x11_notify_touch_up;
|
|
}
|