Compare commits
107 Commits
wip/tablet
...
wip/garnac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e3f96d972 | ||
|
|
5f91d34f88 | ||
|
|
d0a708b42c | ||
|
|
d940d5e581 | ||
|
|
70f69e5de4 | ||
|
|
c2ce0e6795 | ||
|
|
adbd566f83 | ||
|
|
f511f65a14 | ||
|
|
0942d68f1a | ||
|
|
73d5d837db | ||
|
|
ea5b691ac6 | ||
|
|
53d1b11386 | ||
|
|
85e8feca67 | ||
|
|
fb47374629 | ||
|
|
9a92d5fe89 | ||
|
|
337b833e23 | ||
|
|
d25af2a02a | ||
|
|
820a6ab406 | ||
|
|
cd225c4e19 | ||
|
|
98cd8136ca | ||
|
|
e6972924d0 | ||
|
|
ead09bf6cc | ||
|
|
fe09a3c4e2 | ||
|
|
ee6867611f | ||
|
|
207c11d1f7 | ||
|
|
c6beb1cfc5 | ||
|
|
b34fe72bb7 | ||
|
|
18f301cec9 | ||
|
|
406677e2a0 | ||
|
|
4f25057413 | ||
|
|
2f492c133c | ||
|
|
138a47b8f9 | ||
|
|
62e4954c96 | ||
|
|
062b696df2 | ||
|
|
5effde59f6 | ||
|
|
76595af8af | ||
|
|
21c8911254 | ||
|
|
35554555e0 | ||
|
|
e2ad8700a9 | ||
|
|
323c608b0c | ||
|
|
0efe076a0a | ||
|
|
6f7f98540f | ||
|
|
56632d2ef7 | ||
|
|
6296d30e1a | ||
|
|
ed16b40c98 | ||
|
|
7bba20e536 | ||
|
|
8e6244238d | ||
|
|
ba9ec00694 | ||
|
|
08cda496f8 | ||
|
|
f9552bb9c0 | ||
|
|
7e267e9b01 | ||
|
|
fbb4c0b831 | ||
|
|
d7faab76e0 | ||
|
|
b7892ba1c5 | ||
|
|
ab2d2af176 | ||
|
|
80674fc9e4 | ||
|
|
9587a60da4 | ||
|
|
73958aeb59 | ||
|
|
77b33a86b8 | ||
|
|
f3b94d9a78 | ||
|
|
af8b938f92 | ||
|
|
1496a7ead3 | ||
|
|
e7e62ee4a4 | ||
|
|
f6e471fca4 | ||
|
|
1dd121002f | ||
|
|
526fdca3fb | ||
|
|
220ac7c8f2 | ||
|
|
5ea39e0e77 | ||
|
|
1c23d4bc51 | ||
|
|
2e6bfa8bae | ||
|
|
a59170c09f | ||
|
|
aa9b2c5494 | ||
|
|
c1d157e136 | ||
|
|
2cd21f1b20 | ||
|
|
5ccde659c1 | ||
|
|
fd62a1f6ce | ||
|
|
b8808ca24d | ||
|
|
41ff0aaf60 | ||
|
|
c5d0791710 | ||
|
|
828277f5e0 | ||
|
|
e56d6b06cf | ||
|
|
96aed5fd2e | ||
|
|
88c510c38a | ||
|
|
6bcff556b5 | ||
|
|
81736b1dea | ||
|
|
cc09ca8892 | ||
|
|
d76aa89be9 | ||
|
|
8cd4b0e11f | ||
|
|
6b08990dcc | ||
|
|
8b769a3412 | ||
|
|
8d3ac8c3e9 | ||
|
|
074b0d6b2a | ||
|
|
8e8cdf1873 | ||
|
|
72ee6b8b65 | ||
|
|
3d9bb1cc09 | ||
|
|
4ed59a020d | ||
|
|
b5e797f453 | ||
|
|
125cba7100 | ||
|
|
720cbc5e5f | ||
|
|
ad7ec6b979 | ||
|
|
991f2d696a | ||
|
|
76175a48d5 | ||
|
|
c8392e025f | ||
|
|
820ffa2781 | ||
|
|
51f7892600 | ||
|
|
de1464f88f | ||
|
|
aebd5ba6e0 |
20
NEWS
20
NEWS
@@ -1,3 +1,23 @@
|
||||
3.21.4
|
||||
======
|
||||
* Fix missing frame border around GTK+ dialogs [Florian; #745060]
|
||||
* Improve X11 <-> wayland copy and paste interaction [Carlos; #768007]
|
||||
* Add support for NV_robustness_video_memory_purge extension [Rui; #739178]
|
||||
* Fix restoring the old focused window on restart [Owen; #766243]
|
||||
* Fix fullscreen windows on other monitors stealing focus after closing
|
||||
a window [Rui; #768221]
|
||||
* Draw monitor content to individual framebuffer [Jonas; #768976]
|
||||
* Provide screen capture API [Jonas; #768978]
|
||||
* Misc. bug fixes and cleanups [Rui, Owen, Luca, Olivier, Jonas, Carlos;
|
||||
#767969, #768243, #762407, #767997, #768039, #768977, #768977]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Luca Bruno, Olivier Fourdan, Carlos Garnacho, Rui Matos,
|
||||
Florian Müllner, Owen W. Taylor
|
||||
|
||||
Translations:
|
||||
Andika Triwidada [id]
|
||||
|
||||
3.21.3
|
||||
======
|
||||
* Don't create invalid UTF-8 window description strings [Rui; #765535]
|
||||
|
||||
@@ -123,6 +123,7 @@ source_h = \
|
||||
clutter-transition.h \
|
||||
clutter-types.h \
|
||||
clutter-units.h \
|
||||
clutter-virtual-input-device.h \
|
||||
clutter-zoom-action.h \
|
||||
$(NULL)
|
||||
|
||||
@@ -168,6 +169,7 @@ source_c = \
|
||||
clutter-image.c \
|
||||
clutter-input-device.c \
|
||||
clutter-input-device-tool.c \
|
||||
clutter-virtual-input-device.c \
|
||||
clutter-interval.c \
|
||||
clutter-keyframe-transition.c \
|
||||
clutter-keysyms-table.c \
|
||||
@@ -418,6 +420,14 @@ x11_source_h_priv += \
|
||||
x11/clutter-input-device-xi2.h \
|
||||
$(NULL)
|
||||
|
||||
x11_source_c += \
|
||||
x11/clutter-virtual-input-device-x11.c \
|
||||
$(NULL)
|
||||
|
||||
x11_source_h_priv += \
|
||||
x11/clutter-virtual-input-device-x11.h \
|
||||
$(NULL)
|
||||
|
||||
backend_source_h += $(x11_source_h)
|
||||
backend_source_c += $(x11_source_c)
|
||||
backend_source_h_priv += $(x11_source_h_priv)
|
||||
@@ -458,13 +468,17 @@ backend_source_c += $(glx_source_c)
|
||||
evdev_c_priv = \
|
||||
evdev/clutter-device-manager-evdev.c \
|
||||
evdev/clutter-input-device-evdev.c \
|
||||
evdev/clutter-seat-evdev.c \
|
||||
evdev/clutter-virtual-input-device-evdev.c \
|
||||
evdev/clutter-event-evdev.c \
|
||||
evdev/clutter-input-device-tool-evdev.c \
|
||||
$(NULL)
|
||||
evdev_h_priv = \
|
||||
evdev/clutter-device-manager-evdev.h \
|
||||
evdev/clutter-input-device-evdev.h \
|
||||
evdev/clutter-seat-evdev.h \
|
||||
evdev/clutter-input-device-tool-evdev.h \
|
||||
evdev/clutter-virtual-input-device-evdev.h \
|
||||
$(NULL)
|
||||
evdev_h = evdev/clutter-evdev.h
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
|
||||
struct _ClutterDeviceManagerPrivate
|
||||
{
|
||||
@@ -435,3 +436,25 @@ _clutter_device_manager_get_backend (ClutterDeviceManager *manager)
|
||||
|
||||
return manager->priv->backend;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_device_manager_create_virtual_device:
|
||||
* @device_manager: a #ClutterDeviceManager
|
||||
* @device_type: the type of the virtual device
|
||||
*
|
||||
* Creates a virtual input device.
|
||||
*
|
||||
* Returns: (transfer full): a newly created virtual device
|
||||
**/
|
||||
ClutterVirtualInputDevice *
|
||||
clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDeviceType device_type)
|
||||
{
|
||||
ClutterDeviceManagerClass *manager_class;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_DEVICE_MANAGER (device_manager), NULL);
|
||||
|
||||
manager_class = CLUTTER_DEVICE_MANAGER_GET_CLASS (device_manager);
|
||||
return manager_class->create_virtual_device (device_manager,
|
||||
device_type);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ struct _ClutterDeviceManagerClass
|
||||
ClutterInputDevice *device);
|
||||
void (* select_stage_events) (ClutterDeviceManager *manager,
|
||||
ClutterStage *stage);
|
||||
ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *manager,
|
||||
ClutterInputDeviceType device_type);
|
||||
|
||||
/* padding */
|
||||
gpointer _padding[7];
|
||||
@@ -105,6 +107,10 @@ CLUTTER_AVAILABLE_IN_1_2
|
||||
ClutterInputDevice * clutter_device_manager_get_core_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDeviceType device_type);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterVirtualInputDevice *clutter_device_manager_create_virtual_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDeviceType device_type);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_DEVICE_MANAGER_H__ */
|
||||
|
||||
@@ -139,7 +139,7 @@ clutter_stage_view_set_property (GObject *object,
|
||||
priv->layout = *layout;
|
||||
break;
|
||||
case PROP_FRAMEBUFFER:
|
||||
priv->framebuffer = g_value_get_boxed (value);
|
||||
priv->framebuffer = g_value_dup_boxed (value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ typedef struct _ClutterState ClutterState;
|
||||
|
||||
typedef struct _ClutterInputDeviceTool ClutterInputDeviceTool;
|
||||
typedef struct _ClutterInputDevice ClutterInputDevice;
|
||||
typedef struct _ClutterVirtualInputDevice ClutterVirtualInputDevice;
|
||||
|
||||
typedef CoglMatrix ClutterMatrix;
|
||||
|
||||
|
||||
222
clutter/clutter/clutter-virtual-input-device.c
Normal file
222
clutter/clutter/clutter-virtual-input-device.c
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clutter-build-config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
|
||||
#include "clutter-device-manager.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-enum-types.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_DEVICE_MANAGER,
|
||||
PROP_DEVICE_TYPE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
typedef struct _ClutterVirtualInputDevicePrivate
|
||||
{
|
||||
ClutterDeviceManager *manager;
|
||||
ClutterInputDeviceType device_type;
|
||||
} ClutterVirtualInputDevicePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (ClutterVirtualInputDevice,
|
||||
clutter_virtual_input_device,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
void
|
||||
clutter_virtual_input_device_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *klass =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device);
|
||||
|
||||
klass->notify_relative_motion (virtual_device, time_us, dx, dy);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_virtual_input_device_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *klass =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device);
|
||||
|
||||
klass->notify_absolute_motion (virtual_device, time_us, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_virtual_input_device_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *klass =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device);
|
||||
|
||||
klass->notify_button (virtual_device, time_us, button, button_state);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_virtual_input_device_notify_key (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *klass =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device);
|
||||
|
||||
klass->notify_key (virtual_device, time_us, key, key_state);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_virtual_input_device_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *klass =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_GET_CLASS (virtual_device);
|
||||
|
||||
klass->notify_keyval (virtual_device, time_us, keyval, key_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_virtual_input_device_get_manager:
|
||||
* @virtual_device: a virtual device
|
||||
*
|
||||
* Gets the device manager of this virtual device.
|
||||
*
|
||||
* Returns: (transfer none): The #ClutterDeviceManager of this virtual device
|
||||
**/
|
||||
ClutterDeviceManager *
|
||||
clutter_virtual_input_device_get_manager (ClutterVirtualInputDevice *virtual_device)
|
||||
{
|
||||
ClutterVirtualInputDevicePrivate *priv =
|
||||
clutter_virtual_input_device_get_instance_private (virtual_device);
|
||||
|
||||
return priv->manager;
|
||||
}
|
||||
|
||||
int
|
||||
clutter_virtual_input_device_get_device_type (ClutterVirtualInputDevice *virtual_device)
|
||||
{
|
||||
ClutterVirtualInputDevicePrivate *priv =
|
||||
clutter_virtual_input_device_get_instance_private (virtual_device);
|
||||
|
||||
return priv->device_type;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterVirtualInputDevice *virtual_device =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
||||
ClutterVirtualInputDevicePrivate *priv =
|
||||
clutter_virtual_input_device_get_instance_private (virtual_device);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEVICE_MANAGER:
|
||||
g_value_set_object (value, priv->manager);
|
||||
break;
|
||||
case PROP_DEVICE_TYPE:
|
||||
g_value_set_enum (value, priv->device_type);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterVirtualInputDevice *virtual_device =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
||||
ClutterVirtualInputDevicePrivate *priv =
|
||||
clutter_virtual_input_device_get_instance_private (virtual_device);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEVICE_MANAGER:
|
||||
priv->manager = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_DEVICE_TYPE:
|
||||
priv->device_type = g_value_get_enum (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_init (ClutterVirtualInputDevice *virtual_device)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_class_init (ClutterVirtualInputDeviceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->get_property = clutter_virtual_input_device_get_property;
|
||||
object_class->set_property = clutter_virtual_input_device_set_property;
|
||||
|
||||
obj_props[PROP_DEVICE_MANAGER] =
|
||||
g_param_spec_object ("device-manager",
|
||||
P_("Device Manager"),
|
||||
P_("The device manager instance"),
|
||||
CLUTTER_TYPE_DEVICE_MANAGER,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
obj_props[PROP_DEVICE_TYPE] =
|
||||
g_param_spec_enum ("device-type",
|
||||
P_("Device type"),
|
||||
P_("Device type"),
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TYPE,
|
||||
CLUTTER_POINTER_DEVICE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
116
clutter/clutter/clutter-virtual-input-device.h
Normal file
116
clutter/clutter/clutter-virtual-input-device.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_H__
|
||||
#define __CLUTTER_VIRTUAL_INPUT_DEVICE_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "clutter-device-manager.h"
|
||||
|
||||
#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE (clutter_virtual_input_device_get_type ())
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterVirtualInputDevice,
|
||||
clutter_virtual_input_device,
|
||||
CLUTTER, VIRTUAL_INPUT_DEVICE,
|
||||
GObject)
|
||||
|
||||
typedef enum _ClutterButtonState
|
||||
{
|
||||
CLUTTER_BUTTON_STATE_RELEASED,
|
||||
CLUTTER_BUTTON_STATE_PRESSED
|
||||
} ClutterButtonState;
|
||||
|
||||
typedef enum _ClutterKeyState
|
||||
{
|
||||
CLUTTER_KEY_STATE_RELEASED,
|
||||
CLUTTER_KEY_STATE_PRESSED
|
||||
} ClutterKeyState;
|
||||
|
||||
struct _ClutterVirtualInputDeviceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*notify_relative_motion) (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy);
|
||||
|
||||
void (*notify_absolute_motion) (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
void (*notify_button) (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state);
|
||||
|
||||
void (*notify_key) (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state);
|
||||
void (*notify_keyval) (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state);
|
||||
};
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_virtual_input_device_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_virtual_input_device_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_virtual_input_device_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_virtual_input_device_notify_key (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_virtual_input_device_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
ClutterDeviceManager * clutter_virtual_input_device_get_manager (ClutterVirtualInputDevice *virtual_device);
|
||||
|
||||
int clutter_virtual_input_device_get_device_type (ClutterVirtualInputDevice *virtual_device);
|
||||
|
||||
#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_H__ */
|
||||
@@ -107,6 +107,7 @@
|
||||
#include "clutter-transition.h"
|
||||
#include "clutter-units.h"
|
||||
#include "clutter-version.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "clutter-zoom-action.h"
|
||||
|
||||
#include "clutter-deprecated.h"
|
||||
|
||||
@@ -46,6 +46,8 @@
|
||||
#include "clutter-device-manager-private.h"
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-input-device-evdev.h"
|
||||
#include "clutter-seat-evdev.h"
|
||||
#include "clutter-virtual-input-device-evdev.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
@@ -59,12 +61,6 @@
|
||||
|
||||
#define DISCRETE_SCROLL_STEP 10.0
|
||||
|
||||
#define AUTOREPEAT_VALUE 2
|
||||
|
||||
/* Try to keep the pointer inside the stage. Hopefully no one is using
|
||||
* this backend with stages smaller than this. */
|
||||
#define INITIAL_POINTER_X 16
|
||||
#define INITIAL_POINTER_Y 16
|
||||
|
||||
/*
|
||||
* Clutter makes the assumption that two core devices have ID's 2 and 3 (core
|
||||
@@ -76,50 +72,8 @@
|
||||
*/
|
||||
#define INITIAL_DEVICE_ID 2
|
||||
|
||||
typedef struct _ClutterTouchState ClutterTouchState;
|
||||
typedef struct _ClutterEventFilter ClutterEventFilter;
|
||||
|
||||
struct _ClutterTouchState
|
||||
{
|
||||
guint32 id;
|
||||
ClutterPoint coords;
|
||||
};
|
||||
|
||||
struct _ClutterSeatEvdev
|
||||
{
|
||||
struct libinput_seat *libinput_seat;
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
|
||||
GSList *devices;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
|
||||
GHashTable *touches;
|
||||
|
||||
struct xkb_state *xkb;
|
||||
xkb_led_index_t caps_lock_led;
|
||||
xkb_led_index_t num_lock_led;
|
||||
xkb_led_index_t scroll_lock_led;
|
||||
uint32_t button_state;
|
||||
|
||||
/* keyboard repeat */
|
||||
gboolean repeat;
|
||||
guint32 repeat_delay;
|
||||
guint32 repeat_interval;
|
||||
guint32 repeat_key;
|
||||
guint32 repeat_count;
|
||||
guint32 repeat_timer;
|
||||
ClutterInputDevice *repeat_device;
|
||||
|
||||
gfloat pointer_x;
|
||||
gfloat pointer_y;
|
||||
|
||||
/* Emulation of discrete scroll events out of smooth ones */
|
||||
gfloat accum_scroll_dx;
|
||||
gfloat accum_scroll_dy;
|
||||
};
|
||||
|
||||
struct _ClutterEventFilter
|
||||
{
|
||||
ClutterEvdevFilterFunc func;
|
||||
@@ -198,24 +152,6 @@ static const char *option_xkb_layout = "us";
|
||||
static const char *option_xkb_variant = "";
|
||||
static const char *option_xkb_options = "";
|
||||
|
||||
static inline guint64
|
||||
us (guint64 us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline guint64
|
||||
ms2us (guint64 ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
us2ms (guint64 us)
|
||||
{
|
||||
return (guint32) (us / 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_evdev_copy_event_data (ClutterEventExtender *event_extender,
|
||||
const ClutterEvent *src,
|
||||
@@ -299,134 +235,34 @@ queue_event (ClutterEvent *event)
|
||||
_clutter_event_push (event, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_repeat_timer (ClutterSeatEvdev *seat)
|
||||
void
|
||||
_clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
ClutterInputDevice *core_pointer,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
float *new_x,
|
||||
float *new_y)
|
||||
{
|
||||
if (seat->repeat_timer)
|
||||
if (manager_evdev->priv->constrain_callback)
|
||||
{
|
||||
g_source_remove (seat->repeat_timer);
|
||||
seat->repeat_timer = 0;
|
||||
g_clear_object (&seat->repeat_device);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keyboard_repeat (gpointer data);
|
||||
|
||||
static void
|
||||
clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
|
||||
|
||||
static void
|
||||
notify_key_device (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
guint32 key,
|
||||
guint32 state,
|
||||
gboolean update_keys)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
enum xkb_state_component changed_state;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
{
|
||||
clear_repeat_timer (seat);
|
||||
return;
|
||||
}
|
||||
|
||||
event = _clutter_key_event_new_from_evdev (input_device,
|
||||
seat->core_keyboard,
|
||||
stage,
|
||||
seat->xkb,
|
||||
seat->button_state,
|
||||
us2ms (time_us), key, state);
|
||||
_clutter_evdev_event_set_event_code (event, key);
|
||||
|
||||
/* We must be careful and not pass multiple releases to xkb, otherwise it gets
|
||||
confused and locks the modifiers */
|
||||
if (state != AUTOREPEAT_VALUE)
|
||||
{
|
||||
changed_state = xkb_state_update_key (seat->xkb,
|
||||
event->key.hardware_keycode,
|
||||
state ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
manager_evdev->priv->constrain_callback (core_pointer,
|
||||
us2ms (time_us),
|
||||
x, y,
|
||||
new_x, new_y,
|
||||
manager_evdev->priv->constrain_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
changed_state = 0;
|
||||
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
|
||||
}
|
||||
ClutterActor *stage = CLUTTER_ACTOR (manager_evdev->priv->stage);
|
||||
float stage_width = clutter_actor_get_width (stage);
|
||||
float stage_height = clutter_actor_get_height (stage);
|
||||
|
||||
queue_event (event);
|
||||
|
||||
if (update_keys && (changed_state & XKB_STATE_LEDS))
|
||||
clutter_seat_evdev_sync_leds (seat);
|
||||
|
||||
if (state == 0 || /* key release */
|
||||
!seat->repeat ||
|
||||
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb), event->key.hardware_keycode))
|
||||
{
|
||||
clear_repeat_timer (seat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == 1) /* key press */
|
||||
seat->repeat_count = 0;
|
||||
|
||||
seat->repeat_count += 1;
|
||||
seat->repeat_key = key;
|
||||
|
||||
switch (seat->repeat_count)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
guint32 interval;
|
||||
|
||||
clear_repeat_timer (seat);
|
||||
seat->repeat_device = g_object_ref (input_device);
|
||||
|
||||
if (seat->repeat_count == 1)
|
||||
interval = seat->repeat_delay;
|
||||
else
|
||||
interval = seat->repeat_interval;
|
||||
|
||||
seat->repeat_timer =
|
||||
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
|
||||
interval,
|
||||
keyboard_repeat,
|
||||
seat,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
x = CLAMP (x, 0.f, stage_width - 1);
|
||||
y = CLAMP (y, 0.f, stage_height - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keyboard_repeat (gpointer data)
|
||||
{
|
||||
ClutterSeatEvdev *seat = data;
|
||||
GSource *source;
|
||||
guint32 time_ms;
|
||||
|
||||
g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
|
||||
source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
|
||||
time_ms = g_source_get_time (source) / 1000;
|
||||
|
||||
notify_key_device (seat->repeat_device,
|
||||
ms2us (time_ms),
|
||||
seat->repeat_key,
|
||||
AUTOREPEAT_VALUE,
|
||||
FALSE);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static ClutterEvent *
|
||||
new_absolute_motion_event (ClutterInputDevice *input_device,
|
||||
@@ -511,45 +347,6 @@ notify_absolute_motion (ClutterInputDevice *input_device,
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_relative_motion (ClutterInputDevice *input_device,
|
||||
struct libinput_event_pointer *pointer_event)
|
||||
{
|
||||
guint64 time_us;
|
||||
double dx;
|
||||
double dy;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
gfloat new_x, new_y;
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterEvent *event;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
if (!_clutter_input_device_get_stage (input_device))
|
||||
return;
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
dx = libinput_event_pointer_get_dx (pointer_event);
|
||||
dy = libinput_event_pointer_get_dy (pointer_event);
|
||||
new_x = seat->pointer_x + dx;
|
||||
new_y = seat->pointer_y + dy;
|
||||
|
||||
time_us = libinput_event_pointer_get_time_usec (pointer_event);
|
||||
event = new_absolute_motion_event (input_device, time_us, new_x, new_y, NULL);
|
||||
|
||||
dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
|
||||
dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
|
||||
_clutter_evdev_event_set_relative_motion (event,
|
||||
dx, dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_relative_tool_motion (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
@@ -682,118 +479,6 @@ notify_scroll (ClutterInputDevice *input_device,
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_button (ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
guint32 button,
|
||||
guint32 state)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
gint button_nr;
|
||||
static gint maskmap[8] =
|
||||
{
|
||||
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
|
||||
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
|
||||
};
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
/* The evdev button numbers don't map sequentially to clutter button
|
||||
* numbers (the right and middle mouse buttons are in the opposite
|
||||
* order) so we'll map them directly with a switch statement */
|
||||
switch (button)
|
||||
{
|
||||
case BTN_LEFT:
|
||||
case BTN_TOUCH:
|
||||
button_nr = CLUTTER_BUTTON_PRIMARY;
|
||||
break;
|
||||
|
||||
case BTN_RIGHT:
|
||||
case BTN_STYLUS:
|
||||
button_nr = CLUTTER_BUTTON_SECONDARY;
|
||||
break;
|
||||
|
||||
case BTN_MIDDLE:
|
||||
case BTN_STYLUS2:
|
||||
button_nr = CLUTTER_BUTTON_MIDDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
button_nr = button - BTN_TOOL_PEN + 4;
|
||||
else
|
||||
button_nr = button - (BTN_LEFT - 1) + 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (button_nr < 1 || button_nr > 12)
|
||||
{
|
||||
g_warning ("Unhandled button event 0x%x", button);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state)
|
||||
event = clutter_event_new (CLUTTER_BUTTON_PRESS);
|
||||
else
|
||||
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
||||
|
||||
if (button_nr < G_N_ELEMENTS (maskmap))
|
||||
{
|
||||
/* Update the modifiers */
|
||||
if (state)
|
||||
seat->button_state |= maskmap[button_nr - 1];
|
||||
else
|
||||
seat->button_state &= ~maskmap[button_nr - 1];
|
||||
}
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->button.time = us2ms (time_us);
|
||||
event->button.stage = CLUTTER_STAGE (stage);
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
event->button.button = button_nr;
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterPoint point;
|
||||
|
||||
clutter_input_device_get_coords (input_device, NULL, &point);
|
||||
event->button.x = point.x;
|
||||
event->button.y = point.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->button.x = seat->pointer_x;
|
||||
event->button.y = seat->pointer_y;
|
||||
}
|
||||
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
_clutter_evdev_event_set_event_code (event, button);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
else
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_touch_event (ClutterInputDevice *input_device,
|
||||
ClutterEventType evtype,
|
||||
@@ -1205,128 +890,6 @@ clutter_event_source_free (ClutterEventSource *source)
|
||||
g_source_unref (g_source);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_touch_state_free (ClutterTouchState *touch_state)
|
||||
{
|
||||
g_slice_free (ClutterTouchState, touch_state);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
|
||||
struct libinput_seat *libinput_seat)
|
||||
{
|
||||
g_assert (seat->libinput_seat == NULL);
|
||||
|
||||
libinput_seat_ref (libinput_seat);
|
||||
libinput_seat_set_user_data (libinput_seat, seat);
|
||||
seat->libinput_seat = libinput_seat;
|
||||
}
|
||||
|
||||
static ClutterSeatEvdev *
|
||||
clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
|
||||
ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterInputDevice *device;
|
||||
struct xkb_context *ctx;
|
||||
struct xkb_rule_names names;
|
||||
struct xkb_keymap *keymap;
|
||||
|
||||
seat = g_new0 (ClutterSeatEvdev, 1);
|
||||
if (!seat)
|
||||
return NULL;
|
||||
|
||||
device = _clutter_input_device_evdev_new_virtual (
|
||||
manager, seat, CLUTTER_POINTER_DEVICE);
|
||||
_clutter_input_device_set_stage (device, priv->stage);
|
||||
seat->pointer_x = INITIAL_POINTER_X;
|
||||
seat->pointer_y = INITIAL_POINTER_Y;
|
||||
_clutter_input_device_set_coords (device, NULL,
|
||||
seat->pointer_x, seat->pointer_y,
|
||||
NULL);
|
||||
_clutter_device_manager_add_device (manager, device);
|
||||
seat->core_pointer = device;
|
||||
|
||||
device = _clutter_input_device_evdev_new_virtual (
|
||||
manager, seat, CLUTTER_KEYBOARD_DEVICE);
|
||||
_clutter_input_device_set_stage (device, priv->stage);
|
||||
_clutter_device_manager_add_device (manager, device);
|
||||
seat->core_keyboard = device;
|
||||
|
||||
seat->touches = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) clutter_touch_state_free);
|
||||
|
||||
ctx = xkb_context_new(0);
|
||||
g_assert (ctx);
|
||||
|
||||
names.rules = "evdev";
|
||||
names.model = "pc105";
|
||||
names.layout = option_xkb_layout;
|
||||
names.variant = option_xkb_variant;
|
||||
names.options = option_xkb_options;
|
||||
|
||||
keymap = xkb_keymap_new_from_names (ctx, &names, 0);
|
||||
xkb_context_unref(ctx);
|
||||
if (keymap)
|
||||
{
|
||||
seat->xkb = xkb_state_new (keymap);
|
||||
|
||||
seat->caps_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS);
|
||||
seat->num_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM);
|
||||
seat->scroll_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL);
|
||||
|
||||
priv->keymap = keymap;
|
||||
}
|
||||
|
||||
seat->repeat = TRUE;
|
||||
seat->repeat_delay = 250; /* ms */
|
||||
seat->repeat_interval = 33; /* ms */
|
||||
|
||||
priv->seats = g_slist_append (priv->seats, seat);
|
||||
return seat;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_evdev_free (ClutterSeatEvdev *seat)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
for (iter = seat->devices; iter; iter = g_slist_next (iter))
|
||||
{
|
||||
ClutterInputDevice *device = iter->data;
|
||||
|
||||
g_object_unref (device);
|
||||
}
|
||||
g_slist_free (seat->devices);
|
||||
g_hash_table_unref (seat->touches);
|
||||
|
||||
xkb_state_unref (seat->xkb);
|
||||
|
||||
clear_repeat_timer (seat);
|
||||
|
||||
if (seat->libinput_seat)
|
||||
libinput_seat_unref (seat->libinput_seat);
|
||||
|
||||
g_free (seat);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat, ClutterStage *stage)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = seat->devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
struct libinput_device *libinput_device)
|
||||
@@ -1346,11 +909,16 @@ evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
* which are located on the main seat. Make whatever seat comes first the
|
||||
* main seat. */
|
||||
if (priv->main_seat->libinput_seat == NULL)
|
||||
seat = priv->main_seat;
|
||||
{
|
||||
seat = priv->main_seat;
|
||||
}
|
||||
else
|
||||
seat = clutter_seat_evdev_new (manager_evdev);
|
||||
{
|
||||
seat = clutter_seat_evdev_new (manager_evdev);
|
||||
}
|
||||
|
||||
clutter_seat_evdev_set_libinput_seat (seat, libinput_seat);
|
||||
priv->seats = g_slist_append (priv->seats, seat);
|
||||
}
|
||||
|
||||
device = _clutter_input_device_evdev_new (manager, seat, libinput_device);
|
||||
@@ -1429,7 +997,7 @@ clutter_device_manager_evdev_remove_device (ClutterDeviceManager *manager,
|
||||
priv->devices = g_slist_remove (priv->devices, device);
|
||||
|
||||
if (seat->repeat_timer && seat->repeat_device == device)
|
||||
clear_repeat_timer (seat);
|
||||
clutter_seat_evdev_clear_repeat_timer (seat);
|
||||
|
||||
g_object_unref (device);
|
||||
}
|
||||
@@ -1494,32 +1062,6 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat)
|
||||
{
|
||||
GSList *iter;
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
int caps_lock, num_lock, scroll_lock;
|
||||
enum libinput_led leds = 0;
|
||||
|
||||
caps_lock = xkb_state_led_index_is_active (seat->xkb, seat->caps_lock_led);
|
||||
num_lock = xkb_state_led_index_is_active (seat->xkb, seat->num_lock_led);
|
||||
scroll_lock = xkb_state_led_index_is_active (seat->xkb, seat->scroll_lock_led);
|
||||
|
||||
if (caps_lock)
|
||||
leds |= LIBINPUT_LED_CAPS_LOCK;
|
||||
if (num_lock)
|
||||
leds |= LIBINPUT_LED_NUM_LOCK;
|
||||
if (scroll_lock)
|
||||
leds |= LIBINPUT_LED_SCROLL_LOCK;
|
||||
|
||||
for (iter = seat->devices; iter; iter = iter->next)
|
||||
{
|
||||
device_evdev = iter->data;
|
||||
_clutter_input_device_evdev_update_leds (device_evdev, leds);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
flush_event_queue (void)
|
||||
{
|
||||
@@ -1568,45 +1110,6 @@ process_base_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
return handled;
|
||||
}
|
||||
|
||||
static ClutterTouchState *
|
||||
_device_seat_add_touch (ClutterInputDevice *input_device,
|
||||
guint32 id)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
ClutterTouchState *touch;
|
||||
|
||||
touch = g_slice_new0 (ClutterTouchState);
|
||||
touch->id = id;
|
||||
|
||||
g_hash_table_insert (seat->touches, GUINT_TO_POINTER (id), touch);
|
||||
|
||||
return touch;
|
||||
}
|
||||
|
||||
static void
|
||||
_device_seat_remove_touch (ClutterInputDevice *input_device,
|
||||
guint32 id)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id));
|
||||
}
|
||||
|
||||
static ClutterTouchState *
|
||||
_device_seat_get_touch (ClutterInputDevice *input_device,
|
||||
guint32 id)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
ClutterSeatEvdev *seat = _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
|
||||
return g_hash_table_lookup (seat->touches, GUINT_TO_POINTER (id));
|
||||
}
|
||||
|
||||
static void
|
||||
check_notify_discrete_scroll (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
ClutterInputDevice *device,
|
||||
@@ -1773,6 +1276,14 @@ translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
|
||||
return (gdouble *) g_array_free (axes, FALSE);
|
||||
}
|
||||
|
||||
static ClutterSeatEvdev *
|
||||
seat_from_device (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
|
||||
|
||||
return _clutter_input_device_evdev_get_seat (device_evdev);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
struct libinput_event *event)
|
||||
@@ -1789,8 +1300,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
guint64 time_us;
|
||||
struct libinput_event_keyboard *key_event =
|
||||
libinput_event_get_keyboard_event (event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time_us = libinput_event_keyboard_get_time_usec (key_event);
|
||||
key = libinput_event_keyboard_get_key (key_event);
|
||||
key_state = libinput_event_keyboard_get_key_state (key_event) ==
|
||||
@@ -1805,18 +1316,35 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
seat_key_count != 0))
|
||||
break;
|
||||
|
||||
notify_key_device (device, time_us, key, key_state, TRUE);
|
||||
clutter_seat_evdev_notify_key (seat_from_device (device),
|
||||
device,
|
||||
time_us, key, key_state, TRUE);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LIBINPUT_EVENT_POINTER_MOTION:
|
||||
{
|
||||
struct libinput_event_pointer *motion_event =
|
||||
struct libinput_event_pointer *pointer_event =
|
||||
libinput_event_get_pointer_event (event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
uint64_t time_us;
|
||||
double dx;
|
||||
double dy;
|
||||
double dx_unaccel;
|
||||
double dy_unaccel;
|
||||
|
||||
notify_relative_motion (device, motion_event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time_us = libinput_event_pointer_get_time_usec (pointer_event);
|
||||
dx = libinput_event_pointer_get_dx (pointer_event);
|
||||
dy = libinput_event_pointer_get_dy (pointer_event);
|
||||
dx_unaccel = libinput_event_pointer_get_dx_unaccelerated (pointer_event);
|
||||
dy_unaccel = libinput_event_pointer_get_dy_unaccelerated (pointer_event);
|
||||
|
||||
clutter_seat_evdev_notify_relative_motion (seat_from_device (device),
|
||||
device,
|
||||
time_us,
|
||||
dx, dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1843,7 +1371,12 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
stage_width);
|
||||
y = libinput_event_pointer_get_absolute_y_transformed (motion_event,
|
||||
stage_height);
|
||||
notify_absolute_motion (device, time_us, x, y, NULL);
|
||||
|
||||
clutter_seat_evdev_notify_absolute_motion (seat_from_device (device),
|
||||
device,
|
||||
time_us,
|
||||
x, y,
|
||||
NULL);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1870,8 +1403,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
seat_button_count != 0))
|
||||
break;
|
||||
|
||||
notify_button (device, time_us, button, button_state);
|
||||
|
||||
clutter_seat_evdev_notify_button (seat_from_device (device), device,
|
||||
time_us, button, button_state);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1966,11 +1499,14 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
guint64 time_us;
|
||||
double x, y;
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterTouchState *touch_state;
|
||||
struct libinput_event_touch *touch_event =
|
||||
libinput_event_get_touch_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device));
|
||||
|
||||
stage = _clutter_input_device_get_stage (device);
|
||||
if (stage == NULL)
|
||||
@@ -1986,7 +1522,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
y = libinput_event_touch_get_y_transformed (touch_event,
|
||||
stage_height);
|
||||
|
||||
touch_state = _device_seat_add_touch (device, slot);
|
||||
touch_state = clutter_seat_evdev_add_touch (seat, slot);
|
||||
touch_state->coords.x = x;
|
||||
touch_state->coords.y = y;
|
||||
|
||||
@@ -1999,18 +1535,21 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
{
|
||||
gint32 slot;
|
||||
guint64 time_us;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterTouchState *touch_state;
|
||||
struct libinput_event_touch *touch_event =
|
||||
libinput_event_get_touch_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device));
|
||||
|
||||
slot = libinput_event_touch_get_slot (touch_event);
|
||||
time_us = libinput_event_touch_get_time_usec (touch_event);
|
||||
touch_state = _device_seat_get_touch (device, slot);
|
||||
touch_state = clutter_seat_evdev_get_touch (seat, slot);
|
||||
|
||||
notify_touch_event (device, CLUTTER_TOUCH_END, time_us, slot,
|
||||
touch_state->coords.x, touch_state->coords.y);
|
||||
_device_seat_remove_touch (device, slot);
|
||||
clutter_seat_evdev_remove_touch (seat, slot);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -2021,11 +1560,14 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
guint64 time_us;
|
||||
double x, y;
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterStage *stage;
|
||||
ClutterTouchState *touch_state;
|
||||
struct libinput_event_touch *touch_event =
|
||||
libinput_event_get_touch_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
seat = _clutter_input_device_evdev_get_seat (CLUTTER_INPUT_DEVICE_EVDEV (device));
|
||||
|
||||
stage = _clutter_input_device_get_stage (device);
|
||||
if (stage == NULL)
|
||||
@@ -2041,7 +1583,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
y = libinput_event_touch_get_y_transformed (touch_event,
|
||||
stage_height);
|
||||
|
||||
touch_state = _device_seat_get_touch (device, slot);
|
||||
touch_state = clutter_seat_evdev_get_touch (seat, slot);
|
||||
touch_state->coords.x = x;
|
||||
touch_state->coords.y = y;
|
||||
|
||||
@@ -2215,34 +1757,38 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
{
|
||||
guint64 time;
|
||||
guint64 time_us;
|
||||
guint32 button_state;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
guint tablet_button;
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
tablet_button = libinput_event_tablet_tool_get_button (tablet_event);
|
||||
|
||||
button_state = libinput_event_tablet_tool_get_button_state (tablet_event) ==
|
||||
LIBINPUT_BUTTON_STATE_PRESSED;
|
||||
notify_button (device, time, tablet_button, button_state);
|
||||
|
||||
clutter_seat_evdev_notify_button (seat_from_device (device), device,
|
||||
time_us, tablet_button, button_state);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_TIP:
|
||||
{
|
||||
guint64 time;
|
||||
guint64 time_us;
|
||||
guint32 button_state;
|
||||
struct libinput_event_tablet_tool *tablet_event =
|
||||
libinput_event_get_tablet_tool_event (event);
|
||||
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
time_us = libinput_event_tablet_tool_get_time_usec (tablet_event);
|
||||
|
||||
button_state = libinput_event_tablet_tool_get_tip_state (tablet_event) ==
|
||||
LIBINPUT_TABLET_TOOL_TIP_DOWN;
|
||||
notify_button (device, time, BTN_TOUCH, button_state);
|
||||
|
||||
clutter_seat_evdev_notify_button (seat_from_device (device), device,
|
||||
time_us, BTN_TOUCH, button_state);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_PAD_BUTTON:
|
||||
@@ -2413,6 +1959,21 @@ static const struct libinput_interface libinput_interface = {
|
||||
close_restricted
|
||||
};
|
||||
|
||||
static ClutterVirtualInputDevice *
|
||||
clutter_device_manager_evdev_create_virtual_device (ClutterDeviceManager *manager,
|
||||
ClutterInputDeviceType device_type)
|
||||
{
|
||||
ClutterDeviceManagerEvdev *manager_evdev =
|
||||
CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
||||
ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_EVDEV,
|
||||
"device-manager", manager,
|
||||
"seat", priv->main_seat,
|
||||
"device-type", device_type,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* GObject implementation
|
||||
*/
|
||||
@@ -2424,6 +1985,8 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
|
||||
ClutterDeviceManagerEvdevPrivate *priv;
|
||||
ClutterEventSource *source;
|
||||
struct udev *udev;
|
||||
struct xkb_context *ctx;
|
||||
struct xkb_rule_names names;
|
||||
|
||||
udev = udev_new ();
|
||||
if (G_UNLIKELY (udev == NULL))
|
||||
@@ -2454,6 +2017,17 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
|
||||
|
||||
udev_unref (udev);
|
||||
|
||||
names.rules = "evdev";
|
||||
names.model = "pc105";
|
||||
names.layout = option_xkb_layout;
|
||||
names.variant = option_xkb_variant;
|
||||
names.options = option_xkb_options;
|
||||
|
||||
ctx = xkb_context_new (0);
|
||||
g_assert (ctx);
|
||||
priv->keymap = xkb_keymap_new_from_names (ctx, &names, 0);
|
||||
xkb_context_unref (ctx);
|
||||
|
||||
priv->main_seat = clutter_seat_evdev_new (manager_evdev);
|
||||
|
||||
dispatch_libinput (manager_evdev);
|
||||
@@ -2539,6 +2113,7 @@ clutter_device_manager_evdev_class_init (ClutterDeviceManagerEvdevClass *klass)
|
||||
manager_class->get_devices = clutter_device_manager_evdev_get_devices;
|
||||
manager_class->get_core_device = clutter_device_manager_evdev_get_core_device;
|
||||
manager_class->get_device = clutter_device_manager_evdev_get_device;
|
||||
manager_class->create_virtual_device = clutter_device_manager_evdev_create_virtual_device;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2684,6 +2259,22 @@ _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *mana
|
||||
compare_ids);
|
||||
}
|
||||
|
||||
struct xkb_keymap *
|
||||
_clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
|
||||
|
||||
return priv->keymap;
|
||||
}
|
||||
|
||||
ClutterStage *
|
||||
_clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
ClutterDeviceManagerEvdevPrivate *priv = manager_evdev->priv;
|
||||
|
||||
return priv->stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_evdev_release_devices:
|
||||
*
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#ifndef __CLUTTER_DEVICE_MANAGER_EVDEV_H__
|
||||
#define __CLUTTER_DEVICE_MANAGER_EVDEV_H__
|
||||
|
||||
#include <clutter/clutter-backend.h>
|
||||
#include <clutter/clutter-device-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -39,6 +40,8 @@ typedef struct _ClutterDeviceManagerEvdev ClutterDeviceManagerEvdev;
|
||||
typedef struct _ClutterDeviceManagerEvdevClass ClutterDeviceManagerEvdevClass;
|
||||
typedef struct _ClutterDeviceManagerEvdevPrivate ClutterDeviceManagerEvdevPrivate;
|
||||
|
||||
typedef struct _ClutterSeatEvdev ClutterSeatEvdev;
|
||||
|
||||
struct _ClutterDeviceManagerEvdev
|
||||
{
|
||||
ClutterDeviceManager parent_instance;
|
||||
@@ -61,6 +64,36 @@ gint _clutter_device_manager_evdev_acquire_device_id (ClutterDeviceManagerEvdev
|
||||
void _clutter_device_manager_evdev_release_device_id (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
struct xkb_keymap * _clutter_device_manager_evdev_get_keymap (ClutterDeviceManagerEvdev *manager_evdev);
|
||||
|
||||
ClutterStage * _clutter_device_manager_evdev_get_stage (ClutterDeviceManagerEvdev *manager_evdev);
|
||||
|
||||
void _clutter_device_manager_evdev_constrain_pointer (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
ClutterInputDevice *core_pointer,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
float *new_x,
|
||||
float *new_y);
|
||||
|
||||
static inline guint64
|
||||
us (guint64 us)
|
||||
{
|
||||
return us;
|
||||
}
|
||||
|
||||
static inline guint64
|
||||
ms2us (guint64 ms)
|
||||
{
|
||||
return us (ms * 1000);
|
||||
}
|
||||
|
||||
static inline guint32
|
||||
us2ms (guint64 us)
|
||||
{
|
||||
return (guint32) (us / 1000);
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_DEVICE_MANAGER_EVDEV_H__ */
|
||||
|
||||
@@ -196,7 +196,8 @@ _clutter_input_device_evdev_new (ClutterDeviceManager *manager,
|
||||
ClutterInputDevice *
|
||||
_clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager,
|
||||
ClutterSeatEvdev *seat,
|
||||
ClutterInputDeviceType type)
|
||||
ClutterInputDeviceType type,
|
||||
ClutterInputMode mode)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device;
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
@@ -223,7 +224,7 @@ _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager,
|
||||
"name", name,
|
||||
"device-manager", manager,
|
||||
"device-type", type,
|
||||
"device-mode", CLUTTER_INPUT_MODE_MASTER,
|
||||
"device-mode", mode,
|
||||
"enabled", TRUE,
|
||||
NULL);
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
#include <glib-object.h>
|
||||
#include <libinput.h>
|
||||
|
||||
#include <clutter/clutter-input-device.h>
|
||||
#include "clutter/clutter-device-manager-private.h"
|
||||
#include "evdev/clutter-seat-evdev.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -56,7 +57,6 @@ G_BEGIN_DECLS
|
||||
CLUTTER_TYPE_INPUT_DEVICE_EVDEV, ClutterInputDeviceEvdevClass))
|
||||
|
||||
typedef struct _ClutterInputDeviceEvdev ClutterInputDeviceEvdev;
|
||||
typedef struct _ClutterSeatEvdev ClutterSeatEvdev;
|
||||
typedef struct _ClutterEventEvdev ClutterEventEvdev;
|
||||
|
||||
struct _ClutterInputDeviceEvdev
|
||||
@@ -76,7 +76,8 @@ ClutterInputDevice * _clutter_input_device_evdev_new (ClutterDe
|
||||
|
||||
ClutterInputDevice * _clutter_input_device_evdev_new_virtual (ClutterDeviceManager *manager,
|
||||
ClutterSeatEvdev *seat,
|
||||
ClutterInputDeviceType type);
|
||||
ClutterInputDeviceType type,
|
||||
ClutterInputMode mode);
|
||||
|
||||
ClutterSeatEvdev * _clutter_input_device_evdev_get_seat (ClutterInputDeviceEvdev *device);
|
||||
|
||||
|
||||
590
clutter/clutter/evdev/clutter-seat-evdev.c
Normal file
590
clutter/clutter/evdev/clutter-seat-evdev.c
Normal file
@@ -0,0 +1,590 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corp.
|
||||
* Copyright (C) 2014 Jonas Ådahl
|
||||
* 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: Damien Lespiau <damien.lespiau@intel.com>
|
||||
* Author: Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "clutter-build-config.h"
|
||||
|
||||
#include "clutter-seat-evdev.h"
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-input-device-evdev.h"
|
||||
#include "clutter-main.h"
|
||||
|
||||
/* Try to keep the pointer inside the stage. Hopefully no one is using
|
||||
* this backend with stages smaller than this. */
|
||||
#define INITIAL_POINTER_X 16
|
||||
#define INITIAL_POINTER_Y 16
|
||||
|
||||
#define AUTOREPEAT_VALUE 2
|
||||
|
||||
void
|
||||
clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
|
||||
struct libinput_seat *libinput_seat)
|
||||
{
|
||||
g_assert (seat->libinput_seat == NULL);
|
||||
|
||||
libinput_seat_ref (libinput_seat);
|
||||
libinput_seat_set_user_data (libinput_seat, seat);
|
||||
seat->libinput_seat = libinput_seat;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat)
|
||||
{
|
||||
GSList *iter;
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
int caps_lock, num_lock, scroll_lock;
|
||||
enum libinput_led leds = 0;
|
||||
|
||||
caps_lock = xkb_state_led_index_is_active (seat->xkb, seat->caps_lock_led);
|
||||
num_lock = xkb_state_led_index_is_active (seat->xkb, seat->num_lock_led);
|
||||
scroll_lock = xkb_state_led_index_is_active (seat->xkb, seat->scroll_lock_led);
|
||||
|
||||
if (caps_lock)
|
||||
leds |= LIBINPUT_LED_CAPS_LOCK;
|
||||
if (num_lock)
|
||||
leds |= LIBINPUT_LED_NUM_LOCK;
|
||||
if (scroll_lock)
|
||||
leds |= LIBINPUT_LED_SCROLL_LOCK;
|
||||
|
||||
for (iter = seat->devices; iter; iter = iter->next)
|
||||
{
|
||||
device_evdev = iter->data;
|
||||
_clutter_input_device_evdev_update_leds (device_evdev, leds);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_touch_state_free (ClutterTouchState *touch_state)
|
||||
{
|
||||
g_slice_free (ClutterTouchState, touch_state);
|
||||
}
|
||||
|
||||
ClutterTouchState *
|
||||
clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id)
|
||||
{
|
||||
ClutterTouchState *touch;
|
||||
|
||||
touch = g_slice_new0 (ClutterTouchState);
|
||||
touch->id = id;
|
||||
|
||||
g_hash_table_insert (seat->touches, GUINT_TO_POINTER (id), touch);
|
||||
|
||||
return touch;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id)
|
||||
{
|
||||
g_hash_table_remove (seat->touches, GUINT_TO_POINTER (id));
|
||||
}
|
||||
|
||||
ClutterTouchState *
|
||||
clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id)
|
||||
{
|
||||
return g_hash_table_lookup (seat->touches, GUINT_TO_POINTER (id));
|
||||
}
|
||||
|
||||
ClutterSeatEvdev *
|
||||
clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev)
|
||||
{
|
||||
ClutterDeviceManager *manager = CLUTTER_DEVICE_MANAGER (manager_evdev);
|
||||
ClutterSeatEvdev *seat;
|
||||
ClutterInputDevice *device;
|
||||
ClutterStage *stage;
|
||||
struct xkb_keymap *keymap;
|
||||
|
||||
seat = g_new0 (ClutterSeatEvdev, 1);
|
||||
if (!seat)
|
||||
return NULL;
|
||||
|
||||
seat->manager_evdev = manager_evdev;
|
||||
device = _clutter_input_device_evdev_new_virtual (
|
||||
manager, seat, CLUTTER_POINTER_DEVICE,
|
||||
CLUTTER_INPUT_MODE_MASTER);
|
||||
stage = _clutter_device_manager_evdev_get_stage (manager_evdev);
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
seat->pointer_x = INITIAL_POINTER_X;
|
||||
seat->pointer_y = INITIAL_POINTER_Y;
|
||||
_clutter_input_device_set_coords (device, NULL,
|
||||
seat->pointer_x, seat->pointer_y,
|
||||
NULL);
|
||||
_clutter_device_manager_add_device (manager, device);
|
||||
seat->core_pointer = device;
|
||||
|
||||
device = _clutter_input_device_evdev_new_virtual (
|
||||
manager, seat, CLUTTER_KEYBOARD_DEVICE,
|
||||
CLUTTER_INPUT_MODE_MASTER);
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
_clutter_device_manager_add_device (manager, device);
|
||||
seat->core_keyboard = device;
|
||||
|
||||
seat->touches = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) clutter_touch_state_free);
|
||||
|
||||
seat->repeat = TRUE;
|
||||
seat->repeat_delay = 250; /* ms */
|
||||
seat->repeat_interval = 33; /* ms */
|
||||
|
||||
keymap = _clutter_device_manager_evdev_get_keymap (manager_evdev);
|
||||
if (keymap)
|
||||
{
|
||||
seat->xkb = xkb_state_new (keymap);
|
||||
|
||||
seat->caps_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_CAPS);
|
||||
seat->num_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_NUM);
|
||||
seat->scroll_lock_led =
|
||||
xkb_keymap_led_get_index (keymap, XKB_LED_NAME_SCROLL);
|
||||
}
|
||||
|
||||
return seat;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat)
|
||||
{
|
||||
if (seat->repeat_timer)
|
||||
{
|
||||
g_source_remove (seat->repeat_timer);
|
||||
seat->repeat_timer = 0;
|
||||
g_clear_object (&seat->repeat_device);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
keyboard_repeat (gpointer data)
|
||||
{
|
||||
ClutterSeatEvdev *seat = data;
|
||||
GSource *source;
|
||||
guint32 time_ms;
|
||||
|
||||
g_return_val_if_fail (seat->repeat_device != NULL, G_SOURCE_REMOVE);
|
||||
source = g_main_context_find_source_by_id (NULL, seat->repeat_timer);
|
||||
time_ms = g_source_get_time (source) / 1000;
|
||||
|
||||
clutter_seat_evdev_notify_key (seat,
|
||||
seat->repeat_device,
|
||||
ms2us (time_ms),
|
||||
seat->repeat_key,
|
||||
AUTOREPEAT_VALUE,
|
||||
FALSE);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_event (ClutterEvent *event)
|
||||
{
|
||||
_clutter_event_push (event, FALSE);
|
||||
}
|
||||
|
||||
static int
|
||||
update_button_count (ClutterSeatEvdev *seat,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
return ++seat->button_count[button];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle cases where we newer saw the initial pressed event. */
|
||||
if (seat->button_count[button] == 0)
|
||||
return 0;
|
||||
|
||||
return --seat->button_count[button];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
uint32_t state,
|
||||
gboolean update_keys)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
enum xkb_state_component changed_state;
|
||||
|
||||
if (state != AUTOREPEAT_VALUE)
|
||||
{
|
||||
/* Drop any repeated button press (for example from virtual devices. */
|
||||
int count = update_button_count (seat, key, state);
|
||||
if (state && count > 1)
|
||||
return;
|
||||
if (!state && count != 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (device);
|
||||
if (stage == NULL)
|
||||
{
|
||||
clutter_seat_evdev_clear_repeat_timer (seat);
|
||||
return;
|
||||
}
|
||||
|
||||
event = _clutter_key_event_new_from_evdev (device,
|
||||
seat->core_keyboard,
|
||||
stage,
|
||||
seat->xkb,
|
||||
seat->button_state,
|
||||
us2ms (time_us), key, state);
|
||||
_clutter_evdev_event_set_event_code (event, key);
|
||||
|
||||
/* We must be careful and not pass multiple releases to xkb, otherwise it gets
|
||||
confused and locks the modifiers */
|
||||
if (state != AUTOREPEAT_VALUE)
|
||||
{
|
||||
changed_state = xkb_state_update_key (seat->xkb,
|
||||
event->key.hardware_keycode,
|
||||
state ? XKB_KEY_DOWN : XKB_KEY_UP);
|
||||
}
|
||||
else
|
||||
{
|
||||
changed_state = 0;
|
||||
clutter_event_set_flags (event, CLUTTER_EVENT_FLAG_SYNTHETIC);
|
||||
}
|
||||
|
||||
queue_event (event);
|
||||
|
||||
if (update_keys && (changed_state & XKB_STATE_LEDS))
|
||||
clutter_seat_evdev_sync_leds (seat);
|
||||
|
||||
if (state == 0 || /* key release */
|
||||
!seat->repeat ||
|
||||
!xkb_keymap_key_repeats (xkb_state_get_keymap (seat->xkb),
|
||||
event->key.hardware_keycode))
|
||||
{
|
||||
clutter_seat_evdev_clear_repeat_timer (seat);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == 1) /* key press */
|
||||
seat->repeat_count = 0;
|
||||
|
||||
seat->repeat_count += 1;
|
||||
seat->repeat_key = key;
|
||||
|
||||
switch (seat->repeat_count)
|
||||
{
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
guint32 interval;
|
||||
|
||||
clutter_seat_evdev_clear_repeat_timer (seat);
|
||||
seat->repeat_device = g_object_ref (device);
|
||||
|
||||
if (seat->repeat_count == 1)
|
||||
interval = seat->repeat_delay;
|
||||
else
|
||||
interval = seat->repeat_interval;
|
||||
|
||||
seat->repeat_timer =
|
||||
clutter_threads_add_timeout_full (CLUTTER_PRIORITY_EVENTS,
|
||||
interval,
|
||||
keyboard_repeat,
|
||||
seat,
|
||||
NULL);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterEvent *
|
||||
new_absolute_motion_event (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
guint64 time_us,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gdouble *axes)
|
||||
{
|
||||
ClutterStage *stage = _clutter_input_device_get_stage (input_device);
|
||||
ClutterEvent *event;
|
||||
|
||||
event = clutter_event_new (CLUTTER_MOTION);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
||||
_clutter_device_manager_evdev_constrain_pointer (seat->manager_evdev,
|
||||
seat->core_pointer,
|
||||
time_us,
|
||||
seat->pointer_x,
|
||||
seat->pointer_y,
|
||||
&x, &y);
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->motion.time = us2ms (time_us);
|
||||
event->motion.stage = stage;
|
||||
event->motion.device = seat->core_pointer;
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
event->motion.x = x;
|
||||
event->motion.y = y;
|
||||
event->motion.axes = axes;
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
}
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) != CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
seat->pointer_x = x;
|
||||
seat->pointer_y = y;
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float dx,
|
||||
float dy,
|
||||
float dx_unaccel,
|
||||
float dy_unaccel)
|
||||
{
|
||||
gfloat new_x, new_y;
|
||||
ClutterEvent *event;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
if (!_clutter_input_device_get_stage (input_device))
|
||||
return;
|
||||
|
||||
new_x = seat->pointer_x + dx;
|
||||
new_y = seat->pointer_y + dy;
|
||||
event = new_absolute_motion_event (seat, input_device,
|
||||
time_us, new_x, new_y, NULL);
|
||||
|
||||
_clutter_evdev_event_set_relative_motion (event,
|
||||
dx, dy,
|
||||
dx_unaccel, dy_unaccel);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
double *axes)
|
||||
{
|
||||
ClutterEvent *event;
|
||||
|
||||
event = new_absolute_motion_event (seat, input_device, time_us, x, x, axes);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
gint button_nr;
|
||||
static gint maskmap[8] =
|
||||
{
|
||||
CLUTTER_BUTTON1_MASK, CLUTTER_BUTTON3_MASK, CLUTTER_BUTTON2_MASK,
|
||||
CLUTTER_BUTTON4_MASK, CLUTTER_BUTTON5_MASK, 0, 0, 0
|
||||
};
|
||||
int button_count;
|
||||
|
||||
/* Drop any repeated button press (for example from virtual devices. */
|
||||
button_count = update_button_count (seat, button, state);
|
||||
if (state && button_count > 1)
|
||||
return;
|
||||
if (!state && button_count != 0)
|
||||
return;
|
||||
|
||||
/* We can drop the event on the floor if no stage has been
|
||||
* associated with the device yet. */
|
||||
stage = _clutter_input_device_get_stage (input_device);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
/* The evdev button numbers don't map sequentially to clutter button
|
||||
* numbers (the right and middle mouse buttons are in the opposite
|
||||
* order) so we'll map them directly with a switch statement */
|
||||
switch (button)
|
||||
{
|
||||
case BTN_LEFT:
|
||||
case BTN_TOUCH:
|
||||
button_nr = CLUTTER_BUTTON_PRIMARY;
|
||||
break;
|
||||
|
||||
case BTN_RIGHT:
|
||||
case BTN_STYLUS:
|
||||
button_nr = CLUTTER_BUTTON_SECONDARY;
|
||||
break;
|
||||
|
||||
case BTN_MIDDLE:
|
||||
case BTN_STYLUS2:
|
||||
button_nr = CLUTTER_BUTTON_MIDDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
button_nr = button - BTN_TOOL_PEN + 4;
|
||||
else
|
||||
button_nr = button - (BTN_LEFT - 1) + 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (button_nr < 1 || button_nr > 12)
|
||||
{
|
||||
g_warning ("Unhandled button event 0x%x", button);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state)
|
||||
event = clutter_event_new (CLUTTER_BUTTON_PRESS);
|
||||
else
|
||||
event = clutter_event_new (CLUTTER_BUTTON_RELEASE);
|
||||
|
||||
if (button_nr < G_N_ELEMENTS (maskmap))
|
||||
{
|
||||
/* Update the modifiers */
|
||||
if (state)
|
||||
seat->button_state |= maskmap[button_nr - 1];
|
||||
else
|
||||
seat->button_state &= ~maskmap[button_nr - 1];
|
||||
}
|
||||
|
||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||
event->button.time = us2ms (time_us);
|
||||
event->button.stage = CLUTTER_STAGE (stage);
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
event->button.button = button_nr;
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterPoint point;
|
||||
|
||||
clutter_input_device_get_coords (input_device, NULL, &point);
|
||||
event->button.x = point.x;
|
||||
event->button.y = point.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->button.x = seat->pointer_x;
|
||||
event->button.y = seat->pointer_y;
|
||||
}
|
||||
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
_clutter_evdev_event_set_event_code (event, button);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
}
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
|
||||
queue_event (event);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_free (ClutterSeatEvdev *seat)
|
||||
{
|
||||
GSList *iter;
|
||||
|
||||
for (iter = seat->devices; iter; iter = g_slist_next (iter))
|
||||
{
|
||||
ClutterInputDevice *device = iter->data;
|
||||
|
||||
g_object_unref (device);
|
||||
}
|
||||
g_slist_free (seat->devices);
|
||||
g_hash_table_unref (seat->touches);
|
||||
|
||||
xkb_state_unref (seat->xkb);
|
||||
|
||||
clutter_seat_evdev_clear_repeat_timer (seat);
|
||||
|
||||
if (seat->libinput_seat)
|
||||
libinput_seat_unref (seat->libinput_seat);
|
||||
|
||||
g_free (seat);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
_clutter_input_device_set_stage (seat->core_pointer, stage);
|
||||
_clutter_input_device_set_stage (seat->core_keyboard, stage);
|
||||
|
||||
for (l = seat->devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
}
|
||||
132
clutter/clutter/evdev/clutter-seat-evdev.h
Normal file
132
clutter/clutter/evdev/clutter-seat-evdev.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2010 Intel Corp.
|
||||
* Copyright (C) 2014 Jonas Ådahl
|
||||
* 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: Damien Lespiau <damien.lespiau@intel.com>
|
||||
* Author: Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_SEAT_EVDEV_H__
|
||||
#define __CLUTTER_SEAT_EVDEV_H__
|
||||
|
||||
#include <libinput.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "clutter-input-device.h"
|
||||
#include "clutter-device-manager-evdev.h"
|
||||
#include "clutter-xkb-utils.h"
|
||||
|
||||
typedef struct _ClutterTouchState ClutterTouchState;
|
||||
|
||||
struct _ClutterTouchState
|
||||
{
|
||||
guint32 id;
|
||||
ClutterPoint coords;
|
||||
};
|
||||
|
||||
struct _ClutterSeatEvdev
|
||||
{
|
||||
struct libinput_seat *libinput_seat;
|
||||
ClutterDeviceManagerEvdev *manager_evdev;
|
||||
|
||||
GSList *devices;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
|
||||
GHashTable *touches;
|
||||
|
||||
struct xkb_state *xkb;
|
||||
xkb_led_index_t caps_lock_led;
|
||||
xkb_led_index_t num_lock_led;
|
||||
xkb_led_index_t scroll_lock_led;
|
||||
uint32_t button_state;
|
||||
int button_count[KEY_CNT];
|
||||
|
||||
/* keyboard repeat */
|
||||
gboolean repeat;
|
||||
guint32 repeat_delay;
|
||||
guint32 repeat_interval;
|
||||
guint32 repeat_key;
|
||||
guint32 repeat_count;
|
||||
guint32 repeat_timer;
|
||||
ClutterInputDevice *repeat_device;
|
||||
|
||||
gfloat pointer_x;
|
||||
gfloat pointer_y;
|
||||
|
||||
/* Emulation of discrete scroll events out of smooth ones */
|
||||
gfloat accum_scroll_dx;
|
||||
gfloat accum_scroll_dy;
|
||||
};
|
||||
|
||||
void clutter_seat_evdev_notify_key (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
uint32_t state,
|
||||
gboolean update_keys);
|
||||
|
||||
void clutter_seat_evdev_notify_relative_motion (ClutterSeatEvdev *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float dx,
|
||||
float dy,
|
||||
float dx_unaccel,
|
||||
float dy_unaccel);
|
||||
|
||||
void clutter_seat_evdev_notify_absolute_motion (ClutterSeatEvdev *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
double *axes);
|
||||
|
||||
void clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
uint32_t state);
|
||||
|
||||
void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
|
||||
struct libinput_seat *libinput_seat);
|
||||
|
||||
void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
|
||||
|
||||
ClutterTouchState * clutter_seat_evdev_add_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id);
|
||||
|
||||
void clutter_seat_evdev_remove_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id);
|
||||
|
||||
ClutterTouchState * clutter_seat_evdev_get_touch (ClutterSeatEvdev *seat,
|
||||
guint32 id);
|
||||
|
||||
void clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat,
|
||||
ClutterStage *stage);
|
||||
|
||||
void clutter_seat_evdev_clear_repeat_timer (ClutterSeatEvdev *seat);
|
||||
|
||||
ClutterSeatEvdev * clutter_seat_evdev_new (ClutterDeviceManagerEvdev *manager_evdev);
|
||||
|
||||
void clutter_seat_evdev_free (ClutterSeatEvdev *seat);
|
||||
|
||||
#endif /* __CLUTTER_SEAT_EVDEV_H__ */
|
||||
497
clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
Normal file
497
clutter/clutter/evdev/clutter-virtual-input-device-evdev.c
Normal file
@@ -0,0 +1,497 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clutter-build-config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "evdev/clutter-input-device-evdev.h"
|
||||
#include "evdev/clutter-seat-evdev.h"
|
||||
#include "evdev/clutter-virtual-input-device-evdev.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_SEAT,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *obj_props[PROP_LAST];
|
||||
|
||||
struct _ClutterVirtualInputDeviceEvdev
|
||||
{
|
||||
ClutterVirtualInputDevice parent;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
ClutterSeatEvdev *seat;
|
||||
int button_count[KEY_CNT];
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterVirtualInputDeviceEvdev,
|
||||
clutter_virtual_input_device_evdev,
|
||||
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
|
||||
|
||||
typedef enum _EvdevButtonType
|
||||
{
|
||||
EVDEV_BUTTON_TYPE_NONE,
|
||||
EVDEV_BUTTON_TYPE_KEY,
|
||||
EVDEV_BUTTON_TYPE_BUTTON,
|
||||
} EvdevButtonType;
|
||||
|
||||
static int
|
||||
update_button_count (ClutterVirtualInputDeviceEvdev *virtual_evdev,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
return ++virtual_evdev->button_count[button];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Handle cases where we newer saw the initial pressed event. */
|
||||
if (virtual_evdev->button_count[button] == 0)
|
||||
return 0;
|
||||
|
||||
return --virtual_evdev->button_count[button];
|
||||
}
|
||||
}
|
||||
|
||||
static EvdevButtonType
|
||||
get_button_type (uint16_t code)
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case BTN_TOOL_PEN:
|
||||
case BTN_TOOL_RUBBER:
|
||||
case BTN_TOOL_BRUSH:
|
||||
case BTN_TOOL_PENCIL:
|
||||
case BTN_TOOL_AIRBRUSH:
|
||||
case BTN_TOOL_MOUSE:
|
||||
case BTN_TOOL_LENS:
|
||||
case BTN_TOOL_QUINTTAP:
|
||||
case BTN_TOOL_DOUBLETAP:
|
||||
case BTN_TOOL_TRIPLETAP:
|
||||
case BTN_TOOL_QUADTAP:
|
||||
case BTN_TOOL_FINGER:
|
||||
case BTN_TOUCH:
|
||||
return EVDEV_BUTTON_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (code >= KEY_ESC && code <= KEY_MICMUTE)
|
||||
return EVDEV_BUTTON_TYPE_KEY;
|
||||
if (code >= BTN_MISC && code <= BTN_GEAR_UP)
|
||||
return EVDEV_BUTTON_TYPE_BUTTON;
|
||||
if (code >= KEY_OK && code <= KEY_LIGHTS_TOGGLE)
|
||||
return EVDEV_BUTTON_TYPE_KEY;
|
||||
if (code >= BTN_DPAD_UP && code <= BTN_DPAD_RIGHT)
|
||||
return EVDEV_BUTTON_TYPE_BUTTON;
|
||||
if (code >= KEY_ALS_TOGGLE && code <= KEY_KBDINPUTASSIST_CANCEL)
|
||||
return EVDEV_BUTTON_TYPE_KEY;
|
||||
if (code >= BTN_TRIGGER_HAPPY && code <= BTN_TRIGGER_HAPPY40)
|
||||
return EVDEV_BUTTON_TYPE_BUTTON;
|
||||
return EVDEV_BUTTON_TYPE_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
int code;
|
||||
uint64_t time_us;
|
||||
|
||||
time_us = g_get_monotonic_time ();
|
||||
|
||||
for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++)
|
||||
{
|
||||
switch (get_button_type (code))
|
||||
{
|
||||
case EVDEV_BUTTON_TYPE_KEY:
|
||||
clutter_virtual_input_device_notify_key (virtual_device,
|
||||
time_us,
|
||||
code,
|
||||
CLUTTER_KEY_STATE_RELEASED);
|
||||
break;
|
||||
case EVDEV_BUTTON_TYPE_BUTTON:
|
||||
clutter_virtual_input_device_notify_button (virtual_device,
|
||||
time_us,
|
||||
code,
|
||||
CLUTTER_BUTTON_STATE_RELEASED);
|
||||
break;
|
||||
case EVDEV_BUTTON_TYPE_NONE:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
|
||||
clutter_seat_evdev_notify_relative_motion (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
dx, dy,
|
||||
dx, dy);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
|
||||
clutter_seat_evdev_notify_absolute_motion (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
x, y,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
int button_count;
|
||||
|
||||
if (get_button_type (button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
||||
button);
|
||||
return;
|
||||
}
|
||||
|
||||
button_count = update_button_count (virtual_evdev, button, button_state);
|
||||
if (button_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x button presses (ignoring)",
|
||||
button);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_seat_evdev_notify_button (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
button,
|
||||
button_state);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_key (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
int key_count;
|
||||
|
||||
if (get_button_type (key) != EVDEV_BUTTON_TYPE_KEY)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", key);
|
||||
return;
|
||||
}
|
||||
|
||||
key_count = update_button_count (virtual_evdev, key, key_state);
|
||||
if (key_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x key presses (ignoring)",
|
||||
key);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_seat_evdev_notify_key (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
key,
|
||||
key_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_device,
|
||||
guint keyval,
|
||||
guint *keycode_out,
|
||||
guint *level_out)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
ClutterDeviceManager *manager;
|
||||
struct xkb_keymap *xkb_keymap;
|
||||
struct xkb_state *state;
|
||||
guint keycode, layout;
|
||||
xkb_keycode_t min_keycode, max_keycode;
|
||||
|
||||
manager = clutter_virtual_input_device_get_manager (virtual_device);
|
||||
xkb_keymap = _clutter_device_manager_evdev_get_keymap (CLUTTER_DEVICE_MANAGER_EVDEV (manager));
|
||||
state = virtual_evdev->seat->xkb;
|
||||
|
||||
layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
|
||||
max_keycode = xkb_keymap_max_keycode (xkb_keymap);
|
||||
for (keycode = min_keycode; keycode < max_keycode; keycode++)
|
||||
{
|
||||
gint num_levels, level;
|
||||
num_levels = xkb_keymap_num_levels_for_key (xkb_keymap, keycode, layout);
|
||||
for (level = 0; level < num_levels; level++)
|
||||
{
|
||||
const xkb_keysym_t *syms;
|
||||
gint num_syms, sym;
|
||||
num_syms = xkb_keymap_key_get_syms_by_level (xkb_keymap, keycode, layout, level, &syms);
|
||||
for (sym = 0; sym < num_syms; sym++)
|
||||
{
|
||||
if (syms[sym] == keyval)
|
||||
{
|
||||
*keycode_out = keycode;
|
||||
if (level_out)
|
||||
*level_out = level;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t level,
|
||||
uint32_t key_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
guint keysym, keycode, evcode;
|
||||
|
||||
if (level == 0)
|
||||
return;
|
||||
|
||||
if (level == 1)
|
||||
{
|
||||
keysym = XKB_KEY_Shift_L;
|
||||
}
|
||||
else if (level == 2)
|
||||
{
|
||||
keysym = XKB_KEY_ISO_Level3_Shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Unhandled level: %d\n", level);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pick_keycode_for_keyval_in_current_group (virtual_device, keysym,
|
||||
&keycode, NULL))
|
||||
return;
|
||||
|
||||
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
|
||||
keycode, &evcode);
|
||||
clutter_seat_evdev_notify_key (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
evcode,
|
||||
key_state,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
int key_count;
|
||||
guint keycode = 0, level = 0, evcode = 0;
|
||||
|
||||
if (!pick_keycode_for_keyval_in_current_group (virtual_device,
|
||||
keyval, &keycode, &level))
|
||||
{
|
||||
g_warning ("No keycode found for keyval %x in current group", keyval);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
|
||||
keycode, &evcode);
|
||||
|
||||
if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", evcode);
|
||||
return;
|
||||
}
|
||||
|
||||
key_count = update_button_count (virtual_evdev, evcode, key_state);
|
||||
if (key_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x key presses (ignoring)",
|
||||
keycode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_state)
|
||||
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
||||
|
||||
clutter_seat_evdev_notify_key (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
evcode,
|
||||
key_state,
|
||||
TRUE);
|
||||
|
||||
if (!key_state)
|
||||
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEAT:
|
||||
g_value_set_pointer (value, virtual_evdev->seat);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEAT:
|
||||
virtual_evdev->seat = g_value_get_pointer (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_constructed (GObject *object)
|
||||
{
|
||||
ClutterVirtualInputDevice *virtual_device =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object);
|
||||
ClutterDeviceManager *manager;
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterStage *stage;
|
||||
|
||||
manager = clutter_virtual_input_device_get_manager (virtual_device);
|
||||
device_type = clutter_virtual_input_device_get_device_type (virtual_device);
|
||||
|
||||
virtual_evdev->device =
|
||||
_clutter_input_device_evdev_new_virtual (manager,
|
||||
virtual_evdev->seat,
|
||||
device_type,
|
||||
CLUTTER_INPUT_MODE_SLAVE);
|
||||
|
||||
stage = _clutter_device_manager_evdev_get_stage (CLUTTER_DEVICE_MANAGER_EVDEV (manager));
|
||||
_clutter_input_device_set_stage (virtual_evdev->device, stage);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_finalize (GObject *object)
|
||||
{
|
||||
ClutterVirtualInputDevice *virtual_device =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE (object);
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (object);
|
||||
GObjectClass *object_class;
|
||||
|
||||
release_pressed_buttons (virtual_device);
|
||||
g_clear_object (&virtual_evdev->device);
|
||||
|
||||
object_class =
|
||||
G_OBJECT_CLASS (clutter_virtual_input_device_evdev_parent_class);
|
||||
object_class->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_init (ClutterVirtualInputDeviceEvdev *virtual_device_evdev)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_class_init (ClutterVirtualInputDeviceEvdevClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterVirtualInputDeviceClass *virtual_input_device_class =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass);
|
||||
|
||||
object_class->get_property = clutter_virtual_input_device_evdev_get_property;
|
||||
object_class->set_property = clutter_virtual_input_device_evdev_set_property;
|
||||
object_class->constructed = clutter_virtual_input_device_evdev_constructed;
|
||||
object_class->finalize = clutter_virtual_input_device_evdev_finalize;
|
||||
|
||||
virtual_input_device_class->notify_relative_motion = clutter_virtual_input_device_evdev_notify_relative_motion;
|
||||
virtual_input_device_class->notify_absolute_motion = clutter_virtual_input_device_evdev_notify_absolute_motion;
|
||||
virtual_input_device_class->notify_button = clutter_virtual_input_device_evdev_notify_button;
|
||||
virtual_input_device_class->notify_key = clutter_virtual_input_device_evdev_notify_key;
|
||||
virtual_input_device_class->notify_keyval = clutter_virtual_input_device_evdev_notify_keyval;
|
||||
|
||||
obj_props[PROP_SEAT] = g_param_spec_pointer ("seat",
|
||||
P_("ClutterSeatEvdev"),
|
||||
P_("ClutterSeatEvdev"),
|
||||
CLUTTER_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||
}
|
||||
35
clutter/clutter/evdev/clutter-virtual-input-device-evdev.h
Normal file
35
clutter/clutter/evdev/clutter-virtual-input-device-evdev.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__
|
||||
#define __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
|
||||
#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_EVDEV (clutter_virtual_input_device_evdev_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (ClutterVirtualInputDeviceEvdev,
|
||||
clutter_virtual_input_device_evdev,
|
||||
CLUTTER, VIRTUAL_INPUT_DEVICE_EVDEV,
|
||||
ClutterVirtualInputDevice)
|
||||
|
||||
#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV_H__ */
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "clutter-backend-x11.h"
|
||||
#include "clutter-input-device-core-x11.h"
|
||||
#include "clutter-stage-x11.h"
|
||||
#include "clutter-virtual-input-device-x11.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-debug.h"
|
||||
@@ -480,6 +481,13 @@ clutter_device_manager_x11_get_device (ClutterDeviceManager *manager,
|
||||
GINT_TO_POINTER (id));
|
||||
}
|
||||
|
||||
static ClutterVirtualInputDevice *
|
||||
clutter_device_manager_x11_create_virtual_device (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDeviceType device_type)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_X11, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_x11_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
@@ -526,6 +534,7 @@ clutter_device_manager_x11_class_init (ClutterDeviceManagerX11Class *klass)
|
||||
manager_class->get_devices = clutter_device_manager_x11_get_devices;
|
||||
manager_class->get_core_device = clutter_device_manager_x11_get_core_device;
|
||||
manager_class->get_device = clutter_device_manager_x11_get_device;
|
||||
manager_class->create_virtual_device = clutter_device_manager_x11_create_virtual_device;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
89
clutter/clutter/x11/clutter-virtual-input-device-x11.c
Normal file
89
clutter/clutter/x11/clutter-virtual-input-device-x11.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clutter-build-config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "x11/clutter-virtual-input-device-x11.h"
|
||||
|
||||
struct _ClutterVirtualInputDeviceX11
|
||||
{
|
||||
ClutterVirtualInputDevice parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterVirtualInputDeviceX11,
|
||||
clutter_virtual_input_device_x11,
|
||||
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_notify_relative_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_notify_absolute_motion (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_init (ClutterVirtualInputDeviceX11 *virtual_device_x11)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_class_init (ClutterVirtualInputDeviceX11Class *klass)
|
||||
{
|
||||
ClutterVirtualInputDeviceClass *virtual_input_device_class =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_CLASS (klass);
|
||||
|
||||
virtual_input_device_class->notify_relative_motion = clutter_virtual_input_device_x11_notify_relative_motion;
|
||||
virtual_input_device_class->notify_absolute_motion = clutter_virtual_input_device_x11_notify_absolute_motion;
|
||||
virtual_input_device_class->notify_button = clutter_virtual_input_device_x11_notify_button;
|
||||
virtual_input_device_class->notify_key = clutter_virtual_input_device_x11_notify_key;
|
||||
}
|
||||
35
clutter/clutter/x11/clutter-virtual-input-device-x11.h
Normal file
35
clutter/clutter/x11/clutter-virtual-input-device-x11.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__
|
||||
#define __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
|
||||
#define CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_X11 (clutter_virtual_input_device_x11_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (ClutterVirtualInputDeviceX11,
|
||||
clutter_virtual_input_device_x11,
|
||||
CLUTTER, VIRTUAL_INPUT_DEVICE_X11,
|
||||
ClutterVirtualInputDevice)
|
||||
|
||||
#endif /* __CLUTTER_VIRTUAL_INPUT_DEVICE_X11_H__ */
|
||||
@@ -15,16 +15,13 @@ UNIT_TESTS = \
|
||||
test-state-animator.c \
|
||||
test-fbo.c \
|
||||
test-multistage.c \
|
||||
test-cogl-primitives.c \
|
||||
test-cogl-tex-tile.c \
|
||||
test-cogl-tex-convert.c \
|
||||
test-cogl-tex-foreign.c \
|
||||
test-cogl-tex-getset.c \
|
||||
test-cogl-offscreen.c \
|
||||
test-cogl-tex-polygon.c \
|
||||
test-cogl-multitexture.c \
|
||||
test-stage-read-pixels.c \
|
||||
test-clip.c \
|
||||
test-paint-wrapper.c \
|
||||
test-texture-quality.c \
|
||||
test-layout.c \
|
||||
|
||||
@@ -1,396 +0,0 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <gmodule.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef struct _CallbackData CallbackData;
|
||||
typedef struct _Clip Clip;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLIP_NONE,
|
||||
CLIP_RECTANGLE,
|
||||
CLIP_ROTATED_RECTANGLE,
|
||||
CLIP_SHAPES
|
||||
} ClipType;
|
||||
|
||||
struct _Clip
|
||||
{
|
||||
ClipType type;
|
||||
gint x1, y1, x2, y2;
|
||||
};
|
||||
|
||||
struct _CallbackData
|
||||
{
|
||||
ClutterActor *stage;
|
||||
CoglHandle hand;
|
||||
|
||||
Clip current_clip;
|
||||
|
||||
GSList *clips;
|
||||
};
|
||||
|
||||
static const char
|
||||
instructions[] =
|
||||
"Left button and drag to draw a rectangle, control+left to draw a rotated "
|
||||
"rectangle or shift+left to draw a path. Press 'r' to reset or 'u' "
|
||||
"to undo the last clip.";
|
||||
|
||||
static void
|
||||
path_shapes (gint x, gint y, gint width, gint height)
|
||||
{
|
||||
cogl_path_move_to (x, y);
|
||||
cogl_path_line_to (x, (y + height * 4 / 5));
|
||||
cogl_path_line_to ((x + width * 4 / 15), (y + height * 4 / 5));
|
||||
cogl_path_close ();
|
||||
|
||||
cogl_path_rectangle (x + width / 3,
|
||||
y,
|
||||
x + width * 9 / 15,
|
||||
y + height * 4 / 5);
|
||||
|
||||
cogl_path_ellipse ((x + width * 4 / 5),
|
||||
(y + height * 2 / 5),
|
||||
(width * 2 / 15),
|
||||
(height * 2 / 5));
|
||||
}
|
||||
|
||||
static void
|
||||
draw_shapes (gint x, gint y)
|
||||
{
|
||||
path_shapes (x, y, 300, 100);
|
||||
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||
cogl_path_fill_preserve ();
|
||||
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||
cogl_path_stroke ();
|
||||
}
|
||||
|
||||
static void
|
||||
make_clip_path (Clip *clip)
|
||||
{
|
||||
switch (clip->type)
|
||||
{
|
||||
case CLIP_NONE:
|
||||
break;
|
||||
|
||||
case CLIP_RECTANGLE:
|
||||
cogl_path_rectangle (clip->x1,
|
||||
clip->y1,
|
||||
clip->x2,
|
||||
clip->y2);
|
||||
break;
|
||||
|
||||
case CLIP_ROTATED_RECTANGLE:
|
||||
{
|
||||
int size = MIN (ABS (clip->x2 - clip->x1),
|
||||
ABS (clip->y2 - clip->y1));
|
||||
int cx = (clip->x1 + clip->x2) / 2;
|
||||
int cy = (clip->y1 + clip->y2) / 2;
|
||||
|
||||
cogl_path_move_to (cx - size / 2, cy);
|
||||
cogl_path_line_to (cx, cy - size / 2);
|
||||
cogl_path_line_to (cx + size / 2, cy);
|
||||
cogl_path_line_to (cx, cy + size / 2);
|
||||
cogl_path_close ();
|
||||
}
|
||||
break;
|
||||
|
||||
case CLIP_SHAPES:
|
||||
{
|
||||
int x, y, width, height;
|
||||
|
||||
if (clip->x1 < clip->x2)
|
||||
{
|
||||
x = clip->x1;
|
||||
width = clip->x2 - x;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = clip->x2;
|
||||
width = clip->x1 - x;
|
||||
}
|
||||
if (clip->y1 < clip->y2)
|
||||
{
|
||||
y = clip->y1;
|
||||
height = clip->y2 - y;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = clip->y2;
|
||||
height = clip->y1 - y;
|
||||
}
|
||||
|
||||
path_shapes (x, y, width, height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_paint (ClutterActor *actor, CallbackData *data)
|
||||
{
|
||||
int i;
|
||||
ClutterGeometry stage_size;
|
||||
gint hand_width, hand_height;
|
||||
GSList *node;
|
||||
|
||||
clutter_actor_get_allocation_geometry (data->stage, &stage_size);
|
||||
|
||||
hand_width = cogl_texture_get_width (data->hand);
|
||||
hand_height = cogl_texture_get_height (data->hand);
|
||||
|
||||
/* Setup the clipping */
|
||||
for (node = data->clips; node; node = node->next)
|
||||
{
|
||||
Clip *clip = (Clip *) node->data;
|
||||
|
||||
if (clip->type == CLIP_RECTANGLE)
|
||||
cogl_clip_push_rectangle (clip->x1,
|
||||
clip->y1,
|
||||
clip->x2,
|
||||
clip->y2);
|
||||
else if (clip->type == CLIP_ROTATED_RECTANGLE)
|
||||
{
|
||||
float size = MIN (ABS (clip->x2 - clip->x1),
|
||||
ABS (clip->y2 - clip->y1));
|
||||
int cx = (clip->x1 + clip->x2) / 2;
|
||||
int cy = (clip->y1 + clip->y2) / 2;
|
||||
|
||||
size = sqrtf ((size / 2) * (size / 2) * 2);
|
||||
|
||||
cogl_push_matrix ();
|
||||
|
||||
/* Rotate 45° about the centre point */
|
||||
cogl_translate (cx, cy, 0.0f);
|
||||
cogl_rotate (45.0f, 0.0f, 0.0f, 1.0f);
|
||||
cogl_clip_push_rectangle (-size / 2, -size / 2, size / 2, size / 2);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
else
|
||||
{
|
||||
make_clip_path (clip);
|
||||
cogl_clip_push_from_path ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Draw a rectangle filling the entire stage */
|
||||
cogl_set_source_color4ub (0x80, 0x80, 0xff, 0xff);
|
||||
cogl_rectangle (0, 0, stage_size.width, stage_size.height);
|
||||
|
||||
draw_shapes (10, 10);
|
||||
|
||||
/* Draw the hand at different rotations */
|
||||
for (i = -2; i <= 2; i++)
|
||||
{
|
||||
cogl_push_matrix ();
|
||||
|
||||
cogl_translate (stage_size.width / 2 + stage_size.width / 6 * i,
|
||||
stage_size.height / 2, 0);
|
||||
|
||||
cogl_rotate (i * 40, 0, 1, 0);
|
||||
|
||||
cogl_set_source_color4ub (0xff, 0xff, 0xff, 0xff);
|
||||
|
||||
cogl_set_source_texture (data->hand);
|
||||
cogl_rectangle_with_texture_coords ((-hand_width / 2),
|
||||
(-hand_height / 2),
|
||||
(hand_width / 2),
|
||||
(hand_height / 2),
|
||||
0, 0, 1, 1);
|
||||
|
||||
cogl_pop_matrix ();
|
||||
}
|
||||
|
||||
draw_shapes (stage_size.width - 310, stage_size.height - 110);
|
||||
|
||||
/* Remove all of the clipping */
|
||||
g_slist_foreach (data->clips, (GFunc) cogl_clip_pop, NULL);
|
||||
|
||||
/* Draw the bounding box for each of the clips */
|
||||
for (node = data->clips; node; node = node->next)
|
||||
{
|
||||
Clip *clip = (Clip *) node->data;
|
||||
|
||||
make_clip_path (clip);
|
||||
cogl_set_source_color4ub (0x00, 0x00, 0xff, 0xff);
|
||||
cogl_path_stroke ();
|
||||
}
|
||||
|
||||
/* Draw the bounding box for the pending new clip */
|
||||
if (data->current_clip.type != CLIP_NONE)
|
||||
{
|
||||
make_clip_path (&data->current_clip);
|
||||
cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
|
||||
cogl_path_stroke ();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_press (ClutterActor *stage, ClutterButtonEvent *event,
|
||||
CallbackData *data)
|
||||
{
|
||||
data->current_clip.x1 = data->current_clip.x2 = event->x;
|
||||
data->current_clip.y1 = data->current_clip.y2 = event->y;
|
||||
|
||||
switch (event->button)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRIMARY:
|
||||
if (clutter_event_has_shift_modifier ((ClutterEvent *) event))
|
||||
data->current_clip.type = CLIP_SHAPES;
|
||||
else if (clutter_event_has_control_modifier ((ClutterEvent *) event))
|
||||
data->current_clip.type = CLIP_ROTATED_RECTANGLE;
|
||||
else
|
||||
data->current_clip.type = CLIP_RECTANGLE;
|
||||
break;
|
||||
|
||||
case CLUTTER_BUTTON_SECONDARY:
|
||||
data->current_clip.type = CLIP_ROTATED_RECTANGLE;
|
||||
break;
|
||||
|
||||
case CLUTTER_BUTTON_MIDDLE:
|
||||
data->current_clip.type = CLIP_SHAPES;
|
||||
break;
|
||||
|
||||
default:
|
||||
data->current_clip.type = CLIP_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_button_release (ClutterActor *stage, ClutterButtonEvent *event,
|
||||
CallbackData *data)
|
||||
{
|
||||
if (data->current_clip.type != CLIP_NONE)
|
||||
{
|
||||
data->clips = g_slist_prepend (data->clips,
|
||||
g_slice_copy (sizeof (Clip),
|
||||
&data->current_clip));
|
||||
|
||||
data->current_clip.type = CLIP_NONE;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_motion (ClutterActor *stage, ClutterMotionEvent *event,
|
||||
CallbackData *data)
|
||||
{
|
||||
if (data->current_clip.type != CLIP_NONE)
|
||||
{
|
||||
data->current_clip.x2 = event->x;
|
||||
data->current_clip.y2 = event->y;
|
||||
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
free_clips (CallbackData *data)
|
||||
{
|
||||
GSList *node;
|
||||
|
||||
for (node = data->clips; node; node = node->next)
|
||||
g_slice_free (Clip, node->data);
|
||||
|
||||
g_slist_free (data->clips);
|
||||
|
||||
data->clips = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_key_press (ClutterActor *stage,
|
||||
ClutterEvent *event,
|
||||
CallbackData *data)
|
||||
{
|
||||
switch (clutter_event_get_key_symbol (event))
|
||||
{
|
||||
case CLUTTER_KEY_r:
|
||||
free_clips (data);
|
||||
clutter_actor_queue_redraw (stage);
|
||||
break;
|
||||
|
||||
case CLUTTER_KEY_u:
|
||||
if (data->clips)
|
||||
{
|
||||
g_slice_free (Clip, data->clips->data);
|
||||
data->clips = g_slist_delete_link (data->clips, data->clips);
|
||||
clutter_actor_queue_redraw (stage);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_clip_main (int argc, char **argv)
|
||||
{
|
||||
CallbackData data;
|
||||
ClutterActor *stub_actor, *label;
|
||||
gchar *file;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
data.current_clip.type = CLIP_NONE;
|
||||
data.clips = NULL;
|
||||
|
||||
data.stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (data.stage), "Clipping");
|
||||
g_signal_connect (data.stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
stub_actor = clutter_rectangle_new ();
|
||||
clutter_container_add (CLUTTER_CONTAINER (data.stage), stub_actor, NULL);
|
||||
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
data.hand = cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
g_free (file);
|
||||
|
||||
label = clutter_text_new_with_text ("Sans 12px", instructions);
|
||||
clutter_text_set_line_wrap (CLUTTER_TEXT (label), TRUE);
|
||||
clutter_actor_set_width (label, clutter_actor_get_width (data.stage) - 310);
|
||||
clutter_actor_set_y (label,
|
||||
clutter_actor_get_height (data.stage)
|
||||
- clutter_actor_get_height (label));
|
||||
clutter_container_add (CLUTTER_CONTAINER (data.stage), label, NULL);
|
||||
|
||||
g_signal_connect (stub_actor, "paint", G_CALLBACK (on_paint), &data);
|
||||
|
||||
g_signal_connect (data.stage, "button-press-event",
|
||||
G_CALLBACK (on_button_press), &data);
|
||||
g_signal_connect (data.stage, "button-release-event",
|
||||
G_CALLBACK (on_button_release), &data);
|
||||
g_signal_connect (data.stage, "motion-event",
|
||||
G_CALLBACK (on_motion), &data);
|
||||
g_signal_connect (data.stage, "key-press-event",
|
||||
G_CALLBACK (on_key_press), &data);
|
||||
|
||||
clutter_actor_show (data.stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
cogl_handle_unref (data.hand);
|
||||
|
||||
free_clips (&data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_clip_describe (void)
|
||||
{
|
||||
return "Actor clipping with various techniques";
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
typedef void (*PaintFunc) (void);
|
||||
|
||||
static void
|
||||
test_paint_line (void)
|
||||
{
|
||||
cogl_path_line (-50, -25, 50, 25);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_rect (void)
|
||||
{
|
||||
cogl_path_rectangle (-50, -25, 50, 25);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_rndrect(void)
|
||||
{
|
||||
cogl_path_round_rectangle (-50, -25, 50, 25, 10, 5);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_polyl (void)
|
||||
{
|
||||
gfloat poly_coords[] = {
|
||||
-50, -50,
|
||||
+50, -30,
|
||||
+30, +30,
|
||||
-30, +40
|
||||
};
|
||||
|
||||
cogl_path_polyline (poly_coords, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_polyg (void)
|
||||
{
|
||||
gfloat poly_coords[] = {
|
||||
-50, -50,
|
||||
+50, -30,
|
||||
+30, +30,
|
||||
-30, +40
|
||||
};
|
||||
|
||||
cogl_path_polygon (poly_coords, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_elp (void)
|
||||
{
|
||||
cogl_path_ellipse (0, 0, 60, 40);
|
||||
}
|
||||
|
||||
static void
|
||||
test_paint_curve (void)
|
||||
{
|
||||
cogl_path_move_to (-50, +50);
|
||||
|
||||
cogl_path_curve_to (+100, -50,
|
||||
-100, -50,
|
||||
+50, +50);
|
||||
}
|
||||
|
||||
static PaintFunc paint_func []=
|
||||
{
|
||||
test_paint_line,
|
||||
test_paint_rect,
|
||||
test_paint_rndrect,
|
||||
test_paint_polyl,
|
||||
test_paint_polyg,
|
||||
test_paint_elp,
|
||||
test_paint_curve
|
||||
};
|
||||
|
||||
static void
|
||||
paint_cb (ClutterActor *self, ClutterTimeline *tl)
|
||||
{
|
||||
gint paint_index = (clutter_timeline_get_progress (tl)
|
||||
* G_N_ELEMENTS (paint_func));
|
||||
|
||||
cogl_push_matrix ();
|
||||
|
||||
paint_func[paint_index] ();
|
||||
|
||||
cogl_translate (100, 100, 0);
|
||||
cogl_set_source_color4ub (0, 160, 0, 255);
|
||||
cogl_path_stroke_preserve ();
|
||||
|
||||
cogl_translate (150, 0, 0);
|
||||
cogl_set_source_color4ub (200, 0, 0, 255);
|
||||
cogl_path_fill ();
|
||||
|
||||
cogl_pop_matrix();
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_primitives_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
ClutterTimeline *tl;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
tl = clutter_timeline_new (G_N_ELEMENTS (paint_func) * 1000);
|
||||
clutter_timeline_set_loop (tl, TRUE);
|
||||
clutter_timeline_start (tl);
|
||||
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Path Primitives");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
coglbox = clutter_group_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
g_signal_connect (coglbox, "paint", G_CALLBACK (paint_cb), tl);
|
||||
/* Redraw every frame of the timeline */
|
||||
g_signal_connect_swapped (tl, "new-frame",
|
||||
G_CALLBACK (clutter_actor_queue_redraw), coglbox);
|
||||
|
||||
clutter_actor_set_rotation (coglbox, CLUTTER_Y_AXIS, -30, 200, 0, 0);
|
||||
clutter_actor_set_position (coglbox, 0, 100);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
g_object_unref (tl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_primitives (void)
|
||||
{
|
||||
return "2D Path primitives support in Cogl.";
|
||||
}
|
||||
@@ -1,270 +0,0 @@
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
/* Coglbox declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define TEST_TYPE_COGLBOX test_coglbox_get_type()
|
||||
|
||||
#define TEST_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
#define TEST_IS_COGLBOX(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_IS_COGLBOX_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
|
||||
TEST_TYPE_COGLBOX))
|
||||
|
||||
#define TEST_COGLBOX_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
TEST_TYPE_COGLBOX, TestCoglboxClass))
|
||||
|
||||
typedef struct _TestCoglbox TestCoglbox;
|
||||
typedef struct _TestCoglboxClass TestCoglboxClass;
|
||||
typedef struct _TestCoglboxPrivate TestCoglboxPrivate;
|
||||
|
||||
struct _TestCoglbox
|
||||
{
|
||||
ClutterActor parent;
|
||||
|
||||
/*< private >*/
|
||||
TestCoglboxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _TestCoglboxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
|
||||
/* padding for future expansion */
|
||||
void (*_test_coglbox1) (void);
|
||||
void (*_test_coglbox2) (void);
|
||||
void (*_test_coglbox3) (void);
|
||||
void (*_test_coglbox4) (void);
|
||||
};
|
||||
|
||||
static GType test_coglbox_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
/* Coglbox private declaration
|
||||
*--------------------------------------------------*/
|
||||
|
||||
G_DEFINE_TYPE (TestCoglbox, test_coglbox, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
#define TEST_COGLBOX_GET_PRIVATE(obj) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), TEST_TYPE_COGLBOX, TestCoglboxPrivate))
|
||||
|
||||
struct _TestCoglboxPrivate
|
||||
{
|
||||
CoglHandle cogl_tex_id[4];
|
||||
};
|
||||
|
||||
/* Coglbox implementation
|
||||
*--------------------------------------------------*/
|
||||
|
||||
static void
|
||||
test_coglbox_paint(ClutterActor *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv = TEST_COGLBOX_GET_PRIVATE (self);
|
||||
gfloat texcoords[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
|
||||
|
||||
cogl_set_source_color4ub (0x66, 0x66, 0xdd, 0xff);
|
||||
cogl_rectangle (0, 0, 400, 400);
|
||||
|
||||
cogl_push_matrix ();
|
||||
|
||||
cogl_translate (100, 100, 0);
|
||||
cogl_set_source_texture (priv->cogl_tex_id[1]);
|
||||
cogl_rectangle_with_texture_coords (0, 0, 200, 213,
|
||||
texcoords[0], texcoords[1],
|
||||
texcoords[2], texcoords[3]);
|
||||
|
||||
cogl_pop_matrix();
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_dispose (GObject *object)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
|
||||
priv = TEST_COGLBOX_GET_PRIVATE (object);
|
||||
cogl_handle_unref (priv->cogl_tex_id);
|
||||
|
||||
G_OBJECT_CLASS (test_coglbox_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_init (TestCoglbox *self)
|
||||
{
|
||||
TestCoglboxPrivate *priv;
|
||||
guint width;
|
||||
guint height;
|
||||
guint rowstride;
|
||||
CoglPixelFormat format;
|
||||
gint size;
|
||||
guchar *data;
|
||||
gint x,y,t;
|
||||
guchar *pixel;
|
||||
gchar *file;
|
||||
|
||||
self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self);
|
||||
|
||||
/* Load image from file */
|
||||
file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
|
||||
priv->cogl_tex_id[0] =
|
||||
cogl_texture_new_from_file (file,
|
||||
COGL_TEXTURE_NONE,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
NULL);
|
||||
|
||||
if (priv->cogl_tex_id[0] == COGL_INVALID_HANDLE)
|
||||
{
|
||||
printf ("Failed loading redhand.png image!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_free (file);
|
||||
|
||||
printf("Texture loaded from file.\n");
|
||||
|
||||
/* Obtain pixel data */
|
||||
|
||||
format = cogl_texture_get_format (priv->cogl_tex_id[0]);
|
||||
g_assert(format == COGL_PIXEL_FORMAT_RGBA_8888_PRE ||
|
||||
format == COGL_PIXEL_FORMAT_ARGB_8888_PRE);
|
||||
|
||||
width = cogl_texture_get_width (priv->cogl_tex_id[0]);
|
||||
height = cogl_texture_get_height (priv->cogl_tex_id[0]);
|
||||
size = cogl_texture_get_data (priv->cogl_tex_id[0],
|
||||
format, 0, NULL);
|
||||
|
||||
printf("size: %dx%d\n", width, height);
|
||||
printf("format: 0x%x\n", format);
|
||||
printf("bytesize: %d\n", size);
|
||||
|
||||
data = (guchar*) g_malloc (sizeof(guchar) * size);
|
||||
|
||||
cogl_texture_get_data (priv->cogl_tex_id[0],
|
||||
format, 0, data);
|
||||
rowstride = cogl_texture_get_rowstride (priv->cogl_tex_id[0]);
|
||||
|
||||
/* Create new texture from modified data */
|
||||
|
||||
priv->cogl_tex_id[1] =
|
||||
cogl_texture_new_from_data (width, height,
|
||||
COGL_TEXTURE_NONE,
|
||||
format, format,
|
||||
rowstride, data);
|
||||
|
||||
if (priv->cogl_tex_id[1] == COGL_INVALID_HANDLE)
|
||||
{
|
||||
printf ("Failed creating image from data!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
printf ("Texture created from data.\n");
|
||||
|
||||
/* Modify data (swap red and green) */
|
||||
|
||||
for (y=0; y<height; ++y)
|
||||
{
|
||||
for (x=0; x<width; ++x)
|
||||
{
|
||||
pixel = data + y * rowstride + x * 4;
|
||||
if (format == COGL_PIXEL_FORMAT_RGBA_8888_PRE)
|
||||
{
|
||||
t = pixel[0];
|
||||
pixel[0] = pixel[1];
|
||||
pixel[1] = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
t = pixel[1];
|
||||
pixel[1] = pixel[2];
|
||||
pixel[2] = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cogl_texture_set_region (priv->cogl_tex_id[1],
|
||||
0, 0, 0, 0,
|
||||
100, 100, width, height,
|
||||
format, 0, data);
|
||||
|
||||
cogl_texture_set_region (priv->cogl_tex_id[1],
|
||||
100, 100, 100, 100,
|
||||
100, 100, width, height,
|
||||
format, 0, data);
|
||||
|
||||
printf ("Subregion data updated.\n");
|
||||
}
|
||||
|
||||
static void
|
||||
test_coglbox_class_init (TestCoglboxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = test_coglbox_finalize;
|
||||
gobject_class->dispose = test_coglbox_dispose;
|
||||
actor_class->paint = test_coglbox_paint;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (TestCoglboxPrivate));
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
test_coglbox_new (void)
|
||||
{
|
||||
return g_object_new (TEST_TYPE_COGLBOX, NULL);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_cogl_tex_getset_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage;
|
||||
ClutterActor *coglbox;
|
||||
|
||||
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
|
||||
return 1;
|
||||
|
||||
/* Stage */
|
||||
stage = clutter_stage_new ();
|
||||
clutter_actor_set_size (stage, 400, 400);
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl Texture Readback");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
|
||||
/* Cogl Box */
|
||||
coglbox = test_coglbox_new ();
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), coglbox);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT const char *
|
||||
test_cogl_tex_getset_describe (void)
|
||||
{
|
||||
return "Texture region readback and update in Cogl.";
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include <config.h>
|
||||
#include <clutter-build-config.h>
|
||||
#include <glib.h>
|
||||
#include <gmodule.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
* conflicts we only expose the minimal set of GLES 2.0 types and enums
|
||||
* publicly.
|
||||
*/
|
||||
#ifdef COGL_COMPILATION
|
||||
#if defined(COGL_COMPILATION) || defined(COGL_ENABLE_MUTTER_API)
|
||||
#include "cogl-gl-header.h"
|
||||
#else
|
||||
#include <cogl/cogl-gles2-types.h>
|
||||
|
||||
@@ -936,7 +936,7 @@ _cogl_pipeline_layer_needs_combine_separate
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
|
||||
if (egl_display->current_draw_surface == draw &&
|
||||
egl_display->current_read_surface == read &&
|
||||
egl_display->current_context == context)
|
||||
return EGL_TRUE;
|
||||
return EGL_TRUE;
|
||||
|
||||
ret = eglMakeCurrent (egl_renderer->edpy,
|
||||
draw,
|
||||
|
||||
@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [21])
|
||||
m4_define([mutter_micro_version], [3])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -59,14 +59,14 @@ AM_PATH_GLIB_2_0([2.49.0])
|
||||
CANBERRA_GTK=libcanberra-gtk3
|
||||
CANBERRA_GTK_VERSION=0.26
|
||||
|
||||
LIBWACOM_VERSION=0.19
|
||||
LIBWACOM_VERSION=0.13
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
gtk+-3.0 >= 3.19.8
|
||||
gio-unix-2.0 >= 2.35.1
|
||||
pango >= 1.2.0
|
||||
cairo >= 1.10.0
|
||||
gsettings-desktop-schemas >= 3.19.3
|
||||
gsettings-desktop-schemas >= 3.21.4
|
||||
json-glib-1.0
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
@@ -246,7 +246,7 @@ AS_IF([test "$have_wayland" = "yes"], [
|
||||
AC_SUBST([WAYLAND_SCANNER])
|
||||
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
|
||||
|
||||
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.1],
|
||||
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.5],
|
||||
[ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
|
||||
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
|
||||
])
|
||||
|
||||
@@ -6,6 +6,7 @@ data/50-mutter-windows.xml.in
|
||||
data/mutter.desktop.in
|
||||
data/org.gnome.mutter.gschema.xml.in
|
||||
data/org.gnome.mutter.wayland.gschema.xml.in
|
||||
src/backends/meta-input-settings.c
|
||||
src/backends/meta-monitor-manager.c
|
||||
src/compositor/compositor.c
|
||||
src/compositor/meta-background.c
|
||||
@@ -23,6 +24,7 @@ src/core/util.c
|
||||
src/core/window.c
|
||||
src/ui/frames.c
|
||||
src/ui/theme.c
|
||||
src/wayland/meta-wayland-tablet-pad.c
|
||||
src/x11/session.c
|
||||
src/x11/window-props.c
|
||||
src/x11/xprops.c
|
||||
|
||||
1
po/am.po
1
po/am.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2003-02-03 10:16+EDT\n"
|
||||
"Last-Translator: Ge'ez Frontier Foundation <locales@geez.org>\n"
|
||||
"Language-Team: Amharic <locales@geez.org>\n"
|
||||
"Language: am\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/as.po
2
po/as.po
@@ -14,7 +14,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-08-18 21:37+0530\n"
|
||||
"Last-Translator: Nilamdyuti Goswami <ngoswami@redhat.com>\n"
|
||||
"Language-Team: Assamese <kde-i18n-doc@kde.org>\n"
|
||||
"Language: as_IN\n"
|
||||
"Language: as\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/az.po
2
po/az.po
@@ -12,10 +12,10 @@ msgstr ""
|
||||
"PO-Revision-Date: 2004-08-17 21:53+0300\n"
|
||||
"Last-Translator: Metin Amiroff <metin@karegen.com>\n"
|
||||
"Language-Team: Azerbaijani <translation-team-az@lists.sourceforge.net>\n"
|
||||
"Language: az\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"net>\n"
|
||||
"X-Generator: KBabel 1.3.1\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2009-02-14 19:37+0200\n"
|
||||
"Last-Translator: Ihar Hrachyshka <ihar.hrachyshka@gmail.com>\n"
|
||||
"Language-Team: i18n@mova.org <i18n@mova.org>\n"
|
||||
"Language: be@latin\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/bn.po
1
po/bn.po
@@ -13,6 +13,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2005-10-03 01:16+0600\n"
|
||||
"Last-Translator: Mahay Alam Khan <makl10n@yahoo.com>\n"
|
||||
"Language-Team: Bengali <gnome-trans@bengalinux.org>\n"
|
||||
"Language: bn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -19,7 +19,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-09-25 13:56+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bengali (India) <kde-i18n-doc@kde.org>\n"
|
||||
"Language: bn-IN\n"
|
||||
"Language: bn_IN\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/br.po
1
po/br.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2009-09-14 04:51+0100\n"
|
||||
"Last-Translator: Denis\n"
|
||||
"Language-Team: Brenux <brenux@free.fr>\n"
|
||||
"Language: br\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-09-14 21:12+0200\n"
|
||||
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
|
||||
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
|
||||
"Language: ca-XV\n"
|
||||
"Language: ca@valencia\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bits\n"
|
||||
|
||||
1
po/cy.po
1
po/cy.po
@@ -15,6 +15,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2008-02-05 21:12-0000\n"
|
||||
"Last-Translator: Rhys Jones <rhys@sucs.org>\n"
|
||||
"Language-Team: Cymraeg <gnome-cy@pengwyn.linux.org.uk>\n"
|
||||
"Language: cy\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/dz.po
1
po/dz.po
@@ -10,6 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2007-05-24 23:11+0530\n"
|
||||
"Last-Translator: Tshewang Norbu <bumthap2006@hotmail.com>\n"
|
||||
"Language-Team: DZONGKHA <pgeyleg@dit.gov.bt>\n"
|
||||
"Language: dz\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2005-07-18 18:28-0400\n"
|
||||
"Last-Translator: Adam Weinberger <adamw@gnome.org>\n"
|
||||
"Language-Team: Canadian English <adamw@gnome.org>\n"
|
||||
"Language: en_CA\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
59
po/es.po
59
po/es.po
@@ -14,11 +14,11 @@ msgstr ""
|
||||
"Project-Id-Version: mutter.master\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2016-02-28 13:37+0000\n"
|
||||
"PO-Revision-Date: 2016-02-29 16:02+0100\n"
|
||||
"POT-Creation-Date: 2016-07-24 19:39+0000\n"
|
||||
"PO-Revision-Date: 2016-07-26 13:00+0200\n"
|
||||
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
|
||||
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
|
||||
"Language: \n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -464,29 +464,38 @@ msgstr "Cambiar al VT 11"
|
||||
msgid "Switch to VT 12"
|
||||
msgstr "Cambiar al VT 12"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:518
|
||||
#: ../src/backends/meta-input-settings.c:1605
|
||||
#| msgid "Switch system controls"
|
||||
msgid "Switch monitor"
|
||||
msgstr "Cambiar monitor"
|
||||
|
||||
#: ../src/backends/meta-input-settings.c:1607
|
||||
msgid "Show on-screen help"
|
||||
msgstr "Mostrar la ayuda en pantalla"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:515
|
||||
msgid "Built-in display"
|
||||
msgstr "Pantalla integrada"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:544
|
||||
#: ../src/backends/meta-monitor-manager.c:538
|
||||
msgid "Unknown"
|
||||
msgstr "Desconocida"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:546
|
||||
#: ../src/backends/meta-monitor-manager.c:540
|
||||
msgid "Unknown Display"
|
||||
msgstr "Pantalla desconocida"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: ../src/backends/meta-monitor-manager.c:554
|
||||
#: ../src/backends/meta-monitor-manager.c:548
|
||||
#, c-format
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:456
|
||||
#: ../src/compositor/compositor.c:463
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
@@ -495,7 +504,7 @@ msgstr ""
|
||||
"Ya existe un gestor de composición ejecutándose en la monitor %i, pantalla "
|
||||
"«%s»."
|
||||
|
||||
#: ../src/core/bell.c:185
|
||||
#: ../src/core/bell.c:194
|
||||
msgid "Bell event"
|
||||
msgstr "Evento de campana"
|
||||
|
||||
@@ -524,45 +533,44 @@ msgstr "_Esperar"
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Forzar la salida"
|
||||
|
||||
#: ../src/core/display.c:555
|
||||
#: ../src/core/display.c:590
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n"
|
||||
|
||||
#: ../src/core/main.c:181
|
||||
#: ../src/core/main.c:182
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "Desactivar conexión al gestor de sesión"
|
||||
|
||||
#: ../src/core/main.c:187
|
||||
#: ../src/core/main.c:188
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "Reemplazar el gestor de ventanas en ejecución"
|
||||
|
||||
#: ../src/core/main.c:193
|
||||
#: ../src/core/main.c:194
|
||||
msgid "Specify session management ID"
|
||||
msgstr "Especificar el ID se gestión de sesión"
|
||||
|
||||
#: ../src/core/main.c:198
|
||||
#: ../src/core/main.c:199
|
||||
msgid "X Display to use"
|
||||
msgstr "Pantalla X que usar"
|
||||
|
||||
#: ../src/core/main.c:204
|
||||
#: ../src/core/main.c:205
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "Inicializar sesión desde el archivo de salvaguarda"
|
||||
|
||||
#: ../src/core/main.c:210
|
||||
#: ../src/core/main.c:211
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "Hacer que las llamadas a las X sean síncronas"
|
||||
|
||||
#: ../src/core/main.c:217
|
||||
#: ../src/core/main.c:218
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "Ejecutar como compositor Wayland"
|
||||
|
||||
#: ../src/core/main.c:223
|
||||
#| msgid "Run as a wayland compositor"
|
||||
#: ../src/core/main.c:224
|
||||
msgid "Run as a nested compositor"
|
||||
msgstr "Ejecutar como compositor anidado"
|
||||
|
||||
#: ../src/core/main.c:231
|
||||
#: ../src/core/main.c:232
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Ejecutar como servidor completo, en lugar de anidado"
|
||||
|
||||
@@ -603,15 +611,20 @@ msgstr ""
|
||||
"La pantalla «%s» ya tiene un gestor de ventanas; pruebe a usar la opción «--"
|
||||
"replace» para reemplazar el gestor de ventanas activo."
|
||||
|
||||
#: ../src/core/screen.c:603
|
||||
#: ../src/core/screen.c:606
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "La ventana %d en la pantalla «%s» no es válida\n"
|
||||
|
||||
#: ../src/core/util.c:121
|
||||
#: ../src/core/util.c:120
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter fue compilado sin soporte para modo prolijo\n"
|
||||
|
||||
#: ../src/wayland/meta-wayland-tablet-pad.c:595
|
||||
#, c-format
|
||||
msgid "Mode Switch: Mode %d"
|
||||
msgstr "Cambiar modo: modo %d"
|
||||
|
||||
#: ../src/x11/session.c:1815
|
||||
msgid ""
|
||||
"These windows do not support "save current setup" and will have to "
|
||||
@@ -620,7 +633,7 @@ msgstr ""
|
||||
"Estas ventanas no soportan «guardar la configuración actual» y tendrán que "
|
||||
"reiniciarse manualmente la próxima vez que inicie una sesión."
|
||||
|
||||
#: ../src/x11/window-props.c:549
|
||||
#: ../src/x11/window-props.c:548
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (on %s)"
|
||||
|
||||
1
po/fa.po
1
po/fa.po
@@ -13,6 +13,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2012-04-01 00:10+0330\n"
|
||||
"Last-Translator: Arash Mousavi <mousavi.arash@gmail.com>\n"
|
||||
"Language-Team: Persian\n"
|
||||
"Language: fa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/gu.po
2
po/gu.po
@@ -11,7 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-09-12 11:50+0530\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: American English <kde-i18n-doc@kde.org>\n"
|
||||
"Language: \n"
|
||||
"Language: gu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ha.po
1
po/ha.po
@@ -7,6 +7,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2006-05-11 13:30+0100\n"
|
||||
"Last-Translator: saudat mohammed <saudat@wazobialinux>\n"
|
||||
"Language-Team: hausa\n"
|
||||
"Language: ha\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/hr.po
1
po/hr.po
@@ -10,6 +10,7 @@ msgstr ""
|
||||
"Last-Translator: Launchpad Translations Administrators <rosetta@launchpad."
|
||||
"net>\n"
|
||||
"Language-Team: Croatian <lokalizacija@linux.hr>\n"
|
||||
"Language: hr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/hy.po
1
po/hy.po
@@ -9,6 +9,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2005-09-04 18:18+0200\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: <en@li.org>\n"
|
||||
"Language: hy\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ig.po
1
po/ig.po
@@ -7,6 +7,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2006-07-07 10:49+0100\n"
|
||||
"Last-Translator: Onye, Sylvester <sylvester@wazobialinux.com>\n"
|
||||
"Language-Team: Igbo\n"
|
||||
"Language: ig\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/is.po
1
po/is.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2003-06-22 17:16--100\n"
|
||||
"Last-Translator: Samuel Jon Gunnarsson <sammi@techattack.nu>\n"
|
||||
"Language-Team: Icelandic <gnome@techattack.nu>\n"
|
||||
"Language: is\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ka.po
1
po/ka.po
@@ -15,6 +15,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2007-09-07 14:18+0200\n"
|
||||
"Last-Translator: Vladimer Sichinava ვლადიმერ სიჭინავა <vsichi@gnome.org>\n"
|
||||
"Language-Team: Georgian <http://mail.gnome.org/mailman/listinfo/gnome-ge-list>\n"
|
||||
"Language: ka\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/ko.po
2
po/ko.po
@@ -22,7 +22,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2016-03-13 04:38+0900\n"
|
||||
"Last-Translator: Changwoo Ryu <cwryu@debian.org>\n"
|
||||
"Language-Team: GNOME Korea <gnome-kr@googlegroups.com>\n"
|
||||
"Language: Korean\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ku.po
1
po/ku.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2007-03-04 21:37+0100\n"
|
||||
"Last-Translator: Erdal Ronahi <erdal.ronahi@gmail.com>\n"
|
||||
"Language-Team: Kurdish <gnu-ku-wergerandin@lists.sourceforge.net>\n"
|
||||
"Language: ku\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/la.po
1
po/la.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2008-10-17 22:07-0400\n"
|
||||
"Last-Translator: Thomas Thurman <tthurman@gnome.org>\n"
|
||||
"Language-Team: Latin <la@li.org>\n"
|
||||
"Language: la\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2009-03-15 16:17+0530\n"
|
||||
"Last-Translator: Sangeeta Kumari <sangeeta09@gmail.com>\n"
|
||||
"Language-Team: Maithili <maithili.sf.net>\n"
|
||||
"Language: mai\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/mg.po
1
po/mg.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2006-06-29 22:27+0300\n"
|
||||
"Last-Translator: Fano Rajaonarisoa <rajfanhar@yahoo.fr>\n"
|
||||
"Language-Team: Malagasy <i18n-malagasy-gnome@gna.org>\n"
|
||||
"Language: mg\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit"
|
||||
|
||||
1
po/mk.po
1
po/mk.po
@@ -19,6 +19,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2008-02-03 12:50+0100\n"
|
||||
"Last-Translator: Arangel Angov <ufo@linux.net.mk>\n"
|
||||
"Language-Team: Macedonian <ossm-members@hedona.on.net.mk>\n"
|
||||
"Language: mk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/mn.po
1
po/mn.po
@@ -17,6 +17,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2004-01-03 15:09+0100\n"
|
||||
"Last-Translator: Sanlig Badral <Badral@openmn.org>\n"
|
||||
"Language-Team: Mongolian <openmn-core@lists.sf.net>\n"
|
||||
"Language: mn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ms.po
1
po/ms.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"Last-Translator: Hasbullah Bin Pit <sebol@ikhlas.com>\n"
|
||||
"Language-Team: Projek Gabai (Bahasa Melayu) <gabai-penyumbang@lists."
|
||||
"sourceforge.net>\n"
|
||||
"Language: ms\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/nb.po
2
po/nb.po
@@ -10,7 +10,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2015-03-19 21:24+0100\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
|
||||
"Language: \n"
|
||||
"Language: nb\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2010-08-08 15:45+0100\n"
|
||||
"Last-Translator: Nils-Christoph Fiedler <ncfiedler@gnome.org>\n"
|
||||
"Language-Team: Low German <nds-lowgerman@lists.sourceforge.net>\n"
|
||||
"Language: nds\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/ne.po
1
po/ne.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2007-12-26 15:17+0545\n"
|
||||
"Last-Translator: Nabin Gautam <nabin@mpp.org.np>\n"
|
||||
"Language-Team: Nepali <info@mpp.org.np>\n"
|
||||
"Language: ne\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/nn.po
1
po/nn.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2009-06-16 09:54-0400\n"
|
||||
"Last-Translator: Eskild Hustvedt <eskildh@gnome.org>\n"
|
||||
"Language-Team: Norwegian Nynorsk <i18n-no@lister.ping.uio.no>\n"
|
||||
"Language: nn\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/rw.po
1
po/rw.po
@@ -19,6 +19,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2005-03-28 19:35-0700\n"
|
||||
"Last-Translator: Steve Murphy <murf@e-tools.com>\n"
|
||||
"Language-Team: Kinyarwanda <translation-team-rw@lists.sourceforge.net>\n"
|
||||
"Language: rw\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/si.po
1
po/si.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2007-08-17 14:12+0530\n"
|
||||
"Last-Translator: Danishka Navin <snavin@redhat.com>\n"
|
||||
"Language-Team: Sinhala <en@li.org>\n"
|
||||
"Language: si\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/sl.po
2
po/sl.po
@@ -15,7 +15,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2016-03-05 21:12+0100\n"
|
||||
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
|
||||
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
|
||||
"Language: sl_SI\n"
|
||||
"Language: sl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/sq.po
1
po/sq.po
@@ -11,6 +11,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2008-09-27 12:27+0200\n"
|
||||
"Last-Translator: Laurent Dhima <laurenti@alblinux.net>\n"
|
||||
"Language-Team: albanian <gnome-albanian-perkthyesit@lists.sourceforge.net>\n"
|
||||
"Language: sq\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2016-03-09 09:52+0200\n"
|
||||
"Last-Translator: Miroslav Nikolić <miroslavnikolic@rocketmail.com>\n"
|
||||
"Language-Team: Serbian <(nothing)>\n"
|
||||
"Language: sr\n"
|
||||
"Language: sr@latin\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
4
po/ta.po
4
po/ta.po
@@ -20,12 +20,10 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-09-15 01:22+0630\n"
|
||||
"Last-Translator: Shantha kumar <shkumar@redhat.com>\n"
|
||||
"Language-Team: American English <kde-i18n-doc@kde.org>\n"
|
||||
"com>>\n"
|
||||
"Language: en_US\n"
|
||||
"Language: ta\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"0500\n"
|
||||
"X-Generator: Lokalize 1.5\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n!=1);\\n"
|
||||
"\n"
|
||||
|
||||
2
po/tg.po
2
po/tg.po
@@ -12,7 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-01-21 16:12+0500\n"
|
||||
"Last-Translator: Victor Ibragimov <victor.ibragimov@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: Tajik\n"
|
||||
"Language: tg\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/tk.po
1
po/tk.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2004-08-13 03:30+0330\n"
|
||||
"Last-Translator: Gurban Mühemmet Tewekgeli <gmtavakkoli@yahoo.com>\n"
|
||||
"Language-Team: Turkmen <kakilikgroup@yahoo.com>\n"
|
||||
"Language: tk\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
2
po/ug.po
2
po/ug.po
@@ -13,7 +13,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2013-04-06 18:40+0900\n"
|
||||
"Last-Translator: Gheyret Kenji <gheyret@gmail.com>\n"
|
||||
"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
|
||||
"Language: \n"
|
||||
"Language: ug\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/wa.po
1
po/wa.po
@@ -15,6 +15,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2003-07-12 14:51+0200\n"
|
||||
"Last-Translator: Pablo Saratxaga <pablo@mandrakesoft.com>\n"
|
||||
"Language-Team: Walon <linux-wa@walon.org>\n"
|
||||
"Language: wa\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/xh.po
1
po/xh.po
@@ -12,6 +12,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2005-03-22 18:03+0200\n"
|
||||
"Last-Translator: Canonical Ltd <translations@canonical.com>\n"
|
||||
"Language-Team: Xhosa <xh-translate@ubuntu.com>\n"
|
||||
"Language: xh\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
1
po/yo.po
1
po/yo.po
@@ -7,6 +7,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2006-08-09 13:26+0100\n"
|
||||
"Last-Translator: Fajuyitan, Sunday Ayo <ayo@wazobialinux.com>\n"
|
||||
"Language-Team: Yoruba\n"
|
||||
"Language: yo\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -14,7 +14,7 @@ msgstr ""
|
||||
"PO-Revision-Date: 2014-08-21 18:55+0800\n"
|
||||
"Last-Translator: Chao-Hsiung Liao <j_h_liau@yahoo.com.tw>\n"
|
||||
"Language-Team: Chinese (Hong Kong) <community@linuxhall.org>\n"
|
||||
"Language: zh_TW\n"
|
||||
"Language: zh_HK\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <meta/meta-idle-monitor.h>
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-monitor-manager-private.h"
|
||||
#include "meta-input-settings-private.h"
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "backends/meta-renderer.h"
|
||||
#include "core/util-private.h"
|
||||
@@ -146,4 +147,6 @@ void meta_backend_monitors_changed (MetaBackend *backend);
|
||||
|
||||
gboolean meta_is_stage_views_enabled (void);
|
||||
|
||||
MetaInputSettings *meta_backend_get_input_settings (MetaBackend *backend);
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <clutter/clutter-mutter.h>
|
||||
#include <meta/meta-backend.h>
|
||||
#include <meta/main.h>
|
||||
#include "meta-backend-private.h"
|
||||
#include "meta-input-settings-private.h"
|
||||
|
||||
@@ -72,7 +73,13 @@ struct _MetaBackendPrivate
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaBackend, meta_backend, G_TYPE_OBJECT);
|
||||
static void
|
||||
initable_iface_init (GInitableIface *initable_iface);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
|
||||
G_ADD_PRIVATE (MetaBackend)
|
||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
||||
initable_iface_init));
|
||||
|
||||
static void
|
||||
meta_backend_finalize (GObject *object)
|
||||
@@ -316,7 +323,7 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
g_slist_free (devices);
|
||||
}
|
||||
|
||||
priv->input_settings = meta_input_settings_get ();
|
||||
priv->input_settings = meta_input_settings_create ();
|
||||
|
||||
center_pointer (backend);
|
||||
}
|
||||
@@ -362,21 +369,11 @@ meta_backend_real_get_relative_motion_deltas (MetaBackend *backend,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_constructed (GObject *object)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (object);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->renderer = META_BACKEND_GET_CLASS (backend)->create_renderer (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_class_init (MetaBackendClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_backend_constructed;
|
||||
object_class->finalize = meta_backend_finalize;
|
||||
|
||||
klass->post_init = meta_backend_real_post_init;
|
||||
@@ -406,6 +403,32 @@ meta_backend_class_init (MetaBackendClass *klass)
|
||||
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_backend_initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (initable);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->renderer = META_BACKEND_GET_CLASS (backend)->create_renderer (backend);
|
||||
if (!priv->renderer)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Failed to create MetaRenderer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
initable_iface_init (GInitableIface *initable_iface)
|
||||
{
|
||||
initable_iface->init = meta_backend_initable_init;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_init (MetaBackend *backend)
|
||||
{
|
||||
@@ -615,7 +638,7 @@ void
|
||||
meta_backend_set_client_pointer_constraint (MetaBackend *backend,
|
||||
MetaPointerConstraint *constraint)
|
||||
{
|
||||
g_assert (!constraint || (constraint && !backend->client_pointer_constraint));
|
||||
g_assert (!constraint || !backend->client_pointer_constraint);
|
||||
|
||||
g_clear_object (&backend->client_pointer_constraint);
|
||||
if (constraint)
|
||||
@@ -696,6 +719,8 @@ void
|
||||
meta_init_backend (MetaBackendType backend_type)
|
||||
{
|
||||
GType type;
|
||||
MetaBackend *backend;
|
||||
GError *error = NULL;
|
||||
|
||||
switch (backend_type)
|
||||
{
|
||||
@@ -715,7 +740,12 @@ meta_init_backend (MetaBackendType backend_type)
|
||||
|
||||
/* meta_backend_init() above install the backend globally so
|
||||
* so meta_get_backend() works even during initialization. */
|
||||
g_object_new (type, NULL);
|
||||
backend = g_object_new (type, NULL);
|
||||
if (!g_initable_init (G_INITABLE (backend), NULL, &error))
|
||||
{
|
||||
g_warning ("Failed to create backend: %s", error->message);
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,3 +794,11 @@ meta_is_stage_views_enabled (void)
|
||||
|
||||
return strcmp (mutter_stage_views, "1") == 0;
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
meta_backend_get_input_settings (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
return priv->input_settings;
|
||||
}
|
||||
|
||||
@@ -101,12 +101,12 @@ struct _MetaInputSettingsClass
|
||||
|
||||
GType meta_input_settings_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaInputSettings * meta_input_settings_get (void);
|
||||
MetaInputSettings * meta_input_settings_create (void);
|
||||
|
||||
GSettings * meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
MetaOutput * meta_input_settings_get_tablet_output (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
MetaMonitorInfo * meta_input_settings_get_tablet_monitor_info (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GDesktopTabletMapping meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
@@ -128,7 +128,7 @@ gboolean meta_input_settings_handle_pad_button (MetaIn
|
||||
ClutterInputDevice *pad,
|
||||
gboolean is_press,
|
||||
guint button);
|
||||
gchar * meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
gchar * meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ static GQuark quark_tool_settings = 0;
|
||||
|
||||
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
|
||||
typedef struct _DeviceMappingInfo DeviceMappingInfo;
|
||||
typedef struct _ToolSettings ToolSettings;
|
||||
|
||||
struct _DeviceMappingInfo
|
||||
{
|
||||
@@ -56,6 +57,15 @@ struct _DeviceMappingInfo
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _ToolSettings
|
||||
{
|
||||
GSettings *settings;
|
||||
ClutterInputDeviceTool *tool;
|
||||
GDesktopStylusButtonAction button_action;
|
||||
GDesktopStylusButtonAction secondary_button_action;
|
||||
gdouble curve[4];
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsPrivate
|
||||
{
|
||||
ClutterDeviceManager *device_manager;
|
||||
@@ -132,8 +142,10 @@ meta_input_settings_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&priv->monitor_manager);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (priv->wacom_db)
|
||||
libwacom_database_destroy (priv->wacom_db);
|
||||
#endif
|
||||
|
||||
G_OBJECT_CLASS (meta_input_settings_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -913,39 +925,118 @@ lookup_device_settings (ClutterInputDevice *device)
|
||||
return settings;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
static void
|
||||
tool_settings_cache_pressure_curve (ToolSettings *tool_settings)
|
||||
{
|
||||
GVariant *variant;
|
||||
const gint32 *curve;
|
||||
gsize n_elems;
|
||||
|
||||
if (clutter_input_device_tool_get_tool_type (tool_settings->tool) ==
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
variant = g_settings_get_value (tool_settings->settings, "eraser-pressure-curve");
|
||||
else
|
||||
variant = g_settings_get_value (tool_settings->settings, "pressure-curve");
|
||||
|
||||
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
||||
if (n_elems == 4)
|
||||
{
|
||||
tool_settings->curve[0] = (gdouble) curve[0] / 100;
|
||||
tool_settings->curve[1] = (gdouble) curve[1] / 100;
|
||||
tool_settings->curve[2] = (gdouble) curve[2] / 100;
|
||||
tool_settings->curve[3] = (gdouble) curve[3] / 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
tool_settings->curve[0] = tool_settings->curve[1] = 0;
|
||||
tool_settings->curve[2] = tool_settings->curve[3] = 1;
|
||||
}
|
||||
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
static void
|
||||
tool_settings_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
ToolSettings *tool_settings)
|
||||
{
|
||||
if (strcmp (key, "button-action") == 0)
|
||||
tool_settings->button_action = g_settings_get_enum (settings, "button-action");
|
||||
else if (strcmp (key, "secondary-button-action") == 0)
|
||||
tool_settings->secondary_button_action = g_settings_get_enum (settings, "secondary-button-action");
|
||||
else if (strcmp (key, "pressure-curve") == 0 &&
|
||||
clutter_input_device_tool_get_tool_type (tool_settings->tool) !=
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
tool_settings_cache_pressure_curve (tool_settings);
|
||||
else if (strcmp (key, "eraser-pressure-curve") == 0 &&
|
||||
clutter_input_device_tool_get_tool_type (tool_settings->tool) ==
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
tool_settings_cache_pressure_curve (tool_settings);
|
||||
}
|
||||
|
||||
static ToolSettings *
|
||||
tool_settings_new (ClutterInputDeviceTool *tool,
|
||||
const gchar *schema_path)
|
||||
{
|
||||
ToolSettings *tool_settings;
|
||||
|
||||
tool_settings = g_new0 (ToolSettings, 1);
|
||||
tool_settings->tool = tool;
|
||||
tool_settings->settings =
|
||||
g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
|
||||
schema_path);
|
||||
|
||||
g_signal_connect (tool_settings->settings, "changed",
|
||||
G_CALLBACK (tool_settings_changed_cb), tool_settings);
|
||||
|
||||
/* Initialize values */
|
||||
tool_settings->button_action =
|
||||
g_settings_get_enum (tool_settings->settings, "button-action");
|
||||
tool_settings->secondary_button_action =
|
||||
g_settings_get_enum (tool_settings->settings, "secondary-button-action");
|
||||
tool_settings_cache_pressure_curve (tool_settings);
|
||||
|
||||
return tool_settings;
|
||||
}
|
||||
|
||||
static void
|
||||
tool_settings_free (ToolSettings *tool_settings)
|
||||
{
|
||||
g_object_unref (tool_settings->settings);
|
||||
g_free (tool_settings);
|
||||
}
|
||||
|
||||
static ToolSettings *
|
||||
lookup_tool_settings (ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
GSettings *settings;
|
||||
ToolSettings *tool_settings;
|
||||
guint64 serial;
|
||||
gchar *path;
|
||||
|
||||
settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
|
||||
tool_settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
|
||||
if (tool_settings)
|
||||
return tool_settings;
|
||||
|
||||
if (!settings)
|
||||
serial = clutter_input_device_tool_get_serial (tool);
|
||||
|
||||
if (serial == 0)
|
||||
{
|
||||
serial = clutter_input_device_tool_get_serial (tool);
|
||||
|
||||
if (serial == 0)
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
|
||||
clutter_input_device_get_vendor_id (device),
|
||||
clutter_input_device_get_product_id (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", serial);
|
||||
}
|
||||
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
|
||||
path);
|
||||
g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, settings,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_free (path);
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
|
||||
clutter_input_device_get_vendor_id (device),
|
||||
clutter_input_device_get_product_id (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", serial);
|
||||
}
|
||||
|
||||
return settings;
|
||||
tool_settings = tool_settings_new (tool, path);
|
||||
g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, tool_settings,
|
||||
(GDestroyNotify) tool_settings_free);
|
||||
g_free (path);
|
||||
|
||||
return tool_settings;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
@@ -1164,15 +1255,17 @@ meta_input_settings_init (MetaInputSettings *settings)
|
||||
g_signal_connect (priv->monitor_manager, "monitors-changed",
|
||||
G_CALLBACK (monitors_changed_cb), settings);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
priv->wacom_db = libwacom_database_new ();
|
||||
if (!priv->wacom_db)
|
||||
{
|
||||
g_warning ("Could not create database of Wacom devices, "
|
||||
"expect tablets to misbehave");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static MetaInputSettings *
|
||||
MetaInputSettings *
|
||||
meta_input_settings_create (void)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
@@ -1189,20 +1282,6 @@ meta_input_settings_create (void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
meta_input_settings_get (void)
|
||||
{
|
||||
static MetaInputSettings *input_settings = NULL;
|
||||
|
||||
if (g_once_init_enter (&input_settings))
|
||||
{
|
||||
MetaInputSettings *settings = meta_input_settings_create ();
|
||||
g_once_init_leave (&input_settings, settings);
|
||||
}
|
||||
|
||||
return input_settings;
|
||||
}
|
||||
|
||||
GSettings *
|
||||
meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
@@ -1219,12 +1298,13 @@ meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
return info ? g_object_ref (info->settings) : NULL;
|
||||
}
|
||||
|
||||
MetaOutput *
|
||||
meta_input_settings_get_tablet_output (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
MetaMonitorInfo *
|
||||
meta_input_settings_get_tablet_monitor_info (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
MetaOutput *output;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
@@ -1234,7 +1314,12 @@ meta_input_settings_get_tablet_output (MetaInputSettings *settings,
|
||||
if (!info)
|
||||
return NULL;
|
||||
|
||||
return meta_input_settings_find_output (settings, info->settings, device);
|
||||
output = meta_input_settings_find_output (settings, info->settings, device);
|
||||
|
||||
if (output && output->crtc)
|
||||
return output->crtc->logical_monitor;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GDesktopTabletMapping
|
||||
@@ -1262,19 +1347,19 @@ meta_input_settings_get_stylus_button_action (MetaInputSettings *input_sett
|
||||
ClutterInputDevice *current_tablet,
|
||||
guint button)
|
||||
{
|
||||
GSettings *settings;
|
||||
ToolSettings *tool_settings;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
|
||||
settings = lookup_tool_settings (tool, current_tablet);
|
||||
tool_settings = lookup_tool_settings (tool, current_tablet);
|
||||
|
||||
if (button == 2)
|
||||
return g_settings_get_enum (settings, "button-action");
|
||||
return tool_settings->button_action;
|
||||
else if (button == 3)
|
||||
return g_settings_get_enum (settings, "secondary-button-action");
|
||||
return tool_settings->secondary_button_action;
|
||||
else
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
@@ -1426,10 +1511,7 @@ meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *inpu
|
||||
ClutterInputDevice *current_tablet,
|
||||
gdouble pressure)
|
||||
{
|
||||
GSettings *settings;
|
||||
GVariant *variant;
|
||||
const gint32 *curve;
|
||||
gsize n_elems;
|
||||
ToolSettings *tool_settings;
|
||||
|
||||
pressure = CLAMP (pressure, 0, 1);
|
||||
|
||||
@@ -1437,24 +1519,12 @@ meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *inpu
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), pressure);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (current_tablet), pressure);
|
||||
|
||||
settings = lookup_tool_settings (tool, current_tablet);
|
||||
|
||||
if (clutter_input_device_tool_get_tool_type (tool) == CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
variant = g_settings_get_value (settings, "eraser-pressure-curve");
|
||||
else
|
||||
variant = g_settings_get_value (settings, "pressure-curve");
|
||||
|
||||
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
||||
if (n_elems != 4)
|
||||
return pressure;
|
||||
|
||||
tool_settings = lookup_tool_settings (tool, current_tablet);
|
||||
pressure = calculate_bezier_position (pressure,
|
||||
(gdouble) curve[0] / 100,
|
||||
(gdouble) curve[1] / 100,
|
||||
(gdouble) curve[2] / 100,
|
||||
(gdouble) curve[3] / 100);
|
||||
g_variant_unref (variant);
|
||||
|
||||
tool_settings->curve[0],
|
||||
tool_settings->curve[1],
|
||||
tool_settings->curve[2],
|
||||
tool_settings->curve[3]);
|
||||
return pressure;
|
||||
}
|
||||
|
||||
@@ -1505,7 +1575,7 @@ meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
|
||||
@@ -54,6 +54,8 @@ meta_input_settings_native_set_send_events (MetaInputSettings *settings,
|
||||
}
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
libinput_device_config_send_events_set_mode (libinput_device, libinput_mode);
|
||||
}
|
||||
|
||||
@@ -65,6 +67,8 @@ meta_input_settings_native_set_matrix (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
if (libinput_device_config_calibration_has_matrix (libinput_device) > 0)
|
||||
libinput_device_config_calibration_set_matrix (libinput_device, matrix);
|
||||
@@ -78,6 +82,8 @@ meta_input_settings_native_set_speed (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
libinput_device_config_accel_set_speed (libinput_device,
|
||||
CLAMP (speed, -1, 1));
|
||||
}
|
||||
@@ -90,6 +96,8 @@ meta_input_settings_native_set_left_handed (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
if (libinput_device_config_left_handed_is_available (libinput_device))
|
||||
libinput_device_config_left_handed_set (libinput_device, enabled);
|
||||
@@ -103,6 +111,8 @@ meta_input_settings_native_set_tap_enabled (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
if (libinput_device_config_tap_get_finger_count (libinput_device) > 0)
|
||||
libinput_device_config_tap_set_enabled (libinput_device,
|
||||
@@ -119,6 +129,8 @@ meta_input_settings_native_set_invert_scroll (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
if (libinput_device_config_scroll_has_natural_scroll (libinput_device))
|
||||
libinput_device_config_scroll_set_natural_scroll_enabled (libinput_device,
|
||||
@@ -163,6 +175,8 @@ meta_input_settings_native_set_edge_scroll (MetaInputSettings *settin
|
||||
enum libinput_config_scroll_method supported;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
supported = libinput_device_config_scroll_get_methods (libinput_device);
|
||||
|
||||
if (supported & LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
@@ -190,6 +204,8 @@ meta_input_settings_native_set_scroll_button (MetaInputSettings *settings,
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
if (!device_set_scroll_method (libinput_device,
|
||||
LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN))
|
||||
@@ -207,6 +223,8 @@ meta_input_settings_native_set_click_method (MetaInputSettings *settin
|
||||
struct libinput_device *libinput_device;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
|
||||
@@ -1022,6 +1022,7 @@ meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native)
|
||||
"layout", &view_layout,
|
||||
"framebuffer", framebuffer,
|
||||
NULL);
|
||||
cogl_object_unref (framebuffer);
|
||||
|
||||
meta_onscreen_native_set_view (onscreen, view);
|
||||
|
||||
@@ -1056,6 +1057,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
"framebuffer", framebuffer,
|
||||
"monitor-info", monitor_info,
|
||||
NULL);
|
||||
cogl_object_unref (framebuffer);
|
||||
|
||||
meta_onscreen_native_set_view (onscreen, view);
|
||||
|
||||
|
||||
@@ -553,27 +553,6 @@ on_startup_notification_changed (MetaStartupNotification *sn,
|
||||
g_signal_emit_by_name (display->screen, "startup-sequence-changed", sequence);
|
||||
}
|
||||
|
||||
static void
|
||||
check_pad_removed (MetaDisplay *display,
|
||||
ClutterInputDevice *device,
|
||||
ClutterDeviceManager *device_manager)
|
||||
{
|
||||
ClutterInputDevice *pad;
|
||||
|
||||
if (!display->current_pad_osd)
|
||||
return;
|
||||
|
||||
pad = g_object_get_data (G_OBJECT (display->current_pad_osd),
|
||||
"meta-pad-osd-device");
|
||||
|
||||
if (pad == device)
|
||||
{
|
||||
/* Close pad OSD */
|
||||
clutter_actor_destroy (display->current_pad_osd);
|
||||
display->current_pad_osd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_display_open:
|
||||
*
|
||||
@@ -941,11 +920,10 @@ meta_display_open (void)
|
||||
display->compositor = NULL;
|
||||
|
||||
/* Mutter used to manage all X screens of the display in a single process, but
|
||||
* now it always manages exactly one screen as specified by the DISPLAY
|
||||
* environment variable.
|
||||
* now it always manages exactly one screen - the default screen retrieved
|
||||
* from GDK.
|
||||
*/
|
||||
i = meta_ui_get_screen_number ();
|
||||
screen = meta_screen_new (display, i, timestamp);
|
||||
screen = meta_screen_new (display, timestamp);
|
||||
|
||||
if (!screen)
|
||||
{
|
||||
@@ -997,10 +975,6 @@ meta_display_open (void)
|
||||
|
||||
meta_idle_monitor_init_dbus ();
|
||||
|
||||
g_signal_connect_swapped (clutter_device_manager_get_default (),
|
||||
"device-removed", G_CALLBACK (check_pad_removed),
|
||||
display);
|
||||
|
||||
/* Done opening new display */
|
||||
display->display_opening = FALSE;
|
||||
|
||||
@@ -2665,7 +2639,7 @@ meta_display_unmanage_screen (MetaDisplay *display,
|
||||
guint32 timestamp)
|
||||
{
|
||||
meta_verbose ("Unmanaging screen %d on display %s\n",
|
||||
screen->number, display->name);
|
||||
meta_ui_get_screen_number (), display->name);
|
||||
meta_display_close (display, timestamp);
|
||||
}
|
||||
|
||||
@@ -3129,14 +3103,14 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
MetaInputSettings *input_settings;
|
||||
const gchar *layout_path = NULL;
|
||||
ClutterActor *osd;
|
||||
MetaOutput *output;
|
||||
MetaMonitorInfo *monitor;
|
||||
gint monitor_idx;
|
||||
GSettings *settings;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (display->current_pad_osd)
|
||||
{
|
||||
@@ -3147,7 +3121,7 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
if (input_settings)
|
||||
{
|
||||
settings = meta_input_settings_get_tablet_settings (input_settings, pad);
|
||||
output = meta_input_settings_get_tablet_output (input_settings, pad);
|
||||
monitor = meta_input_settings_get_tablet_monitor_info (input_settings, pad);
|
||||
#ifdef HAVE_LIBWACOM
|
||||
wacom_device = meta_input_settings_get_tablet_wacom_device (input_settings,
|
||||
pad);
|
||||
@@ -3158,10 +3132,10 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
if (!layout_path || !settings)
|
||||
return;
|
||||
|
||||
if (output && output->crtc)
|
||||
if (monitor)
|
||||
{
|
||||
monitor_idx = meta_screen_get_monitor_index_for_rect (display->screen,
|
||||
&output->crtc->rect);
|
||||
&monitor->rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3175,11 +3149,8 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
if (osd)
|
||||
{
|
||||
display->current_pad_osd = osd;
|
||||
g_object_set_data (G_OBJECT (display->current_pad_osd),
|
||||
"meta-pad-osd-device", pad);
|
||||
g_object_add_weak_pointer (G_OBJECT (display->current_pad_osd),
|
||||
(gpointer *) &display->current_pad_osd);
|
||||
clutter_actor_grab_key_focus (osd);
|
||||
}
|
||||
|
||||
g_object_unref (settings);
|
||||
@@ -3198,7 +3169,7 @@ meta_display_get_pad_action_label (MetaDisplay *display,
|
||||
{
|
||||
MetaInputSettings *settings;
|
||||
|
||||
settings = meta_input_settings_get ();
|
||||
settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
label = meta_input_settings_get_pad_button_action_label (settings, pad, action_number);
|
||||
if (label)
|
||||
return label;
|
||||
|
||||
@@ -69,7 +69,6 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->rect.y,
|
||||
frame->rect.width,
|
||||
frame->rect.height,
|
||||
frame->window->screen->number,
|
||||
&create_serial);
|
||||
frame->xwindow = frame->ui_frame->xwindow;
|
||||
|
||||
|
||||
@@ -304,50 +304,75 @@ on_sigterm (gpointer user_data)
|
||||
}
|
||||
|
||||
#if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND)
|
||||
static char *
|
||||
find_logind_session_type (void)
|
||||
static gboolean
|
||||
session_type_is_supported (const char *session_type)
|
||||
{
|
||||
char **sessions;
|
||||
return (g_strcmp0 (session_type, "x11") == 0) ||
|
||||
(g_strcmp0 (session_type, "wayland") == 0);
|
||||
}
|
||||
|
||||
static char *
|
||||
find_session_type (void)
|
||||
{
|
||||
char **sessions = NULL;
|
||||
char *session_id;
|
||||
char *session_type;
|
||||
const char *session_type_env;
|
||||
gboolean is_tty = FALSE;
|
||||
int ret, i;
|
||||
|
||||
ret = sd_pid_get_session (0, &session_id);
|
||||
|
||||
if (ret == 0 && session_id != NULL)
|
||||
{
|
||||
ret = sd_session_get_type (session_id, &session_type);
|
||||
free (session_id);
|
||||
|
||||
if (ret < 0)
|
||||
session_type = NULL;
|
||||
if (ret == 0)
|
||||
{
|
||||
if (session_type_is_supported (session_type))
|
||||
goto out;
|
||||
else
|
||||
is_tty = g_strcmp0 (session_type, "tty") == 0;
|
||||
free (session_type);
|
||||
}
|
||||
}
|
||||
else if (sd_uid_get_sessions (getuid (), 1, &sessions) > 0)
|
||||
{
|
||||
for (i = 0; sessions[i] != NULL; i++)
|
||||
{
|
||||
ret = sd_session_get_type (sessions[i], &session_type);
|
||||
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
if (session_type_is_supported (session_type))
|
||||
{
|
||||
g_strfreev (sessions);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (session_type);
|
||||
}
|
||||
}
|
||||
g_strfreev (sessions);
|
||||
|
||||
session_type_env = g_getenv ("XDG_SESSION_TYPE");
|
||||
if (session_type_is_supported (session_type_env))
|
||||
{
|
||||
/* The string should be freeable */
|
||||
session_type = strdup (session_type_env);
|
||||
goto out;
|
||||
}
|
||||
session_type = NULL;
|
||||
|
||||
ret = sd_uid_get_sessions (getuid (), TRUE, &sessions);
|
||||
|
||||
if (ret < 0 || sessions == NULL)
|
||||
goto out;
|
||||
|
||||
for (i = 0; sessions[i] != NULL; i++)
|
||||
/* Legacy support for starting through xinit */
|
||||
if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")))
|
||||
{
|
||||
ret = sd_session_get_type (sessions[i], &session_type);
|
||||
|
||||
if (ret < 0)
|
||||
continue;
|
||||
|
||||
if (g_strcmp0 (session_type, "x11") == 0||
|
||||
g_strcmp0 (session_type, "wayland") == 0)
|
||||
break;
|
||||
|
||||
g_clear_pointer (&session_type, (GDestroyNotify) free);
|
||||
session_type = strdup ("x11");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i] != NULL; i++)
|
||||
free (sessions[i]);
|
||||
free (sessions);
|
||||
meta_warning ("Unsupported session type\n");
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
|
||||
out:
|
||||
return session_type;
|
||||
@@ -356,16 +381,12 @@ out:
|
||||
static gboolean
|
||||
check_for_wayland_session_type (void)
|
||||
{
|
||||
char *session_type = NULL;
|
||||
gboolean is_wayland = FALSE;
|
||||
char *session_type;
|
||||
gboolean is_wayland;
|
||||
|
||||
session_type = find_logind_session_type ();
|
||||
|
||||
if (session_type != NULL)
|
||||
{
|
||||
is_wayland = g_strcmp0 (session_type, "wayland") == 0;
|
||||
free (session_type);
|
||||
}
|
||||
session_type = find_session_type ();
|
||||
is_wayland = g_strcmp0 (session_type, "wayland") == 0;
|
||||
free (session_type);
|
||||
|
||||
return is_wayland;
|
||||
}
|
||||
@@ -441,8 +462,10 @@ meta_init (void)
|
||||
|
||||
calculate_compositor_configuration (&compositor_type, &backend_type);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (compositor_type == META_COMPOSITOR_TYPE_WAYLAND)
|
||||
meta_set_is_wayland_compositor (TRUE);
|
||||
#endif
|
||||
|
||||
if (g_get_home_dir ())
|
||||
if (chdir (g_get_home_dir ()) < 0)
|
||||
|
||||
@@ -756,8 +756,8 @@ meta_window_place (MetaWindow *window,
|
||||
x += xi->rect.x;
|
||||
y += xi->rect.y;
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
|
||||
window->desc, window->screen->number, xi->number);
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on monitor %d\n",
|
||||
window->desc, xi->number);
|
||||
|
||||
goto done_check_denied_focus;
|
||||
}
|
||||
|
||||
@@ -48,9 +48,7 @@ struct _MetaScreen
|
||||
GObject parent_instance;
|
||||
|
||||
MetaDisplay *display;
|
||||
int number;
|
||||
char *screen_name;
|
||||
Screen *xscreen;
|
||||
Window xroot;
|
||||
int default_depth;
|
||||
Visual *default_xvisual;
|
||||
@@ -119,7 +117,6 @@ struct _MetaScreenClass
|
||||
};
|
||||
|
||||
MetaScreen* meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
guint32 timestamp);
|
||||
void meta_screen_free (MetaScreen *screen,
|
||||
guint32 timestamp);
|
||||
|
||||
@@ -569,10 +569,11 @@ take_manager_selection (MetaDisplay *display,
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
int number;
|
||||
Screen *xscreen;
|
||||
Window xroot;
|
||||
Display *xdisplay;
|
||||
Window new_wm_sn_owner;
|
||||
@@ -583,6 +584,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
|
||||
replace_current_wm = meta_get_replace_current_wm ();
|
||||
|
||||
number = meta_ui_get_screen_number ();
|
||||
|
||||
/* Only display->name, display->xdisplay, and display->error_traps
|
||||
* can really be used in this function, since normally screens are
|
||||
* created from the MetaDisplay constructor
|
||||
@@ -642,9 +645,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->closing = 0;
|
||||
|
||||
screen->display = display;
|
||||
screen->number = number;
|
||||
screen->screen_name = get_screen_name (display, number);
|
||||
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->xroot = xroot;
|
||||
screen->rect.x = screen->rect.y = 0;
|
||||
|
||||
@@ -655,10 +656,10 @@ meta_screen_new (MetaDisplay *display,
|
||||
meta_monitor_manager_get_screen_size (manager,
|
||||
&screen->rect.width,
|
||||
&screen->rect.height);
|
||||
|
||||
xscreen = ScreenOfDisplay (xdisplay, number);
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
screen->default_xvisual = DefaultVisualOfScreen (xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (xscreen);
|
||||
|
||||
screen->wm_sn_selection_window = new_wm_sn_owner;
|
||||
screen->wm_sn_atom = wm_sn_atom;
|
||||
@@ -715,8 +716,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->keys_grabbed = FALSE;
|
||||
meta_screen_grab_keys (screen);
|
||||
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay);
|
||||
|
||||
screen->tile_preview_timeout_id = 0;
|
||||
|
||||
@@ -726,7 +726,7 @@ meta_screen_new (MetaDisplay *display,
|
||||
meta_prefs_add_listener (prefs_changed_callback, screen);
|
||||
|
||||
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
|
||||
screen->number, screen->screen_name, screen->xroot);
|
||||
number, screen->screen_name, screen->xroot);
|
||||
|
||||
return screen;
|
||||
}
|
||||
@@ -793,7 +793,7 @@ meta_screen_free (MetaScreen *screen,
|
||||
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
|
||||
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);
|
||||
meta_ui_get_screen_number (), screen->display->name);
|
||||
|
||||
unset_wm_check_hint (screen);
|
||||
|
||||
@@ -1956,8 +1956,7 @@ meta_screen_update_workspace_names (MetaScreen *screen)
|
||||
screen->display->atom__NET_DESKTOP_NAMES,
|
||||
&names, &n_names))
|
||||
{
|
||||
meta_verbose ("Failed to get workspace names from root window %d\n",
|
||||
screen->number);
|
||||
meta_verbose ("Failed to get workspace names from root window\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2656,7 +2655,7 @@ meta_screen_apply_startup_properties (MetaScreen *screen,
|
||||
int
|
||||
meta_screen_get_screen_number (MetaScreen *screen)
|
||||
{
|
||||
return screen->number;
|
||||
return meta_ui_get_screen_number ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2712,7 +2711,8 @@ meta_screen_set_cm_selection (MetaScreen *screen)
|
||||
guint32 timestamp;
|
||||
|
||||
timestamp = meta_display_get_current_time_roundtrip (screen->display);
|
||||
g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d", screen->number);
|
||||
g_snprintf (selection, sizeof (selection), "_NET_WM_CM_S%d",
|
||||
meta_ui_get_screen_number ());
|
||||
a = XInternAtom (screen->display->xdisplay, selection, False);
|
||||
screen->wm_cm_selection_window = take_manager_selection (screen->display, screen->xroot, a, timestamp, TRUE);
|
||||
}
|
||||
|
||||
@@ -237,7 +237,7 @@ meta_stack_tracker_dump (MetaStackTracker *tracker)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "MetaStackTracker state (screen=%d)\n", tracker->screen->number);
|
||||
meta_topic (META_DEBUG_STACK, "MetaStackTracker state\n");
|
||||
meta_push_no_msg_prefix ();
|
||||
meta_topic (META_DEBUG_STACK, " xserver_serial: %ld\n", tracker->xserver_serial);
|
||||
meta_topic (META_DEBUG_STACK, " verified_stack: ");
|
||||
|
||||
@@ -675,7 +675,7 @@ meta_startup_notification_constructed (GObject *object)
|
||||
sn_error_trap_pop);
|
||||
sn->sn_context =
|
||||
sn_monitor_context_new (sn->sn_display,
|
||||
sn->display->screen->number,
|
||||
meta_ui_get_screen_number (),
|
||||
meta_startup_notification_sn_event,
|
||||
sn,
|
||||
NULL);
|
||||
|
||||
@@ -421,16 +421,11 @@ meta_ui_frame_calc_geometry (MetaUIFrame *frame,
|
||||
}
|
||||
|
||||
MetaFrames*
|
||||
meta_frames_new (int screen_number)
|
||||
meta_frames_new (void)
|
||||
{
|
||||
GdkScreen *screen;
|
||||
MetaFrames *frames;
|
||||
|
||||
screen = gdk_display_get_screen (gdk_display_get_default (),
|
||||
screen_number);
|
||||
|
||||
frames = g_object_new (META_TYPE_FRAMES,
|
||||
"screen", screen,
|
||||
"type", GTK_WINDOW_POPUP,
|
||||
NULL);
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ struct _MetaFramesClass
|
||||
|
||||
GType meta_frames_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaFrames *meta_frames_new (int screen_number);
|
||||
MetaFrames *meta_frames_new (void);
|
||||
|
||||
MetaUIFrame * meta_frames_manage_window (MetaFrames *frames,
|
||||
MetaWindow *meta_window,
|
||||
|
||||
18
src/ui/ui.c
18
src/ui/ui.c
@@ -34,7 +34,6 @@
|
||||
struct _MetaUI
|
||||
{
|
||||
Display *xdisplay;
|
||||
Screen *xscreen;
|
||||
MetaFrames *frames;
|
||||
|
||||
/* For double-click tracking */
|
||||
@@ -81,20 +80,18 @@ meta_ui_get_screen_number (void)
|
||||
}
|
||||
|
||||
MetaUI*
|
||||
meta_ui_new (Display *xdisplay,
|
||||
Screen *screen)
|
||||
meta_ui_new (Display *xdisplay)
|
||||
{
|
||||
GdkDisplay *gdisplay;
|
||||
MetaUI *ui;
|
||||
|
||||
ui = g_new0 (MetaUI, 1);
|
||||
ui->xdisplay = xdisplay;
|
||||
ui->xscreen = screen;
|
||||
|
||||
gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
|
||||
g_assert (gdisplay == gdk_display_get_default ());
|
||||
|
||||
ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
|
||||
ui->frames = meta_frames_new ();
|
||||
/* GTK+ needs the frame-sync protocol to work in order to properly
|
||||
* handle style changes. This means that the dummy widget we create
|
||||
* to get the style for title bars actually needs to be mapped
|
||||
@@ -141,16 +138,17 @@ meta_ui_create_frame (MetaUI *ui,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
gint screen_no,
|
||||
gulong *create_serial)
|
||||
{
|
||||
GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay);
|
||||
GdkScreen *screen = gdk_display_get_screen (display, screen_no);
|
||||
GdkScreen *screen;
|
||||
GdkWindowAttr attrs;
|
||||
gint attributes_mask;
|
||||
GdkWindow *window;
|
||||
GdkVisual *visual;
|
||||
|
||||
screen = gdk_display_get_default_screen (display);
|
||||
|
||||
/* Default depth/visual handles clients with weird visuals; they can
|
||||
* always be children of the root depth/visual obviously, but
|
||||
* e.g. DRI games can't be children of a parent that has the same
|
||||
@@ -251,14 +249,16 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
|
||||
MetaFrameFlags flags,
|
||||
MetaFrameBorders *borders)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkScreen *screen;
|
||||
int text_height;
|
||||
MetaStyleInfo *style_info = NULL;
|
||||
PangoContext *context;
|
||||
const PangoFontDescription *font_desc;
|
||||
PangoFontDescription *free_font_desc = NULL;
|
||||
|
||||
GdkDisplay *display = gdk_x11_lookup_xdisplay (ui->xdisplay);
|
||||
GdkScreen *screen = gdk_display_get_screen (display, XScreenNumberOfScreen (ui->xscreen));
|
||||
display = gdk_x11_lookup_xdisplay (ui->xdisplay);
|
||||
screen = gdk_display_get_default_screen (display);
|
||||
|
||||
style_info = meta_theme_create_style_info (screen, NULL);
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ Display* meta_ui_get_display (void);
|
||||
|
||||
gint meta_ui_get_screen_number (void);
|
||||
|
||||
MetaUI* meta_ui_new (Display *xdisplay,
|
||||
Screen *screen);
|
||||
MetaUI* meta_ui_new (Display *xdisplay);
|
||||
void meta_ui_free (MetaUI *ui);
|
||||
|
||||
void meta_ui_theme_get_frame_borders (MetaUI *ui,
|
||||
@@ -59,7 +58,6 @@ MetaUIFrame * meta_ui_create_frame (MetaUI *ui,
|
||||
gint y,
|
||||
gint width,
|
||||
gint height,
|
||||
gint screen_no,
|
||||
gulong *create_serial);
|
||||
void meta_ui_move_resize_frame (MetaUI *ui,
|
||||
Window frame,
|
||||
|
||||
@@ -563,8 +563,7 @@ parent_surface_state_applied (gpointer data, gpointer user_data)
|
||||
MetaWaylandSurface *parent = surface->sub.parent;
|
||||
ClutterActor *parent_actor =
|
||||
clutter_actor_get_parent (CLUTTER_ACTOR (parent->surface_actor));
|
||||
ClutterActor *surface_actor =
|
||||
surface_actor = CLUTTER_ACTOR (surface->surface_actor);
|
||||
ClutterActor *surface_actor = CLUTTER_ACTOR (surface->surface_actor);
|
||||
|
||||
for (it = surface->sub.pending_placement_ops; it; it = it->next)
|
||||
{
|
||||
|
||||
@@ -82,6 +82,7 @@ tablet_pad_group_destroy (struct wl_client *client,
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_tablet_pad_group_v2_interface group_interface = {
|
||||
tablet_pad_group_destroy
|
||||
};
|
||||
@@ -314,12 +315,11 @@ broadcast_group_mode (MetaWaylandTabletPadGroup *group,
|
||||
uint32_t time)
|
||||
{
|
||||
struct wl_display *display = group->pad->tablet_seat->seat->wl_display;
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
group->mode_switch_serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, &group->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_pad_group_v2_send_mode_switch (resource, time,
|
||||
group->mode_switch_serial,
|
||||
@@ -330,10 +330,9 @@ broadcast_group_mode (MetaWaylandTabletPadGroup *group,
|
||||
static void
|
||||
broadcast_group_buttons (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, &group->focus_resource_list)
|
||||
{
|
||||
meta_wayland_tablet_pad_group_send_buttons (group, resource);
|
||||
}
|
||||
@@ -412,9 +411,7 @@ move_resources_for_client (struct wl_list *destination,
|
||||
void
|
||||
meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group)
|
||||
{
|
||||
struct wl_list *l = &group->focus_resource_list;
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&group->focus_resource_list))
|
||||
{
|
||||
move_resources (&group->resource_list, &group->focus_resource_list);
|
||||
}
|
||||
@@ -429,8 +426,11 @@ meta_wayland_tablet_pad_group_sync_focus (MetaWaylandTabletPadGroup *group)
|
||||
meta_wayland_tablet_pad_group_update_rings_focus (group);
|
||||
meta_wayland_tablet_pad_group_update_strips_focus (group);
|
||||
|
||||
broadcast_group_mode (group, clutter_get_current_event_time ());
|
||||
broadcast_group_buttons (group);
|
||||
if (!wl_list_empty (&group->focus_resource_list))
|
||||
{
|
||||
broadcast_group_mode (group, clutter_get_current_event_time ());
|
||||
broadcast_group_buttons (group);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
||||
@@ -100,13 +100,13 @@ static const struct zwp_tablet_pad_ring_v2_interface ring_interface = {
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
struct wl_resource *group_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_ring_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_get_version (group_resource), id);
|
||||
wl_resource_set_implementation (resource, &ring_interface,
|
||||
ring, unbind_resource);
|
||||
wl_resource_set_user_data (resource, ring);
|
||||
@@ -115,30 +115,16 @@ meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_lookup_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&ring->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&ring->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_list *l = &ring->focus_resource_list;
|
||||
struct wl_list *focus_resources = &ring->focus_resource_list;
|
||||
enum zwp_tablet_pad_ring_v2_source source;
|
||||
gboolean source_known = FALSE;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
if (wl_list_empty (focus_resources))
|
||||
return FALSE;
|
||||
if (event->type != CLUTTER_PAD_RING)
|
||||
return FALSE;
|
||||
@@ -149,7 +135,7 @@ meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring,
|
||||
source_known = TRUE;
|
||||
}
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, focus_resources)
|
||||
{
|
||||
gdouble angle = event->pad_ring.angle;
|
||||
|
||||
@@ -195,11 +181,9 @@ move_resources_for_client (struct wl_list *destination,
|
||||
void
|
||||
meta_wayland_tablet_pad_ring_sync_focus (MetaWaylandTabletPadRing *ring)
|
||||
{
|
||||
struct wl_list *l = &ring->focus_resource_list;
|
||||
|
||||
g_clear_pointer (&ring->feedback, g_free);
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&ring->focus_resource_list))
|
||||
{
|
||||
move_resources (&ring->resource_list, &ring->focus_resource_list);
|
||||
}
|
||||
|
||||
@@ -48,11 +48,8 @@ void meta_wayland_tablet_pad_ring_set_group (MetaWaylandTa
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_create_new_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
struct wl_resource *group_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_ring_lookup_resource (MetaWaylandTabletPadRing *ring,
|
||||
struct wl_client *client);
|
||||
|
||||
gboolean meta_wayland_tablet_pad_ring_handle_event (MetaWaylandTabletPadRing *ring,
|
||||
const ClutterEvent *event);
|
||||
|
||||
@@ -100,13 +100,13 @@ static const struct zwp_tablet_pad_strip_v2_interface strip_interface = {
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *seat_resource,
|
||||
struct wl_resource *group_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_tablet_pad_strip_v2_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_get_version (group_resource), id);
|
||||
wl_resource_set_implementation (resource, &strip_interface,
|
||||
strip, unbind_resource);
|
||||
wl_resource_set_user_data (resource, strip);
|
||||
@@ -115,30 +115,16 @@ meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *st
|
||||
return resource;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_lookup_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_find_for_client (&strip->resource_list, client);
|
||||
|
||||
if (!resource)
|
||||
resource = wl_resource_find_for_client (&strip->focus_resource_list, client);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_list *l = &strip->focus_resource_list;
|
||||
struct wl_list *focus_resources = &strip->focus_resource_list;
|
||||
enum zwp_tablet_pad_strip_v2_source source;
|
||||
gboolean source_known = FALSE;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
if (wl_list_empty (focus_resources))
|
||||
return FALSE;
|
||||
if (event->type != CLUTTER_PAD_STRIP)
|
||||
return FALSE;
|
||||
@@ -149,7 +135,7 @@ meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip,
|
||||
source_known = TRUE;
|
||||
}
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, focus_resources)
|
||||
{
|
||||
gdouble value = event->pad_strip.value;
|
||||
|
||||
@@ -194,11 +180,9 @@ move_resources_for_client (struct wl_list *destination,
|
||||
void
|
||||
meta_wayland_tablet_pad_strip_sync_focus (MetaWaylandTabletPadStrip *strip)
|
||||
{
|
||||
struct wl_list *l = &strip->focus_resource_list;
|
||||
|
||||
g_clear_pointer (&strip->feedback, g_free);
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&strip->focus_resource_list))
|
||||
{
|
||||
move_resources (&strip->resource_list, &strip->focus_resource_list);
|
||||
}
|
||||
|
||||
@@ -49,11 +49,8 @@ void meta_wayland_tablet_pad_strip_set_group (MetaWayland
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_create_new_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client,
|
||||
struct wl_resource *pad_resource,
|
||||
struct wl_resource *group_resource,
|
||||
uint32_t id);
|
||||
struct wl_resource *
|
||||
meta_wayland_tablet_pad_strip_lookup_resource (MetaWaylandTabletPadStrip *strip,
|
||||
struct wl_client *client);
|
||||
|
||||
gboolean meta_wayland_tablet_pad_strip_handle_event (MetaWaylandTabletPadStrip *strip,
|
||||
const ClutterEvent *event);
|
||||
|
||||
@@ -95,13 +95,12 @@ group_rings_strips (MetaWaylandTabletPad *pad)
|
||||
meta_wayland_tablet_pad_ring_set_group (ring, group);
|
||||
}
|
||||
else
|
||||
#else
|
||||
#endif
|
||||
{
|
||||
/* Assign everything to the first group */
|
||||
if (n_group == 0)
|
||||
meta_wayland_tablet_pad_ring_set_group (ring, group);
|
||||
}
|
||||
#endif
|
||||
n_elem++;
|
||||
}
|
||||
|
||||
@@ -116,13 +115,13 @@ group_rings_strips (MetaWaylandTabletPad *pad)
|
||||
meta_wayland_tablet_pad_strip_set_group (strip, group);
|
||||
}
|
||||
else
|
||||
#else
|
||||
#endif
|
||||
{
|
||||
/* Assign everything to the first group */
|
||||
if (n_group == 0)
|
||||
meta_wayland_tablet_pad_strip_set_group (strip, group);
|
||||
}
|
||||
#endif
|
||||
|
||||
n_elem++;
|
||||
}
|
||||
|
||||
@@ -196,7 +195,6 @@ void
|
||||
meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad)
|
||||
{
|
||||
struct wl_resource *resource, *next;
|
||||
GList *l;
|
||||
|
||||
meta_wayland_tablet_pad_set_focus (pad, NULL);
|
||||
|
||||
@@ -207,16 +205,13 @@ meta_wayland_tablet_pad_free (MetaWaylandTabletPad *pad)
|
||||
wl_list_init (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
for (l = pad->groups; l; l = l->next)
|
||||
meta_wayland_tablet_pad_group_free (l->data);
|
||||
for (l = pad->rings; l; l = l->next)
|
||||
meta_wayland_tablet_pad_ring_free (l->data);
|
||||
for (l = pad->strips; l; l = l->next)
|
||||
meta_wayland_tablet_pad_strip_free (l->data);
|
||||
g_list_free_full (pad->groups,
|
||||
(GDestroyNotify) meta_wayland_tablet_pad_group_free);
|
||||
g_list_free_full (pad->rings,
|
||||
(GDestroyNotify) meta_wayland_tablet_pad_ring_free);
|
||||
g_list_free_full (pad->strips,
|
||||
(GDestroyNotify) meta_wayland_tablet_pad_strip_free);
|
||||
|
||||
g_list_free (pad->groups);
|
||||
g_list_free (pad->rings);
|
||||
g_list_free (pad->strips);
|
||||
g_hash_table_destroy (pad->feedback);
|
||||
|
||||
g_slice_free (MetaWaylandTabletPad, pad);
|
||||
@@ -253,7 +248,7 @@ tablet_pad_set_feedback (struct wl_client *client,
|
||||
if (!group || group->mode_switch_serial != serial)
|
||||
return;
|
||||
|
||||
input_settings = meta_input_settings_get ();
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, pad->device, button))
|
||||
@@ -340,10 +335,10 @@ handle_pad_button_event (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
enum zwp_tablet_pad_v2_button_state button_state;
|
||||
struct wl_list *l = &pad->focus_resource_list;
|
||||
struct wl_list *focus_resources = &pad->focus_resource_list;
|
||||
struct wl_resource *resource;
|
||||
|
||||
if (wl_list_empty (l))
|
||||
if (wl_list_empty (focus_resources))
|
||||
return FALSE;
|
||||
|
||||
if (event->type == CLUTTER_PAD_BUTTON_PRESS)
|
||||
@@ -353,7 +348,7 @@ handle_pad_button_event (MetaWaylandTabletPad *pad,
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, focus_resources)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_button (resource,
|
||||
clutter_event_get_time (event),
|
||||
@@ -373,7 +368,7 @@ meta_wayland_tablet_pad_update_action (MetaWaylandTabletPad *pad,
|
||||
|
||||
button = event->pad_button.button;
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_input_settings_get ();
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (!input_settings)
|
||||
return;
|
||||
@@ -391,7 +386,7 @@ meta_wayland_tablet_pad_handle_event_action (MetaWaylandTabletPad *pad,
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_input_settings_get ();
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, device,
|
||||
@@ -467,6 +462,40 @@ meta_wayland_tablet_pad_update_groups_focus (MetaWaylandTabletPad *pad)
|
||||
meta_wayland_tablet_pad_group_sync_focus (l->data);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_broadcast_enter (MetaWaylandTabletPad *pad,
|
||||
uint32_t serial,
|
||||
MetaWaylandTablet *tablet,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_resource *resource, *tablet_resource;
|
||||
struct wl_client *client;
|
||||
|
||||
client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
tablet_resource = meta_wayland_tablet_lookup_resource (tablet, client);
|
||||
|
||||
wl_resource_for_each (resource, &pad->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_enter (resource, serial,
|
||||
tablet_resource,
|
||||
surface->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_broadcast_leave (MetaWaylandTabletPad *pad,
|
||||
uint32_t serial,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, &pad->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_leave (resource, serial,
|
||||
surface->resource);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
|
||||
MetaWaylandSurface *surface)
|
||||
@@ -480,20 +509,16 @@ meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
|
||||
|
||||
if (pad->focus_surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l = &pad->focus_resource_list;
|
||||
struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
struct wl_list *focus_resources = &pad->focus_resource_list;
|
||||
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (focus_resources))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_leave (resource, serial, pad->focus_surface->resource);
|
||||
}
|
||||
|
||||
meta_wayland_tablet_pad_broadcast_leave (pad, serial,
|
||||
pad->focus_surface);
|
||||
move_resources (&pad->resource_list, &pad->focus_resource_list);
|
||||
}
|
||||
|
||||
@@ -501,36 +526,28 @@ meta_wayland_tablet_pad_set_focus (MetaWaylandTabletPad *pad,
|
||||
pad->focus_surface = NULL;
|
||||
}
|
||||
|
||||
tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat, pad);
|
||||
tablet = meta_wayland_tablet_seat_lookup_paired_tablet (pad->tablet_seat,
|
||||
pad);
|
||||
|
||||
if (tablet != NULL && surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
struct wl_client *client;
|
||||
|
||||
pad->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (pad->focus_surface->resource, &pad->focus_surface_listener);
|
||||
wl_resource_add_destroy_listener (pad->focus_surface->resource,
|
||||
&pad->focus_surface_listener);
|
||||
|
||||
client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
move_resources_for_client (&pad->focus_resource_list,
|
||||
&pad->resource_list,
|
||||
wl_resource_get_client (pad->focus_surface->resource));
|
||||
&pad->resource_list, client);
|
||||
|
||||
l = &pad->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&pad->focus_resource_list))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pad->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
struct wl_resource *tablet_resource =
|
||||
meta_wayland_tablet_lookup_resource (tablet, client);
|
||||
|
||||
pad->focus_serial = wl_display_next_serial (display);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
{
|
||||
zwp_tablet_pad_v2_send_enter (resource, pad->focus_serial,
|
||||
tablet_resource,
|
||||
pad->focus_surface->resource);
|
||||
}
|
||||
meta_wayland_tablet_pad_broadcast_enter (pad, pad->focus_serial,
|
||||
tablet, pad->focus_surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user