Compare commits
103 Commits
citadel
...
wip/carlos
Author | SHA1 | Date | |
---|---|---|---|
![]() |
208e292df1 | ||
![]() |
548e5138fc | ||
![]() |
6b8d95d9c4 | ||
![]() |
faec8d29b0 | ||
![]() |
4b88a769d2 | ||
![]() |
6704e986a0 | ||
![]() |
d55b44df50 | ||
![]() |
6496cd7c55 | ||
![]() |
6f3ce4de24 | ||
![]() |
034aff4306 | ||
![]() |
af5f93377a | ||
![]() |
abd858fb69 | ||
![]() |
09e02a772e | ||
![]() |
c850aa9733 | ||
![]() |
5a1c7e4a54 | ||
![]() |
e324f0fad0 | ||
![]() |
5978531963 | ||
![]() |
bc111bf958 | ||
![]() |
074d78bd9b | ||
![]() |
2e604709df | ||
![]() |
6c265c131f | ||
![]() |
06adde5c6b | ||
![]() |
a2616d83e8 | ||
![]() |
92bc79fd51 | ||
![]() |
ef67fab737 | ||
![]() |
9acb7f0eed | ||
![]() |
c678cdab5a | ||
![]() |
91f6b3b5bc | ||
![]() |
696915a951 | ||
![]() |
2e07c55241 | ||
![]() |
0f0848191e | ||
![]() |
4b0d3f44e1 | ||
![]() |
4f794d3acb | ||
![]() |
3252ef5dd7 | ||
![]() |
0c9bbbe90e | ||
![]() |
bb62d9e4b0 | ||
![]() |
579220a762 | ||
![]() |
575a4ca281 | ||
![]() |
4b7f2905d6 | ||
![]() |
c7758046eb | ||
![]() |
e64112de64 | ||
![]() |
05f385c8ee | ||
![]() |
8a2b529ca3 | ||
![]() |
0c92417178 | ||
![]() |
543d232b51 | ||
![]() |
4398d63566 | ||
![]() |
dc022a67b0 | ||
![]() |
60fa895ae3 | ||
![]() |
7bb3fe25aa | ||
![]() |
6c5bba94fd | ||
![]() |
667b2726f5 | ||
![]() |
1d3588ba48 | ||
![]() |
16317cec12 | ||
![]() |
f3991c0164 | ||
![]() |
b07d9c5f92 | ||
![]() |
be51a8c18c | ||
![]() |
11c86f9cb3 | ||
![]() |
87c0821a30 | ||
![]() |
03f2bade19 | ||
![]() |
a3825f2085 | ||
![]() |
8b2a89041a | ||
![]() |
52da5fe4f2 | ||
![]() |
307be1e495 | ||
![]() |
9b3ca86b7c | ||
![]() |
da55f15156 | ||
![]() |
b13fe4895f | ||
![]() |
aae4a6065c | ||
![]() |
1555ecad11 | ||
![]() |
292b4dd605 | ||
![]() |
4766e2f858 | ||
![]() |
e3fe8c3dd1 | ||
![]() |
d3e1ce7dbc | ||
![]() |
63ad2c958d | ||
![]() |
849cc3d7f5 | ||
![]() |
8d8c933eb4 | ||
![]() |
2363f4c30b | ||
![]() |
5d45722362 | ||
![]() |
cef6520836 | ||
![]() |
0fbbeb0c82 | ||
![]() |
b97519bb6e | ||
![]() |
60b3f628a6 | ||
![]() |
37deba9557 | ||
![]() |
89cefd037f | ||
![]() |
c9efadacd1 | ||
![]() |
df724f5c75 | ||
![]() |
44bb21c7aa | ||
![]() |
73e705a49b | ||
![]() |
2316dfe394 | ||
![]() |
9597b5a703 | ||
![]() |
0be0a14225 | ||
![]() |
7fafec21b6 | ||
![]() |
88f03d3a26 | ||
![]() |
edc399e5cf | ||
![]() |
908a331fa8 | ||
![]() |
3083e98254 | ||
![]() |
7dc1a28c8c | ||
![]() |
3ce5b34ade | ||
![]() |
5677fbb64d | ||
![]() |
e7f29e764f | ||
![]() |
5563bfe7d9 | ||
![]() |
cd00e69ce3 | ||
![]() |
fe1d297680 | ||
![]() |
67a31633d8 |
@ -12715,6 +12715,9 @@ clutter_actor_event (ClutterActor *actor,
|
||||
signal_num = -1;
|
||||
detail = quark_stage;
|
||||
break;
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
case CLUTTER_EVENT_LAST: /* Just keep compiler warnings quiet */
|
||||
break;
|
||||
}
|
||||
|
@ -387,44 +387,6 @@ typedef enum
|
||||
CLUTTER_MODIFIER_MASK = 0x5c001fff
|
||||
} ClutterModifierType;
|
||||
|
||||
/**
|
||||
* ClutterKeyboardA11yFlags:
|
||||
* @CLUTTER_A11Y_KEYBOARD_ENABLED:
|
||||
* @CLUTTER_A11Y_TIMEOUT_ENABLED:
|
||||
* @CLUTTER_A11Y_MOUSE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_TOGGLE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_BEEP:
|
||||
* @CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP:
|
||||
*
|
||||
* Keyboard accessibility features applied to a ClutterInputDevice keyboard.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_A11Y_KEYBOARD_ENABLED = 1 << 0,
|
||||
CLUTTER_A11Y_TIMEOUT_ENABLED = 1 << 1,
|
||||
CLUTTER_A11Y_MOUSE_KEYS_ENABLED = 1 << 2,
|
||||
CLUTTER_A11Y_SLOW_KEYS_ENABLED = 1 << 3,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS = 1 << 4,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT = 1 << 5,
|
||||
CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT = 1 << 6,
|
||||
CLUTTER_A11Y_BOUNCE_KEYS_ENABLED = 1 << 7,
|
||||
CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT = 1 << 8,
|
||||
CLUTTER_A11Y_TOGGLE_KEYS_ENABLED = 1 << 9,
|
||||
CLUTTER_A11Y_STICKY_KEYS_ENABLED = 1 << 10,
|
||||
CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF = 1 << 11,
|
||||
CLUTTER_A11Y_STICKY_KEYS_BEEP = 1 << 12,
|
||||
CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13,
|
||||
} ClutterKeyboardA11yFlags;
|
||||
|
||||
/**
|
||||
* ClutterPointerA11yFlags:
|
||||
* @CLUTTER_A11Y_POINTER_ENABLED:
|
||||
@ -906,6 +868,8 @@ typedef enum /*< prefix=CLUTTER >*/
|
||||
CLUTTER_PAD_BUTTON_RELEASE,
|
||||
CLUTTER_PAD_STRIP,
|
||||
CLUTTER_PAD_RING,
|
||||
CLUTTER_DEVICE_ADDED,
|
||||
CLUTTER_DEVICE_REMOVED,
|
||||
|
||||
CLUTTER_EVENT_LAST /* helper */
|
||||
} ClutterEventType;
|
||||
@ -1630,12 +1594,6 @@ typedef enum
|
||||
CLUTTER_INPUT_DEVICE_PAD_SOURCE_FINGER,
|
||||
} ClutterInputDevicePadSource;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
|
||||
} ClutterInputDeviceMapping;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_INPUT_CONTENT_HINT_COMPLETION = 1 << 0,
|
||||
|
@ -414,6 +414,8 @@ clutter_event_get_position (const ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
graphene_point_init (position, 0.f, 0.f);
|
||||
break;
|
||||
|
||||
@ -487,6 +489,8 @@ clutter_event_set_coords (ClutterEvent *event,
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
|
||||
case CLUTTER_ENTER:
|
||||
@ -1158,6 +1162,11 @@ clutter_event_set_device (ClutterEvent *event,
|
||||
case CLUTTER_PAD_RING:
|
||||
event->pad_ring.device = device;
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
event->device.device = device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1254,6 +1263,11 @@ clutter_event_get_device (const ClutterEvent *event)
|
||||
case CLUTTER_PAD_RING:
|
||||
device = event->pad_ring.device;
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
device = event->device.device;
|
||||
break;
|
||||
}
|
||||
|
||||
return device;
|
||||
@ -1407,6 +1421,8 @@ clutter_event_copy (const ClutterEvent *event)
|
||||
sizeof (gdouble) * n_axes);
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1461,6 +1477,9 @@ clutter_event_free (ClutterEvent *event)
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
g_free (event->touch.axes);
|
||||
break;
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -1485,40 +1504,17 @@ ClutterEvent *
|
||||
clutter_event_get (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEvent *event;
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
return NULL;
|
||||
event = g_async_queue_try_pop (context->events_queue);
|
||||
|
||||
if (g_queue_is_empty (context->events_queue))
|
||||
return NULL;
|
||||
|
||||
return g_queue_pop_tail (context->events_queue);
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_peek:
|
||||
*
|
||||
* Returns a pointer to the first event from the event queue but
|
||||
* does not remove it.
|
||||
*
|
||||
* Return value: (transfer none): A #ClutterEvent or NULL if queue empty.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
ClutterEvent *
|
||||
clutter_event_peek (void)
|
||||
static gboolean
|
||||
spin_context (gpointer data)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
|
||||
g_return_val_if_fail (context != NULL, NULL);
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
return NULL;
|
||||
|
||||
if (g_queue_is_empty (context->events_queue))
|
||||
return NULL;
|
||||
|
||||
return g_queue_peek_tail (context->events_queue);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1526,21 +1522,9 @@ _clutter_event_push (const ClutterEvent *event,
|
||||
gboolean do_copy)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_assert (context != NULL);
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
context->events_queue = g_queue_new ();
|
||||
|
||||
/* disabled devices don't propagate events */
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL)
|
||||
{
|
||||
if (!clutter_input_device_get_enabled (device))
|
||||
return;
|
||||
}
|
||||
|
||||
if (do_copy)
|
||||
{
|
||||
ClutterEvent *copy;
|
||||
@ -1549,7 +1533,8 @@ _clutter_event_push (const ClutterEvent *event,
|
||||
event = copy;
|
||||
}
|
||||
|
||||
g_queue_push_head (context->events_queue, (gpointer) event);
|
||||
g_async_queue_push (context->events_queue, (gpointer) event);
|
||||
g_idle_add (spin_context, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1586,10 +1571,7 @@ clutter_events_pending (void)
|
||||
|
||||
g_return_val_if_fail (context != NULL, FALSE);
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
return FALSE;
|
||||
|
||||
return g_queue_is_empty (context->events_queue) == FALSE;
|
||||
return g_async_queue_length (context->events_queue) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1728,6 +1710,8 @@ clutter_event_get_axes (const ClutterEvent *event,
|
||||
case CLUTTER_EVENT_LAST:
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
case CLUTTER_PROXIMITY_OUT:
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
|
@ -121,6 +121,7 @@ typedef struct _ClutterProximityEvent ClutterProximityEvent;
|
||||
typedef struct _ClutterPadButtonEvent ClutterPadButtonEvent;
|
||||
typedef struct _ClutterPadStripEvent ClutterPadStripEvent;
|
||||
typedef struct _ClutterPadRingEvent ClutterPadRingEvent;
|
||||
typedef struct _ClutterDeviceEvent ClutterDeviceEvent;
|
||||
|
||||
/**
|
||||
* ClutterAnyEvent:
|
||||
@ -544,6 +545,17 @@ struct _ClutterPadRingEvent
|
||||
guint32 mode;
|
||||
};
|
||||
|
||||
struct _ClutterDeviceEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterEvent:
|
||||
*
|
||||
@ -570,6 +582,7 @@ union _ClutterEvent
|
||||
ClutterPadButtonEvent pad_button;
|
||||
ClutterPadStripEvent pad_strip;
|
||||
ClutterPadRingEvent pad_ring;
|
||||
ClutterDeviceEvent device;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -601,8 +614,6 @@ gboolean clutter_events_pending (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterEvent * clutter_event_get (void);
|
||||
CLUTTER_EXPORT
|
||||
ClutterEvent * clutter_event_peek (void);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_event_put (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
|
@ -61,15 +61,6 @@ typedef struct _ClutterScrollInfo
|
||||
guint last_value_valid : 1;
|
||||
} ClutterScrollInfo;
|
||||
|
||||
typedef struct _ClutterTouchInfo
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
ClutterActor *actor;
|
||||
|
||||
float current_x;
|
||||
float current_y;
|
||||
} ClutterTouchInfo;
|
||||
|
||||
typedef struct _ClutterPtrA11yData
|
||||
{
|
||||
int n_btn_pressed;
|
||||
@ -120,25 +111,18 @@ struct _ClutterInputDevice
|
||||
/* the current click count */
|
||||
int click_count;
|
||||
|
||||
/* the stage the device is on */
|
||||
ClutterStage *stage;
|
||||
|
||||
/* the current state */
|
||||
float current_x;
|
||||
float current_y;
|
||||
uint32_t current_time;
|
||||
int current_button_number;
|
||||
ClutterModifierType current_state;
|
||||
|
||||
/* the current touch points states */
|
||||
GHashTable *touch_sequences_info;
|
||||
/* the current touch points targets */
|
||||
GHashTable *touch_sequence_actors;
|
||||
|
||||
/* the previous state, used for click count generation */
|
||||
int previous_x;
|
||||
int previous_y;
|
||||
uint32_t previous_time;
|
||||
int previous_button_number;
|
||||
ClutterModifierType previous_state;
|
||||
|
||||
GArray *axes;
|
||||
|
||||
@ -157,8 +141,6 @@ struct _ClutterInputDevice
|
||||
int n_strips;
|
||||
int n_mode_groups;
|
||||
|
||||
ClutterInputDeviceMapping mapping_mode;
|
||||
|
||||
guint has_cursor : 1;
|
||||
guint is_enabled : 1;
|
||||
|
||||
@ -180,33 +162,11 @@ CLUTTER_EXPORT
|
||||
void clutter_input_device_update_from_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * _clutter_input_device_get_stage (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||
ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType state);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
guint32 time_);
|
||||
void _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterActor *actor,
|
||||
gboolean emit_crossing);
|
||||
CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_update (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gboolean emit_crossing);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_add_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event);
|
||||
ClutterStage *stage,
|
||||
gboolean emit_crossing,
|
||||
ClutterEvent *for_event);
|
||||
CLUTTER_EXPORT
|
||||
void _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event);
|
||||
@ -214,6 +174,12 @@ CLUTTER_EXPORT
|
||||
void _clutter_input_device_set_n_keys (ClutterInputDevice *device,
|
||||
guint n_keys);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
ClutterModifierType modifiers);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean _clutter_input_device_translate_axis (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
gdouble value,
|
||||
@ -252,4 +218,9 @@ ClutterInputDeviceTool *
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
|
||||
#endif /* CLUTTER_INPUT_DEVICE_PRIVATE_H */
|
||||
|
@ -61,7 +61,6 @@ enum
|
||||
PROP_DEVICE_MODE,
|
||||
|
||||
PROP_HAS_CURSOR,
|
||||
PROP_ENABLED,
|
||||
|
||||
PROP_N_AXES,
|
||||
|
||||
@ -72,12 +71,10 @@ enum
|
||||
PROP_N_RINGS,
|
||||
PROP_N_MODE_GROUPS,
|
||||
PROP_DEVICE_NODE,
|
||||
PROP_MAPPING_MODE,
|
||||
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static void _clutter_input_device_free_touch_info (gpointer data);
|
||||
static void on_cursor_actor_destroy (ClutterActor *actor,
|
||||
ClutterInputDevice *device);
|
||||
static void on_cursor_actor_reactive_changed (ClutterActor *actor,
|
||||
@ -114,7 +111,7 @@ clutter_input_device_dispose (GObject *gobject)
|
||||
g_clear_pointer (&device->axes, g_array_unref);
|
||||
g_clear_pointer (&device->keys, g_array_unref);
|
||||
g_clear_pointer (&device->scroll_info, g_array_unref);
|
||||
g_clear_pointer (&device->touch_sequences_info, g_hash_table_unref);
|
||||
g_clear_pointer (&device->touch_sequence_actors, g_hash_table_unref);
|
||||
|
||||
if (device->cursor_actor)
|
||||
{
|
||||
@ -191,10 +188,6 @@ clutter_input_device_set_property (GObject *gobject,
|
||||
self->has_cursor = g_value_get_boolean (value);
|
||||
break;
|
||||
|
||||
case PROP_ENABLED:
|
||||
clutter_input_device_set_enabled (self, g_value_get_boolean (value));
|
||||
break;
|
||||
|
||||
case PROP_VENDOR_ID:
|
||||
self->vendor_id = g_value_dup_string (value);
|
||||
break;
|
||||
@ -219,10 +212,6 @@ clutter_input_device_set_property (GObject *gobject,
|
||||
self->node_path = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_MAPPING_MODE:
|
||||
self->mapping_mode = g_value_get_enum (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@ -271,10 +260,6 @@ clutter_input_device_get_property (GObject *gobject,
|
||||
g_value_set_uint (value, clutter_input_device_get_n_axes (self));
|
||||
break;
|
||||
|
||||
case PROP_ENABLED:
|
||||
g_value_set_boolean (value, self->is_enabled);
|
||||
break;
|
||||
|
||||
case PROP_VENDOR_ID:
|
||||
g_value_set_string (value, self->vendor_id);
|
||||
break;
|
||||
@ -299,10 +284,6 @@ clutter_input_device_get_property (GObject *gobject,
|
||||
g_value_set_string (value, self->node_path);
|
||||
break;
|
||||
|
||||
case PROP_MAPPING_MODE:
|
||||
g_value_set_enum (value, self->mapping_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@ -402,25 +383,6 @@ clutter_input_device_class_init (ClutterInputDeviceClass *klass)
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
/**
|
||||
* ClutterInputDevice:enabled:
|
||||
*
|
||||
* Whether the device is enabled.
|
||||
*
|
||||
* A device with the #ClutterInputDevice:device-mode property set
|
||||
* to %CLUTTER_INPUT_MODE_MASTER cannot be disabled.
|
||||
*
|
||||
* A device must be enabled in order to receive events from it.
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
obj_props[PROP_ENABLED] =
|
||||
g_param_spec_boolean ("enabled",
|
||||
P_("Enabled"),
|
||||
P_("Whether the device is enabled"),
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
/**
|
||||
* ClutterInputDevice:n-axes:
|
||||
*
|
||||
@ -506,14 +468,6 @@ clutter_input_device_class_init (ClutterInputDeviceClass *klass)
|
||||
NULL,
|
||||
CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
obj_props[PROP_MAPPING_MODE] =
|
||||
g_param_spec_enum ("mapping-mode",
|
||||
P_("Device mapping mode"),
|
||||
P_("Device mapping mode"),
|
||||
CLUTTER_TYPE_INPUT_DEVICE_MAPPING,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
|
||||
gobject_class->dispose = clutter_input_device_dispose;
|
||||
gobject_class->set_property = clutter_input_device_set_property;
|
||||
gobject_class->get_property = clutter_input_device_get_property;
|
||||
@ -528,91 +482,15 @@ clutter_input_device_init (ClutterInputDevice *self)
|
||||
|
||||
self->click_count = 0;
|
||||
|
||||
self->current_time = self->previous_time = CLUTTER_CURRENT_TIME;
|
||||
self->current_x = self->previous_x = -1;
|
||||
self->current_y = self->previous_y = -1;
|
||||
self->previous_time = CLUTTER_CURRENT_TIME;
|
||||
self->previous_x = -1;
|
||||
self->previous_y = -1;
|
||||
self->current_button_number = self->previous_button_number = -1;
|
||||
self->current_state = self->previous_state = 0;
|
||||
|
||||
self->touch_sequences_info =
|
||||
g_hash_table_new_full (NULL, NULL,
|
||||
NULL, _clutter_input_device_free_touch_info);
|
||||
self->touch_sequence_actors = g_hash_table_new (NULL, NULL);
|
||||
self->inv_touch_sequence_actors = g_hash_table_new (NULL, NULL);
|
||||
}
|
||||
|
||||
static ClutterTouchInfo *
|
||||
_clutter_input_device_ensure_touch_info (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterTouchInfo *info;
|
||||
|
||||
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
|
||||
|
||||
if (info == NULL)
|
||||
{
|
||||
info = g_slice_new0 (ClutterTouchInfo);
|
||||
info->sequence = sequence;
|
||||
g_hash_table_insert (device->touch_sequences_info, sequence, info);
|
||||
|
||||
if (g_hash_table_size (device->touch_sequences_info) == 1)
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_set_coords:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @sequence: a #ClutterEventSequence or NULL
|
||||
* @x: X coordinate of the device
|
||||
* @y: Y coordinate of the device
|
||||
*
|
||||
* Stores the last known coordinates of the device
|
||||
*/
|
||||
void
|
||||
_clutter_input_device_set_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
if (sequence == NULL)
|
||||
{
|
||||
if (device->current_x != x)
|
||||
device->current_x = x;
|
||||
|
||||
if (device->current_y != y)
|
||||
device->current_y = y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterTouchInfo *info;
|
||||
info = _clutter_input_device_ensure_touch_info (device, sequence, stage);
|
||||
info->current_x = x;
|
||||
info->current_y = y;
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_set_state:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @state: a bitmask of modifiers
|
||||
*
|
||||
* Stores the last known modifiers state of the device
|
||||
*/
|
||||
void
|
||||
_clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType state)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device->current_state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_modifier_state:
|
||||
* @device: a #ClutterInputDevice
|
||||
@ -627,69 +505,17 @@ _clutter_input_device_set_state (ClutterInputDevice *device,
|
||||
ClutterModifierType
|
||||
clutter_input_device_get_modifier_state (ClutterInputDevice *device)
|
||||
{
|
||||
uint32_t modifiers;
|
||||
ClutterSeat *seat;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), 0);
|
||||
|
||||
return device->current_state;
|
||||
}
|
||||
seat = clutter_input_device_get_seat (device);
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_set_time:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @time_: the time
|
||||
*
|
||||
* Stores the last known event time of the device
|
||||
*/
|
||||
void
|
||||
_clutter_input_device_set_time (ClutterInputDevice *device,
|
||||
guint32 time_)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
if (!clutter_seat_query_state (seat, device, NULL, NULL, &modifiers))
|
||||
return 0;
|
||||
|
||||
if (device->current_time != time_)
|
||||
device->current_time = time_;
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_set_stage:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @stage: a #ClutterStage or %NULL
|
||||
*
|
||||
* Stores the stage under the device
|
||||
*/
|
||||
void
|
||||
_clutter_input_device_set_stage (ClutterInputDevice *device,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
if (device->stage == stage)
|
||||
return;
|
||||
|
||||
device->stage = stage;
|
||||
|
||||
/* we leave the ->cursor_actor in place in order to check
|
||||
* if we left the stage without crossing it again; this way
|
||||
* we can emit a leave event on the cursor actor right before
|
||||
* we emit the leave event on the stage.
|
||||
*/
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_get_stage:
|
||||
* @device: a #ClutterInputDevice
|
||||
*
|
||||
* Retrieves the stage currently associated with @device.
|
||||
*
|
||||
* Return value: The stage currently associated with @device.
|
||||
*/
|
||||
ClutterStage *
|
||||
_clutter_input_device_get_stage (ClutterInputDevice *device)
|
||||
{
|
||||
return device->stage;
|
||||
}
|
||||
|
||||
static void
|
||||
_clutter_input_device_free_touch_info (gpointer data)
|
||||
{
|
||||
g_slice_free (ClutterTouchInfo, data);
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -703,12 +529,8 @@ _clutter_input_device_associate_actor (ClutterInputDevice *device,
|
||||
{
|
||||
GList *sequences =
|
||||
g_hash_table_lookup (device->inv_touch_sequence_actors, actor);
|
||||
ClutterTouchInfo *info;
|
||||
ClutterStage *stage = CLUTTER_STAGE (clutter_actor_get_stage (actor));
|
||||
|
||||
info = _clutter_input_device_ensure_touch_info (device, sequence, stage);
|
||||
info->actor = actor;
|
||||
|
||||
g_hash_table_insert (device->touch_sequence_actors, sequence, actor);
|
||||
g_hash_table_insert (device->inv_touch_sequence_actors,
|
||||
actor, g_list_prepend (sequences, sequence));
|
||||
}
|
||||
@ -736,13 +558,7 @@ _clutter_input_device_unassociate_actor (ClutterInputDevice *device,
|
||||
actor);
|
||||
|
||||
for (l = sequences; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterTouchInfo *info =
|
||||
g_hash_table_lookup (device->touch_sequences_info, l->data);
|
||||
|
||||
if (info)
|
||||
info->actor = NULL;
|
||||
}
|
||||
g_hash_table_remove (device->touch_sequence_actors, l->data);
|
||||
|
||||
g_list_free (sequences);
|
||||
g_hash_table_remove (device->inv_touch_sequence_actors, actor);
|
||||
@ -795,17 +611,31 @@ on_cursor_actor_reactive_changed (ClutterActor *actor,
|
||||
* - set to %TRUE the :has-pointer property of the new pointer
|
||||
* actor
|
||||
*/
|
||||
void
|
||||
static void
|
||||
_clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
ClutterActor *actor,
|
||||
gboolean emit_crossing)
|
||||
gboolean emit_crossing,
|
||||
graphene_point_t coords,
|
||||
uint32_t time_)
|
||||
{
|
||||
ClutterActor *old_actor = clutter_input_device_get_actor (device, sequence);
|
||||
ClutterStage *stage = NULL;
|
||||
|
||||
if (old_actor == actor)
|
||||
return;
|
||||
|
||||
if (emit_crossing)
|
||||
{
|
||||
if (actor)
|
||||
stage = CLUTTER_STAGE (clutter_actor_get_stage (actor));
|
||||
else if (old_actor)
|
||||
stage = CLUTTER_STAGE (clutter_actor_get_stage (old_actor));
|
||||
|
||||
if (!stage)
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_actor != NULL)
|
||||
{
|
||||
ClutterActor *tmp_old_actor;
|
||||
@ -815,12 +645,12 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterEvent *event;
|
||||
|
||||
event = clutter_event_new (CLUTTER_LEAVE);
|
||||
event->crossing.time = device->current_time;
|
||||
event->crossing.time = time_;
|
||||
event->crossing.flags = 0;
|
||||
event->crossing.stage = device->stage;
|
||||
event->crossing.stage = stage;
|
||||
event->crossing.source = old_actor;
|
||||
event->crossing.x = device->current_x;
|
||||
event->crossing.y = device->current_y;
|
||||
event->crossing.x = coords.x;
|
||||
event->crossing.y = coords.y;
|
||||
event->crossing.related = actor;
|
||||
event->crossing.sequence = sequence;
|
||||
clutter_event_set_device (event, device);
|
||||
@ -852,11 +682,11 @@ _clutter_input_device_set_actor (ClutterInputDevice *device,
|
||||
ClutterEvent *event;
|
||||
|
||||
event = clutter_event_new (CLUTTER_ENTER);
|
||||
event->crossing.time = device->current_time;
|
||||
event->crossing.time = time_;
|
||||
event->crossing.flags = 0;
|
||||
event->crossing.stage = device->stage;
|
||||
event->crossing.x = device->current_x;
|
||||
event->crossing.y = device->current_y;
|
||||
event->crossing.stage = stage;
|
||||
event->crossing.x = coords.x;
|
||||
event->crossing.y = coords.y;
|
||||
event->crossing.source = actor;
|
||||
event->crossing.related = old_actor;
|
||||
event->crossing.sequence = sequence;
|
||||
@ -907,56 +737,6 @@ clutter_input_device_get_device_id (ClutterInputDevice *device)
|
||||
return device->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_set_enabled:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @enabled: %TRUE to enable the @device
|
||||
*
|
||||
* Enables or disables a #ClutterInputDevice.
|
||||
*
|
||||
* Only devices with a #ClutterInputDevice:device-mode property set
|
||||
* to %CLUTTER_INPUT_MODE_SLAVE or %CLUTTER_INPUT_MODE_FLOATING can
|
||||
* be disabled.
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
void
|
||||
clutter_input_device_set_enabled (ClutterInputDevice *device,
|
||||
gboolean enabled)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
enabled = !!enabled;
|
||||
|
||||
if (!enabled && device->device_mode == CLUTTER_INPUT_MODE_MASTER)
|
||||
return;
|
||||
|
||||
if (device->is_enabled == enabled)
|
||||
return;
|
||||
|
||||
device->is_enabled = enabled;
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (device), obj_props[PROP_ENABLED]);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_enabled:
|
||||
* @device: a #ClutterInputDevice
|
||||
*
|
||||
* Retrieves whether @device is enabled.
|
||||
*
|
||||
* Return value: %TRUE if the device is enabled
|
||||
*
|
||||
* Since: 1.6
|
||||
*/
|
||||
gboolean
|
||||
clutter_input_device_get_enabled (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
|
||||
|
||||
return device->is_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_coords:
|
||||
* @device: a #ClutterInputDevice
|
||||
@ -978,27 +758,14 @@ clutter_input_device_get_coords (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *point)
|
||||
{
|
||||
ClutterSeat *seat;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
|
||||
g_return_val_if_fail (point != NULL, FALSE);
|
||||
|
||||
if (sequence == NULL)
|
||||
{
|
||||
point->x = device->current_x;
|
||||
point->y = device->current_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterTouchInfo *info =
|
||||
g_hash_table_lookup (device->touch_sequences_info, sequence);
|
||||
seat = clutter_input_device_get_seat (device);
|
||||
|
||||
if (info == NULL)
|
||||
return FALSE;
|
||||
|
||||
point->x = info->current_x;
|
||||
point->y = info->current_y;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return clutter_seat_query_state (seat, device, sequence, point, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1018,27 +785,29 @@ clutter_input_device_get_coords (ClutterInputDevice *device,
|
||||
ClutterActor *
|
||||
clutter_input_device_update (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
gboolean emit_crossing)
|
||||
ClutterStage *stage,
|
||||
gboolean emit_crossing,
|
||||
ClutterEvent *for_event)
|
||||
{
|
||||
ClutterStage *stage;
|
||||
ClutterActor *new_cursor_actor;
|
||||
ClutterActor *old_cursor_actor;
|
||||
graphene_point_t point = GRAPHENE_POINT_INIT (-1.0f, -1.0f);
|
||||
ClutterInputDeviceType device_type = device->device_type;
|
||||
uint32_t time_;
|
||||
|
||||
g_assert (device_type != CLUTTER_KEYBOARD_DEVICE &&
|
||||
device_type != CLUTTER_PAD_DEVICE);
|
||||
|
||||
stage = device->stage;
|
||||
if (G_UNLIKELY (stage == NULL))
|
||||
if (for_event)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No stage defined for device %d '%s'",
|
||||
clutter_input_device_get_device_id (device),
|
||||
clutter_input_device_get_device_name (device));
|
||||
return NULL;
|
||||
clutter_event_get_coords (for_event, &point.x, &point.y);
|
||||
time_ = clutter_event_get_time (for_event);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
clutter_input_device_get_coords (device, sequence, &point);
|
||||
time_ = CLUTTER_CURRENT_TIME;
|
||||
}
|
||||
|
||||
old_cursor_actor = clutter_input_device_get_actor (device, sequence);
|
||||
new_cursor_actor =
|
||||
@ -1065,7 +834,8 @@ clutter_input_device_update (ClutterInputDevice *device,
|
||||
|
||||
_clutter_input_device_set_actor (device, sequence,
|
||||
new_cursor_actor,
|
||||
emit_crossing);
|
||||
emit_crossing,
|
||||
point, time_);
|
||||
|
||||
return new_cursor_actor;
|
||||
}
|
||||
@ -1086,37 +856,12 @@ ClutterActor *
|
||||
clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
ClutterTouchInfo *info;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
if (sequence == NULL)
|
||||
return device->cursor_actor;
|
||||
|
||||
info = g_hash_table_lookup (device->touch_sequences_info, sequence);
|
||||
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
|
||||
return info->actor;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_get_pointer_stage:
|
||||
* @device: a #ClutterInputDevice of type %CLUTTER_POINTER_DEVICE
|
||||
*
|
||||
* Retrieves the #ClutterStage underneath the pointer of @device
|
||||
*
|
||||
* Return value: (transfer none): a pointer to the #ClutterStage or %NULL
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterStage *
|
||||
clutter_input_device_get_pointer_stage (ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (device->device_type == CLUTTER_POINTER_DEVICE, NULL);
|
||||
|
||||
return device->stage;
|
||||
return g_hash_table_lookup (device->touch_sequence_actors, sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1177,95 +922,6 @@ clutter_input_device_get_device_mode (ClutterInputDevice *device)
|
||||
return device->device_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_input_device_update_from_event:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @event: a #ClutterEvent
|
||||
* @update_stage: whether to update the #ClutterStage of the @device
|
||||
* using the stage of the event
|
||||
*
|
||||
* Forcibly updates the state of the @device using a #ClutterEvent
|
||||
*
|
||||
* This function should never be used by applications: it is meant
|
||||
* for integration with embedding toolkits, like clutter-gtk
|
||||
*
|
||||
* Embedding toolkits that disable the event collection inside Clutter
|
||||
* need to use this function to update the state of input devices depending
|
||||
* on a #ClutterEvent that they are going to submit to the event handling code
|
||||
* in Clutter though clutter_do_event(). Since the input devices hold the state
|
||||
* that is going to be used to fill in fields like the #ClutterButtonEvent
|
||||
* click count, or to emit synthesized events like %CLUTTER_ENTER and
|
||||
* %CLUTTER_LEAVE, it is necessary for embedding toolkits to also be
|
||||
* responsible of updating the input device state.
|
||||
*
|
||||
* For instance, this might be the code to translate an embedding toolkit
|
||||
* native motion notification into a Clutter #ClutterMotionEvent and ask
|
||||
* Clutter to process it:
|
||||
*
|
||||
* |[
|
||||
* ClutterEvent c_event;
|
||||
*
|
||||
* translate_native_event_to_clutter (native_event, &c_event);
|
||||
*
|
||||
* clutter_do_event (&c_event);
|
||||
* ]|
|
||||
*
|
||||
* Before letting clutter_do_event() process the event, it is necessary to call
|
||||
* clutter_input_device_update_from_event():
|
||||
*
|
||||
* |[
|
||||
* ClutterEvent c_event;
|
||||
* ClutterDeviceManager *manager;
|
||||
* ClutterInputDevice *device;
|
||||
*
|
||||
* translate_native_event_to_clutter (native_event, &c_event);
|
||||
*
|
||||
* // get the seat
|
||||
* seat = clutter_backend_get_deafult_seat (clutter_get_default_backend ());
|
||||
*
|
||||
* // use the default Core Pointer that Clutter backends register by default
|
||||
* device = clutter_seat_get_pointer (seat);
|
||||
*
|
||||
* // update the state of the input device
|
||||
* clutter_input_device_update_from_event (device, &c_event, FALSE);
|
||||
*
|
||||
* clutter_do_event (&c_event);
|
||||
* ]|
|
||||
*
|
||||
* The @update_stage boolean argument should be used when the input device
|
||||
* enters and leaves a #ClutterStage; it will use the #ClutterStage field
|
||||
* of the passed @event to update the stage associated to the input device.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_input_device_update_from_event (ClutterInputDevice *device,
|
||||
ClutterEvent *event,
|
||||
gboolean update_stage)
|
||||
{
|
||||
ClutterModifierType event_state;
|
||||
ClutterEventSequence *sequence;
|
||||
ClutterStage *event_stage;
|
||||
gfloat event_x, event_y;
|
||||
guint32 event_time;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
event_state = clutter_event_get_state (event);
|
||||
event_time = clutter_event_get_time (event);
|
||||
event_stage = clutter_event_get_stage (event);
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
|
||||
_clutter_input_device_set_coords (device, sequence, event_x, event_y, event_stage);
|
||||
_clutter_input_device_set_state (device, event_state);
|
||||
_clutter_input_device_set_time (device, event_time);
|
||||
|
||||
if (update_stage)
|
||||
_clutter_input_device_set_stage (device, event_stage);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_reset_axes:
|
||||
* @device: a #ClutterInputDevice
|
||||
@ -1646,31 +1302,6 @@ _clutter_input_device_remove_slave (ClutterInputDevice *master,
|
||||
master->slaves = g_list_remove (master->slaves, slave);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_add_sequence:
|
||||
* @device: a #ClutterInputDevice
|
||||
* @sequence: a #ClutterEventSequence
|
||||
*
|
||||
* Start tracking informations related to a touch point (position,
|
||||
* actor underneath the touch point).
|
||||
*/
|
||||
void
|
||||
_clutter_input_device_add_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
ClutterStage *stage;
|
||||
|
||||
if (sequence == NULL)
|
||||
return;
|
||||
|
||||
stage = clutter_event_get_stage (event);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
_clutter_input_device_ensure_touch_info (device, sequence, stage);
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* clutter_input_device_remove_sequence:
|
||||
* @device: a #ClutterInputDevice
|
||||
@ -1683,25 +1314,25 @@ _clutter_input_device_remove_event_sequence (ClutterInputDevice *device,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
ClutterTouchInfo *info =
|
||||
g_hash_table_lookup (device->touch_sequences_info, sequence);
|
||||
ClutterActor *actor =
|
||||
g_hash_table_lookup (device->touch_sequence_actors, sequence);
|
||||
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
if (info->actor != NULL)
|
||||
if (actor != NULL)
|
||||
{
|
||||
GList *sequences =
|
||||
g_hash_table_lookup (device->inv_touch_sequence_actors, info->actor);
|
||||
g_hash_table_lookup (device->inv_touch_sequence_actors, actor);
|
||||
graphene_point_t point;
|
||||
|
||||
sequences = g_list_remove (sequences, sequence);
|
||||
|
||||
g_hash_table_replace (device->inv_touch_sequence_actors,
|
||||
info->actor, sequences);
|
||||
_clutter_input_device_set_actor (device, sequence, NULL, TRUE);
|
||||
actor, sequences);
|
||||
clutter_event_get_coords (event, &point.x, &point.y);
|
||||
_clutter_input_device_set_actor (device, sequence, NULL, TRUE, point,
|
||||
clutter_event_get_time (event));
|
||||
}
|
||||
|
||||
g_hash_table_remove (device->touch_sequences_info, sequence);
|
||||
g_hash_table_remove (device->touch_sequence_actors, sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2391,43 +2022,6 @@ clutter_input_device_get_device_node (ClutterInputDevice *device)
|
||||
return device->node_path;
|
||||
}
|
||||
|
||||
ClutterInputDeviceMapping
|
||||
clutter_input_device_get_mapping_mode (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
g_return_val_if_fail (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE,
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
|
||||
return device->mapping_mode;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
g_return_if_fail (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE);
|
||||
|
||||
if (device->mapping_mode == mapping)
|
||||
return;
|
||||
|
||||
device->mapping_mode = mapping;
|
||||
g_object_notify (G_OBJECT (device), "mapping-mode");
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_input_device_is_grouped (ClutterInputDevice *device,
|
||||
ClutterInputDevice *other_device)
|
||||
|
@ -95,18 +95,11 @@ CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_get_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
CLUTTER_EXPORT
|
||||
ClutterStage * clutter_input_device_get_pointer_stage (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_device_name (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputMode clutter_input_device_get_device_mode (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_has_cursor (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_enabled (ClutterInputDevice *device,
|
||||
gboolean enabled);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_enabled (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_axes (ClutterInputDevice *device);
|
||||
@ -122,11 +115,6 @@ gboolean clutter_input_device_get_axis_value (ClutterInputDev
|
||||
CLUTTER_EXPORT
|
||||
guint clutter_input_device_get_n_keys (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint keyval,
|
||||
ClutterModifierType modifiers);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_get_key (ClutterInputDevice *device,
|
||||
guint index_,
|
||||
guint *keyval,
|
||||
@ -137,11 +125,6 @@ ClutterInputDevice * clutter_input_device_get_associated_device (ClutterInput
|
||||
CLUTTER_EXPORT
|
||||
GList * clutter_input_device_get_slave_devices (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_update_from_event (ClutterInputDevice *device,
|
||||
ClutterEvent *event,
|
||||
gboolean update_stage);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_grab (ClutterInputDevice *device,
|
||||
ClutterActor *actor);
|
||||
@ -161,11 +144,6 @@ CLUTTER_EXPORT
|
||||
ClutterActor * clutter_input_device_sequence_get_grabbed_actor (ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_keycode_to_evdev (ClutterInputDevice *device,
|
||||
guint hardware_keycode,
|
||||
guint *evdev_keycode);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_vendor_id (ClutterInputDevice *device);
|
||||
CLUTTER_EXPORT
|
||||
@ -193,12 +171,6 @@ gint clutter_input_device_get_mode_switch_button_group (Clutt
|
||||
CLUTTER_EXPORT
|
||||
const gchar * clutter_input_device_get_device_node (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
ClutterInputDeviceMapping clutter_input_device_get_mapping_mode (ClutterInputDevice *device);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_input_device_is_grouped (ClutterInputDevice *device,
|
||||
ClutterInputDevice *other_device);
|
||||
|
@ -454,6 +454,7 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
ClutterInputMethodPrivate *priv;
|
||||
ClutterInputDevice *keyboard;
|
||||
ClutterSeat *seat;
|
||||
ClutterStageManager *stage_manager;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event;
|
||||
|
||||
@ -464,10 +465,9 @@ clutter_input_method_forward_key (ClutterInputMethod *im,
|
||||
return;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
stage_manager = clutter_stage_manager_get_default ();
|
||||
stage = clutter_stage_manager_get_default_stage (stage_manager);
|
||||
keyboard = clutter_seat_get_keyboard (seat);
|
||||
stage = _clutter_input_device_get_stage (keyboard);
|
||||
if (stage == NULL)
|
||||
return;
|
||||
|
||||
event = clutter_event_new (press ? CLUTTER_KEY_PRESS : CLUTTER_KEY_RELEASE);
|
||||
event->key.time = time_;
|
||||
|
@ -697,6 +697,8 @@ _clutter_context_get_default (void)
|
||||
ctx->settings = clutter_settings_get_default ();
|
||||
_clutter_settings_set_backend (ctx->settings, ctx->backend);
|
||||
|
||||
ctx->events_queue = g_async_queue_new ();
|
||||
|
||||
ctx->last_repaint_id = 1;
|
||||
}
|
||||
|
||||
@ -1621,7 +1623,9 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
|
||||
emit_crossing_event (event, device);
|
||||
|
||||
actor = clutter_input_device_update (device, NULL, FALSE);
|
||||
actor = clutter_input_device_update (device, NULL,
|
||||
CLUTTER_STAGE (stage), FALSE,
|
||||
event);
|
||||
if (actor != stage)
|
||||
{
|
||||
ClutterEvent *crossing;
|
||||
@ -1770,21 +1774,9 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
/* if the backend provides a device then we should
|
||||
* already have everything we need to update it and
|
||||
* get the actor underneath
|
||||
*/
|
||||
if (device != NULL)
|
||||
actor = clutter_input_device_update (device, NULL, TRUE);
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||
|
||||
actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage),
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
}
|
||||
|
||||
actor = clutter_input_device_update (device, NULL,
|
||||
CLUTTER_STAGE (stage),
|
||||
TRUE, event);
|
||||
if (actor == NULL)
|
||||
break;
|
||||
|
||||
@ -1860,9 +1852,6 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
sequence =
|
||||
clutter_event_get_event_sequence (event);
|
||||
|
||||
if (event->type == CLUTTER_TOUCH_BEGIN)
|
||||
_clutter_input_device_add_event_sequence (device, event);
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
/* Only do a pick to find the source if source is not already set
|
||||
@ -1892,17 +1881,9 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
}
|
||||
|
||||
if (device != NULL)
|
||||
actor = clutter_input_device_update (device, sequence, TRUE);
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (EVENT, "No device found: picking");
|
||||
|
||||
actor = _clutter_stage_do_pick (CLUTTER_STAGE (stage),
|
||||
x, y,
|
||||
CLUTTER_PICK_REACTIVE);
|
||||
}
|
||||
|
||||
actor = clutter_input_device_update (device, sequence,
|
||||
CLUTTER_STAGE (stage),
|
||||
TRUE, event);
|
||||
if (actor == NULL)
|
||||
break;
|
||||
|
||||
@ -1954,6 +1935,11 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
case CLUTTER_CLIENT_MESSAGE:
|
||||
break;
|
||||
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
_clutter_event_process_filters (event);
|
||||
break;
|
||||
|
||||
case CLUTTER_EVENT_LAST:
|
||||
break;
|
||||
}
|
||||
@ -2302,39 +2288,16 @@ void
|
||||
_clutter_clear_events_queue (void)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
ClutterEvent *event;
|
||||
|
||||
if (context->events_queue != NULL)
|
||||
{
|
||||
g_queue_foreach (context->events_queue,
|
||||
(GFunc) clutter_event_free,
|
||||
NULL);
|
||||
g_queue_free (context->events_queue);
|
||||
context->events_queue = NULL;
|
||||
}
|
||||
}
|
||||
/* Lock the queue for as long as it lives */
|
||||
g_async_queue_lock (context->events_queue);
|
||||
|
||||
void
|
||||
_clutter_clear_events_queue_for_stage (ClutterStage *stage)
|
||||
{
|
||||
ClutterMainContext *context = _clutter_context_get_default ();
|
||||
GList *l, *next;
|
||||
|
||||
if (context->events_queue == NULL)
|
||||
return;
|
||||
|
||||
/* Remove any pending events for this stage from the event queue */
|
||||
for (l = context->events_queue->head; l; l = next)
|
||||
{
|
||||
ClutterEvent *event = l->data;
|
||||
|
||||
next = l->next;
|
||||
|
||||
if (event->any.stage == stage)
|
||||
{
|
||||
g_queue_delete_link (context->events_queue, l);
|
||||
while ((event = g_async_queue_try_pop_unlocked (context->events_queue)))
|
||||
clutter_event_free (event);
|
||||
}
|
||||
}
|
||||
|
||||
g_async_queue_unref (context->events_queue);
|
||||
context->events_queue = NULL;
|
||||
}
|
||||
|
||||
ClutterPickMode
|
||||
|
@ -71,6 +71,9 @@ gboolean clutter_actor_has_transitions (ClutterActor *actor);
|
||||
CLUTTER_EXPORT
|
||||
ClutterFrameClock * clutter_actor_pick_frame_clock (ClutterActor *self,
|
||||
ClutterActor **out_actor);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_seat_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#undef __CLUTTER_H_INSIDE__
|
||||
|
||||
|
@ -122,7 +122,7 @@ struct _ClutterMainContext
|
||||
ClutterStageManager *stage_manager;
|
||||
|
||||
/* the main event queue */
|
||||
GQueue *events_queue;
|
||||
GAsyncQueue *events_queue;
|
||||
|
||||
/* the event filters added via clutter_event_add_filter. these are
|
||||
* ordered from least recently added to most recently added */
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "clutter-input-device-tool.h"
|
||||
#include "clutter-input-pointer-a11y-private.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-mutter.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-seat.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
@ -65,9 +66,6 @@ struct _ClutterSeatPrivate
|
||||
|
||||
unsigned int inhibit_unfocus_count;
|
||||
|
||||
/* Keyboard a11y */
|
||||
ClutterKbdA11ySettings kbd_a11y_settings;
|
||||
|
||||
/* Pointer a11y */
|
||||
ClutterPointerA11ySettings pointer_a11y_settings;
|
||||
};
|
||||
@ -404,43 +402,6 @@ clutter_seat_get_keymap (ClutterSeat *seat)
|
||||
return CLUTTER_SEAT_GET_CLASS (seat)->get_keymap (seat);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
are_kbd_a11y_settings_equal (ClutterKbdA11ySettings *a,
|
||||
ClutterKbdA11ySettings *b)
|
||||
{
|
||||
return (memcmp (a, b, sizeof (ClutterKbdA11ySettings)) == 0);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_set_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *settings)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterSeatPrivate *priv = clutter_seat_get_instance_private (seat);
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_SEAT (seat));
|
||||
|
||||
if (are_kbd_a11y_settings_equal (&priv->kbd_a11y_settings, settings))
|
||||
return;
|
||||
|
||||
priv->kbd_a11y_settings = *settings;
|
||||
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
if (seat_class->apply_kbd_a11y_settings)
|
||||
seat_class->apply_kbd_a11y_settings (seat, settings);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_get_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *settings)
|
||||
{
|
||||
ClutterSeatPrivate *priv = clutter_seat_get_instance_private (seat);
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_SEAT (seat));
|
||||
|
||||
*settings = priv->kbd_a11y_settings;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_ensure_a11y_state (ClutterSeat *seat)
|
||||
{
|
||||
@ -674,6 +635,40 @@ clutter_seat_compress_motion (ClutterSeat *seat,
|
||||
seat_class->compress_motion (seat, event, to_discard);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_seat_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterSeatClass *seat_class;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), FALSE);
|
||||
g_return_val_if_fail (event, FALSE);
|
||||
|
||||
seat_class = CLUTTER_SEAT_GET_CLASS (seat);
|
||||
|
||||
if (seat_class->handle_event_post)
|
||||
seat_class->handle_event_post (seat, event);
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
g_assert_true (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
g_signal_emit (seat, signals[DEVICE_ADDED], 0, device);
|
||||
break;
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
g_signal_emit (seat, signals[DEVICE_REMOVED], 0, device);
|
||||
g_object_run_dispose (G_OBJECT (device));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
clutter_seat_warp_pointer (ClutterSeat *seat,
|
||||
int x,
|
||||
@ -709,3 +704,20 @@ clutter_seat_get_touch_mode (ClutterSeat *seat)
|
||||
|
||||
return touch_mode;
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_seat_query_state (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *modifiers)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_SEAT (seat), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), FALSE);
|
||||
|
||||
return CLUTTER_SEAT_GET_CLASS (seat)->query_state (seat,
|
||||
device,
|
||||
sequence,
|
||||
coords,
|
||||
modifiers);
|
||||
}
|
||||
|
@ -37,24 +37,6 @@ CLUTTER_EXPORT
|
||||
G_DECLARE_DERIVABLE_TYPE (ClutterSeat, clutter_seat,
|
||||
CLUTTER, SEAT, GObject)
|
||||
|
||||
/**
|
||||
* ClutterKbdA11ySettings:
|
||||
*
|
||||
* The #ClutterKbdA11ySettings structure contains keyboard accessibility
|
||||
* settings
|
||||
*
|
||||
*/
|
||||
typedef struct _ClutterKbdA11ySettings
|
||||
{
|
||||
ClutterKeyboardA11yFlags controls;
|
||||
gint slowkeys_delay;
|
||||
gint debounce_delay;
|
||||
gint timeout_delay;
|
||||
gint mousekeys_init_delay;
|
||||
gint mousekeys_max_speed;
|
||||
gint mousekeys_accel_time;
|
||||
} ClutterKbdA11ySettings;
|
||||
|
||||
/**
|
||||
* ClutterPointerA11ySettings:
|
||||
*
|
||||
@ -106,10 +88,19 @@ struct _ClutterSeatClass
|
||||
ClutterEvent *event,
|
||||
const ClutterEvent *to_discard);
|
||||
|
||||
gboolean (* handle_event_post) (ClutterSeat *seat,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void (* warp_pointer) (ClutterSeat *seat,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
gboolean (* query_state) (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *modifiers);
|
||||
|
||||
/* Event platform data */
|
||||
void (* copy_event_data) (ClutterSeat *seat,
|
||||
const ClutterEvent *src,
|
||||
@ -117,10 +108,6 @@ struct _ClutterSeatClass
|
||||
void (* free_event_data) (ClutterSeat *seat,
|
||||
ClutterEvent *event);
|
||||
|
||||
/* Keyboard accessibility */
|
||||
void (* apply_kbd_a11y_settings) (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *settings);
|
||||
|
||||
/* Virtual devices */
|
||||
ClutterVirtualInputDevice * (* create_virtual_device) (ClutterSeat *seat,
|
||||
ClutterInputDeviceType device_type);
|
||||
@ -140,12 +127,6 @@ void clutter_seat_bell_notify (ClutterSeat *seat);
|
||||
CLUTTER_EXPORT
|
||||
ClutterKeymap * clutter_seat_get_keymap (ClutterSeat *seat);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
void clutter_seat_set_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *settings);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_seat_get_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *settings);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_seat_ensure_a11y_state (ClutterSeat *seat);
|
||||
|
||||
@ -188,4 +169,11 @@ void clutter_seat_warp_pointer (ClutterSeat *seat,
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_seat_get_touch_mode (ClutterSeat *seat);
|
||||
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_seat_query_state (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *modifiers);
|
||||
|
||||
#endif /* CLUTTER_SEAT_H */
|
||||
|
@ -1013,7 +1013,6 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
gboolean first_event;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
@ -1024,25 +1023,6 @@ _clutter_stage_queue_event (ClutterStage *stage,
|
||||
if (copy_event)
|
||||
event = clutter_event_copy (event);
|
||||
|
||||
/* if needed, update the state of the input device of the event.
|
||||
* we do it here to avoid calling the same code from every backend
|
||||
* event processing function
|
||||
*/
|
||||
device = clutter_event_get_device (event);
|
||||
if (device != NULL &&
|
||||
event->type != CLUTTER_PROXIMITY_IN &&
|
||||
event->type != CLUTTER_PROXIMITY_OUT)
|
||||
{
|
||||
ClutterEventSequence *sequence = clutter_event_get_event_sequence (event);
|
||||
guint32 event_time = clutter_event_get_time (event);
|
||||
gfloat event_x, event_y;
|
||||
|
||||
clutter_event_get_coords (event, &event_x, &event_y);
|
||||
|
||||
_clutter_input_device_set_coords (device, sequence, event_x, event_y, stage);
|
||||
_clutter_input_device_set_time (device, event_time);
|
||||
}
|
||||
|
||||
if (first_event)
|
||||
{
|
||||
gboolean compressible = event->type == CLUTTER_MOTION ||
|
||||
@ -1363,7 +1343,7 @@ clutter_stage_update_devices (ClutterStage *stage,
|
||||
for (l = devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *device = l->data;
|
||||
clutter_input_device_update (device, NULL, TRUE);
|
||||
clutter_input_device_update (device, NULL, stage, TRUE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1680,7 +1660,7 @@ clutter_stage_dispose (GObject *object)
|
||||
|
||||
clutter_actor_hide (CLUTTER_ACTOR (object));
|
||||
|
||||
_clutter_clear_events_queue_for_stage (stage);
|
||||
_clutter_clear_events_queue ();
|
||||
|
||||
if (priv->impl != NULL)
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "backends/meta-backend-types.h"
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
#include "backends/meta-egl.h"
|
||||
#include "backends/meta-input-mapper-private.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/meta-monitor-manager-private.h"
|
||||
#include "backends/meta-orientation-manager.h"
|
||||
@ -67,7 +68,8 @@ struct _MetaBackendClass
|
||||
|
||||
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend,
|
||||
GError **error);
|
||||
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
|
||||
MetaCursorRenderer * (* get_cursor_renderer) (MetaBackend *backend,
|
||||
ClutterInputDevice *device);
|
||||
MetaCursorTracker * (* create_cursor_tracker) (MetaBackend *backend);
|
||||
MetaRenderer * (* create_renderer) (MetaBackend *backend,
|
||||
GError **error);
|
||||
@ -105,6 +107,8 @@ struct _MetaBackendClass
|
||||
void (* set_numlock) (MetaBackend *backend,
|
||||
gboolean numlock_state);
|
||||
|
||||
void (* set_pointer_constraint) (MetaBackend *backend,
|
||||
MetaPointerConstraint *constraint);
|
||||
};
|
||||
|
||||
void meta_init_backend (GType backend_gtype);
|
||||
@ -129,6 +133,8 @@ META_EXPORT_TEST
|
||||
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
|
||||
MetaOrientationManager * meta_backend_get_orientation_manager (MetaBackend *backend);
|
||||
MetaCursorTracker * meta_backend_get_cursor_tracker (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer_for_device (MetaBackend *backend,
|
||||
ClutterInputDevice *device);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
|
||||
META_EXPORT_TEST
|
||||
MetaRenderer * meta_backend_get_renderer (MetaBackend *backend);
|
||||
@ -171,6 +177,7 @@ gboolean meta_is_stage_views_enabled (void);
|
||||
|
||||
gboolean meta_is_stage_views_scaled (void);
|
||||
|
||||
MetaInputMapper *meta_backend_get_input_mapper (MetaBackend *backend);
|
||||
MetaInputSettings *meta_backend_get_input_settings (MetaBackend *backend);
|
||||
|
||||
void meta_backend_notify_keymap_changed (MetaBackend *backend);
|
||||
@ -191,4 +198,12 @@ GList * meta_backend_get_gpus (MetaBackend *backend);
|
||||
WacomDeviceDatabase * meta_backend_get_wacom_database (MetaBackend *backend);
|
||||
#endif
|
||||
|
||||
void meta_backend_add_hw_cursor_inhibitor (MetaBackend *backend,
|
||||
MetaHwCursorInhibitor *inhibitor);
|
||||
|
||||
void meta_backend_remove_hw_cursor_inhibitor (MetaBackend *backend,
|
||||
MetaHwCursorInhibitor *inhibitor);
|
||||
|
||||
gboolean meta_backend_is_hw_cursors_inhibited (MetaBackend *backend);
|
||||
|
||||
#endif /* META_BACKEND_PRIVATE_H */
|
||||
|
@ -53,8 +53,10 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
#include "backends/meta-idle-monitor-private.h"
|
||||
#include "backends/meta-input-mapper-private.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/meta-monitor-manager-dummy.h"
|
||||
@ -120,8 +122,9 @@ struct _MetaBackendPrivate
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaOrientationManager *orientation_manager;
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
GHashTable *cursor_renderers;
|
||||
MetaInputSettings *input_settings;
|
||||
MetaInputMapper *input_mapper;
|
||||
MetaRenderer *renderer;
|
||||
#ifdef HAVE_EGL
|
||||
MetaEgl *egl;
|
||||
@ -150,6 +153,7 @@ struct _MetaBackendPrivate
|
||||
ClutterActor *stage;
|
||||
|
||||
GList *gpus;
|
||||
GList *hw_cursor_inhibitors;
|
||||
|
||||
gboolean is_pointer_position_initialized;
|
||||
|
||||
@ -173,6 +177,14 @@ struct _MetaBackendPrivate
|
||||
};
|
||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||
|
||||
typedef struct _MetaBackendSource MetaBackendSource;
|
||||
|
||||
struct _MetaBackendSource
|
||||
{
|
||||
GSource parent;
|
||||
MetaBackend *backend;
|
||||
};
|
||||
|
||||
static void
|
||||
initable_iface_init (GInitableIface *initable_iface);
|
||||
|
||||
@ -213,6 +225,8 @@ meta_backend_finalize (GObject *object)
|
||||
g_clear_pointer (&priv->wacom_db, libwacom_database_destroy);
|
||||
#endif
|
||||
|
||||
g_hash_table_unref (priv->cursor_renderers);
|
||||
|
||||
if (priv->sleep_signal_id)
|
||||
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
|
||||
if (priv->upower_watch_id)
|
||||
@ -264,6 +278,19 @@ reset_pointer_position (MetaBackend *backend)
|
||||
primary->rect.y + primary->rect.height * 0.9);
|
||||
}
|
||||
|
||||
static void
|
||||
update_cursors (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
MetaCursorRenderer *renderer;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, priv->cursor_renderers);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &renderer))
|
||||
meta_cursor_renderer_force_update (renderer);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_monitors_changed (MetaBackend *backend)
|
||||
{
|
||||
@ -289,7 +316,7 @@ meta_backend_monitors_changed (MetaBackend *backend)
|
||||
}
|
||||
}
|
||||
|
||||
meta_cursor_renderer_force_update (priv->cursor_renderer);
|
||||
update_cursors (backend);
|
||||
}
|
||||
|
||||
void
|
||||
@ -355,8 +382,19 @@ on_device_added (ClutterSeat *seat,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = META_BACKEND (user_data);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
create_device_monitor (backend, device);
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
|
||||
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE ||
|
||||
device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_CURSOR_DEVICE ||
|
||||
device_type == CLUTTER_PAD_DEVICE)
|
||||
meta_input_mapper_add_device (priv->input_mapper, device);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
@ -428,6 +466,8 @@ on_device_removed (ClutterSeat *seat,
|
||||
|
||||
destroy_device_monitor (backend, device);
|
||||
|
||||
meta_input_mapper_remove_device (priv->input_mapper, device);
|
||||
|
||||
/* If the device the user last interacted goes away, check again pointer
|
||||
* visibility.
|
||||
*/
|
||||
@ -438,6 +478,7 @@ on_device_removed (ClutterSeat *seat,
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
priv->current_device = NULL;
|
||||
g_clear_handle_id (&priv->device_update_idle_id, g_source_remove);
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
has_touchscreen = check_has_slave_touchscreen (seat);
|
||||
@ -504,6 +545,42 @@ meta_backend_create_input_settings (MetaBackend *backend)
|
||||
return META_BACKEND_GET_CLASS (backend)->create_input_settings (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
input_mapper_device_mapped_cb (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device,
|
||||
float matrix[6],
|
||||
MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
MetaInputSettings *input_settings = priv->input_settings;
|
||||
|
||||
meta_input_settings_set_device_matrix (input_settings, device, matrix);
|
||||
}
|
||||
|
||||
static void
|
||||
input_mapper_device_enabled_cb (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device,
|
||||
gboolean enabled,
|
||||
MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
MetaInputSettings *input_settings = priv->input_settings;
|
||||
|
||||
meta_input_settings_set_device_enabled (input_settings, device, enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
input_mapper_device_aspect_ratio_cb (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device,
|
||||
double aspect_ratio,
|
||||
MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
MetaInputSettings *input_settings = priv->input_settings;
|
||||
|
||||
meta_input_settings_set_device_aspect_ratio (input_settings, device, aspect_ratio);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_real_post_init (MetaBackend *backend)
|
||||
{
|
||||
@ -519,8 +596,6 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
|
||||
meta_backend_sync_screen_size (backend);
|
||||
|
||||
priv->cursor_renderer = META_BACKEND_GET_CLASS (backend)->create_cursor_renderer (backend);
|
||||
|
||||
priv->device_monitors =
|
||||
g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) g_object_unref);
|
||||
|
||||
@ -529,7 +604,8 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
g_signal_connect_object (seat, "device-added",
|
||||
G_CALLBACK (on_device_added), backend, 0);
|
||||
g_signal_connect_object (seat, "device-removed",
|
||||
G_CALLBACK (on_device_removed), backend, 0);
|
||||
G_CALLBACK (on_device_removed), backend,
|
||||
G_CONNECT_AFTER);
|
||||
|
||||
set_initial_pointer_visibility (backend, seat);
|
||||
|
||||
@ -544,6 +620,14 @@ meta_backend_real_post_init (MetaBackend *backend)
|
||||
meta_input_settings_maybe_restore_numlock_state (priv->input_settings);
|
||||
}
|
||||
|
||||
priv->input_mapper = meta_input_mapper_new ();
|
||||
g_signal_connect (priv->input_mapper, "device-mapped",
|
||||
G_CALLBACK (input_mapper_device_mapped_cb), backend);
|
||||
g_signal_connect (priv->input_mapper, "device-enabled",
|
||||
G_CALLBACK (input_mapper_device_enabled_cb), backend);
|
||||
g_signal_connect (priv->input_mapper, "device-aspect-ratio",
|
||||
G_CALLBACK (input_mapper_device_aspect_ratio_cb), backend);
|
||||
|
||||
#ifdef HAVE_REMOTE_DESKTOP
|
||||
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
|
||||
priv->screen_cast = meta_screen_cast_new (backend,
|
||||
@ -916,10 +1000,18 @@ clutter_source_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackendSource *backend_source = (MetaBackendSource *) source;
|
||||
MetaBackendPrivate *priv =
|
||||
meta_backend_get_instance_private (backend_source->backend);
|
||||
ClutterEvent *event = clutter_event_get ();
|
||||
ClutterSeat *seat;
|
||||
|
||||
if (event)
|
||||
{
|
||||
event->any.stage =
|
||||
CLUTTER_STAGE (meta_backend_get_stage (backend_source->backend));
|
||||
seat = clutter_backend_get_default_seat (priv->clutter_backend);
|
||||
clutter_seat_handle_event_post (seat, event);
|
||||
clutter_do_event (event);
|
||||
clutter_event_free (event);
|
||||
}
|
||||
@ -945,6 +1037,7 @@ static gboolean
|
||||
init_clutter (MetaBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackendSource *backend_source;
|
||||
GSource *source;
|
||||
|
||||
clutter_set_custom_backend_func (meta_get_clutter_backend);
|
||||
@ -956,7 +1049,9 @@ init_clutter (MetaBackend *backend,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
source = g_source_new (&clutter_source_funcs, sizeof (GSource));
|
||||
source = g_source_new (&clutter_source_funcs, sizeof (MetaBackendSource));
|
||||
backend_source = (MetaBackendSource *) source;
|
||||
backend_source->backend = backend;
|
||||
g_source_attach (source, NULL);
|
||||
g_source_unref (source);
|
||||
|
||||
@ -1081,8 +1176,25 @@ MetaCursorRenderer *
|
||||
meta_backend_get_cursor_renderer (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
ClutterInputDevice *pointer;
|
||||
ClutterSeat *seat;
|
||||
|
||||
return priv->cursor_renderer;
|
||||
seat = clutter_backend_get_default_seat (priv->clutter_backend);
|
||||
pointer = clutter_seat_get_pointer (seat);
|
||||
|
||||
return meta_backend_get_cursor_renderer_for_device (backend, pointer);
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_backend_get_cursor_renderer_for_device (MetaBackend *backend,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_BACKEND (backend), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (device) !=
|
||||
CLUTTER_KEYBOARD_DEVICE, NULL);
|
||||
|
||||
return META_BACKEND_GET_CLASS (backend)->get_cursor_renderer (backend, device);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1329,7 +1441,7 @@ meta_backend_get_client_pointer_constraint (MetaBackend *backend)
|
||||
* @constraint: (nullable): the client constraint to follow.
|
||||
*
|
||||
* Sets the current pointer constraint and removes (and unrefs) the previous
|
||||
* one. If @constrant is %NULL, this means that there is no
|
||||
* one. If @constraint is %NULL, this means that there is no
|
||||
* #MetaPointerConstraint active.
|
||||
*/
|
||||
void
|
||||
@ -1338,11 +1450,8 @@ meta_backend_set_client_pointer_constraint (MetaBackend *backend,
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
g_assert (!constraint || !priv->client_pointer_constraint);
|
||||
|
||||
g_clear_object (&priv->client_pointer_constraint);
|
||||
if (constraint)
|
||||
priv->client_pointer_constraint = g_object_ref (constraint);
|
||||
META_BACKEND_GET_CLASS (backend)->set_pointer_constraint (backend, constraint);
|
||||
g_set_object (&priv->client_pointer_constraint, constraint);
|
||||
}
|
||||
|
||||
ClutterBackend *
|
||||
@ -1408,6 +1517,14 @@ meta_is_stage_views_scaled (void)
|
||||
return layout_mode == META_LOGICAL_MONITOR_LAYOUT_MODE_LOGICAL;
|
||||
}
|
||||
|
||||
MetaInputMapper *
|
||||
meta_backend_get_input_mapper (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
return priv->input_mapper;
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
meta_backend_get_input_settings (MetaBackend *backend)
|
||||
{
|
||||
@ -1474,3 +1591,40 @@ meta_backend_get_wacom_database (MetaBackend *backend)
|
||||
return priv->wacom_db;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_backend_add_hw_cursor_inhibitor (MetaBackend *backend,
|
||||
MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->hw_cursor_inhibitors = g_list_prepend (priv->hw_cursor_inhibitors,
|
||||
inhibitor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_backend_remove_hw_cursor_inhibitor (MetaBackend *backend,
|
||||
MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->hw_cursor_inhibitors = g_list_remove (priv->hw_cursor_inhibitors,
|
||||
inhibitor);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_backend_is_hw_cursors_inhibited (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->hw_cursor_inhibitors; l; l = l->next)
|
||||
{
|
||||
MetaHwCursorInhibitor *inhibitor = l->data;
|
||||
|
||||
if (meta_hw_cursor_inhibitor_is_cursor_inhibited (inhibitor))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/meta-stage-private.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
@ -44,6 +46,7 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_BACKEND,
|
||||
PROP_DEVICE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@ -57,6 +60,7 @@ struct _MetaCursorRendererPrivate
|
||||
float current_x;
|
||||
float current_y;
|
||||
|
||||
ClutterInputDevice *device;
|
||||
MetaCursorSprite *displayed_cursor;
|
||||
MetaCursorSprite *overlay_cursor;
|
||||
|
||||
@ -77,14 +81,13 @@ static guint signals[LAST_SIGNAL];
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
|
||||
|
||||
static gboolean
|
||||
meta_hw_cursor_inhibitor_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
gboolean
|
||||
meta_hw_cursor_inhibitor_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaHwCursorInhibitorInterface *iface =
|
||||
META_HW_CURSOR_INHIBITOR_GET_IFACE (inhibitor);
|
||||
|
||||
return iface->is_cursor_sprite_inhibited (inhibitor, cursor_sprite);
|
||||
return iface->is_cursor_inhibited (inhibitor);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -203,6 +206,9 @@ meta_cursor_renderer_get_property (GObject *object,
|
||||
case PROP_BACKEND:
|
||||
g_value_set_object (value, priv->backend);
|
||||
break;
|
||||
case PROP_DEVICE:
|
||||
g_value_set_object (value, priv->device);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -224,6 +230,9 @@ meta_cursor_renderer_set_property (GObject *object,
|
||||
case PROP_BACKEND:
|
||||
priv->backend = g_value_get_object (value);
|
||||
break;
|
||||
case PROP_DEVICE:
|
||||
priv->device = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -284,6 +293,14 @@ meta_cursor_renderer_class_init (MetaCursorRendererClass *klass)
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
obj_props[PROP_DEVICE] =
|
||||
g_param_spec_object ("device",
|
||||
"device",
|
||||
"Input device",
|
||||
CLUTTER_TYPE_INPUT_DEVICE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
||||
|
||||
signals[CURSOR_PAINTED] = g_signal_new ("cursor-painted",
|
||||
@ -332,6 +349,41 @@ meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
|
||||
};
|
||||
}
|
||||
|
||||
static float
|
||||
find_highest_logical_monitor_scale (MetaBackend *backend,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
graphene_rect_t cursor_rect;
|
||||
GList *logical_monitors;
|
||||
GList *l;
|
||||
float highest_scale = 0.0;
|
||||
|
||||
cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
|
||||
cursor_sprite);
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
graphene_rect_t logical_monitor_rect =
|
||||
meta_rectangle_to_graphene_rect (&logical_monitor->rect);
|
||||
|
||||
if (!graphene_rect_intersection (&cursor_rect,
|
||||
&logical_monitor_rect,
|
||||
NULL))
|
||||
continue;
|
||||
|
||||
highest_scale = MAX (highest_scale, logical_monitor->scale);
|
||||
}
|
||||
|
||||
return highest_scale;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
@ -340,9 +392,14 @@ meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer,
|
||||
gboolean handled_by_backend;
|
||||
|
||||
if (cursor_sprite)
|
||||
{
|
||||
float scale = find_highest_logical_monitor_scale (priv->backend,
|
||||
cursor_sprite);
|
||||
meta_cursor_sprite_prepare_at (cursor_sprite,
|
||||
MAX (1, scale),
|
||||
(int) priv->current_x,
|
||||
(int) priv->current_y);
|
||||
}
|
||||
|
||||
handled_by_backend =
|
||||
META_CURSOR_RENDERER_GET_CLASS (renderer)->update_cursor (renderer,
|
||||
@ -354,10 +411,12 @@ meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer,
|
||||
}
|
||||
|
||||
MetaCursorRenderer *
|
||||
meta_cursor_renderer_new (MetaBackend *backend)
|
||||
meta_cursor_renderer_new (MetaBackend *backend,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER,
|
||||
"backend", backend,
|
||||
"device", device,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@ -384,30 +443,18 @@ meta_cursor_renderer_force_update (MetaCursorRenderer *renderer)
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
float x,
|
||||
float y)
|
||||
meta_cursor_renderer_update_position (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||
graphene_point_t pos;
|
||||
|
||||
priv->current_x = x;
|
||||
priv->current_y = y;
|
||||
clutter_input_device_get_coords (priv->device, NULL, &pos);
|
||||
priv->current_x = pos.x;
|
||||
priv->current_y = pos.y;
|
||||
|
||||
meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor);
|
||||
}
|
||||
|
||||
graphene_point_t
|
||||
meta_cursor_renderer_get_position (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
return (graphene_point_t) {
|
||||
.x = priv->current_x,
|
||||
.y = priv->current_y
|
||||
};
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
|
||||
{
|
||||
@ -428,44 +475,11 @@ meta_cursor_renderer_is_overlay_visible (MetaCursorRenderer *renderer)
|
||||
return meta_overlay_is_visible (priv->stage_overlay);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_add_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||
MetaHwCursorInhibitor *inhibitor)
|
||||
ClutterInputDevice *
|
||||
meta_cursor_renderer_get_input_device (MetaCursorRenderer *renderer)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
priv->hw_cursor_inhibitors = g_list_prepend (priv->hw_cursor_inhibitors,
|
||||
inhibitor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_remove_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||
MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
|
||||
priv->hw_cursor_inhibitors = g_list_remove (priv->hw_cursor_inhibitors,
|
||||
inhibitor);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_cursor_renderer_is_hw_cursors_inhibited (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
{
|
||||
MetaCursorRendererPrivate *priv =
|
||||
meta_cursor_renderer_get_instance_private (renderer);
|
||||
GList *l;
|
||||
|
||||
for (l = priv->hw_cursor_inhibitors; l; l = l->next)
|
||||
{
|
||||
MetaHwCursorInhibitor *inhibitor = l->data;
|
||||
|
||||
if (meta_hw_cursor_inhibitor_is_cursor_sprite_inhibited (inhibitor,
|
||||
cursor_sprite))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return priv->device;
|
||||
}
|
||||
|
@ -38,10 +38,11 @@ struct _MetaHwCursorInhibitorInterface
|
||||
{
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
gboolean (* is_cursor_sprite_inhibited) (MetaHwCursorInhibitor *inhibitor,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
gboolean (* is_cursor_inhibited) (MetaHwCursorInhibitor *inhibitor);
|
||||
};
|
||||
|
||||
gboolean meta_hw_cursor_inhibitor_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor);
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer,
|
||||
META, CURSOR_RENDERER, GObject);
|
||||
@ -54,35 +55,25 @@ struct _MetaCursorRendererClass
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
};
|
||||
|
||||
MetaCursorRenderer * meta_cursor_renderer_new (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_cursor_renderer_new (MetaBackend *backend,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
|
||||
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||
float x,
|
||||
float y);
|
||||
graphene_point_t meta_cursor_renderer_get_position (MetaCursorRenderer *renderer);
|
||||
void meta_cursor_renderer_update_position (MetaCursorRenderer *renderer);
|
||||
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
|
||||
|
||||
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||
|
||||
gboolean meta_cursor_renderer_is_overlay_visible (MetaCursorRenderer *renderer);
|
||||
|
||||
void meta_cursor_renderer_add_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||
MetaHwCursorInhibitor *inhibitor);
|
||||
|
||||
void meta_cursor_renderer_remove_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||
MetaHwCursorInhibitor *inhibitor);
|
||||
|
||||
gboolean meta_cursor_renderer_is_hw_cursors_inhibited (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
|
||||
graphene_rect_t meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
|
||||
void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
ClutterInputDevice * meta_cursor_renderer_get_input_device (MetaCursorRenderer *renderer);
|
||||
|
||||
void meta_cursor_renderer_update_stage_overlay (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
|
@ -41,16 +41,12 @@ void meta_cursor_tracker_unset_window_cursor (MetaCursorTracker *tracker);
|
||||
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
MetaCursorSprite *cursor_sprite);
|
||||
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
float new_x,
|
||||
float new_y);
|
||||
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_track_position (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_untrack_position (MetaCursorTracker *tracker);
|
||||
|
||||
MetaCursorSprite * meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker);
|
||||
|
||||
MetaBackend * meta_cursor_tracker_get_backend (MetaCursorTracker *tracker);
|
||||
|
||||
void meta_cursor_tracker_notify_cursor_changed (MetaCursorTracker *tracker);
|
||||
|
@ -31,15 +31,12 @@
|
||||
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "cogl/cogl.h"
|
||||
#include "core/display-private.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta-marshal.h"
|
||||
#include "meta/main.h"
|
||||
#include "meta/util.h"
|
||||
|
||||
@ -303,14 +300,8 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
meta_marshal_VOID__FLOAT_FLOAT,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_FLOAT,
|
||||
G_TYPE_FLOAT);
|
||||
g_signal_set_va_marshaller (signals[CURSOR_MOVED],
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
meta_marshal_VOID__FLOAT_FLOATv);
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[VISIBILITY_CHANGED] = g_signal_new ("visibility-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
@ -437,88 +428,23 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
||||
float new_x,
|
||||
float new_y)
|
||||
meta_cursor_tracker_update_position (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorTrackerPrivate *priv =
|
||||
meta_cursor_tracker_get_instance_private (tracker);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (priv->backend);
|
||||
gboolean position_changed;
|
||||
|
||||
if (priv->x != new_x || priv->y != new_y)
|
||||
{
|
||||
position_changed = TRUE;
|
||||
priv->x = new_x;
|
||||
priv->y = new_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
position_changed = FALSE;
|
||||
}
|
||||
|
||||
meta_cursor_renderer_set_position (cursor_renderer, new_x, new_y);
|
||||
|
||||
if (position_changed)
|
||||
g_signal_emit (tracker, signals[CURSOR_MOVED], 0, new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_gdk (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
GdkSeat *gseat;
|
||||
GdkDevice *gdevice;
|
||||
GdkScreen *gscreen;
|
||||
|
||||
gseat = gdk_display_get_default_seat (gdk_display_get_default ());
|
||||
gdevice = gdk_seat_get_pointer (gseat);
|
||||
|
||||
gdk_device_get_position (gdevice, &gscreen, x, y);
|
||||
if (mods)
|
||||
gdk_device_get_state (gdevice,
|
||||
gdk_screen_get_root_window (gscreen),
|
||||
NULL, (GdkModifierType*)mods);
|
||||
}
|
||||
|
||||
static void
|
||||
get_pointer_position_clutter (int *x,
|
||||
int *y,
|
||||
int *mods)
|
||||
{
|
||||
ClutterSeat *seat;
|
||||
ClutterInputDevice *cdevice;
|
||||
graphene_point_t point;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
cdevice = clutter_seat_get_pointer (seat);
|
||||
|
||||
clutter_input_device_get_coords (cdevice, NULL, &point);
|
||||
if (x)
|
||||
*x = point.x;
|
||||
if (y)
|
||||
*y = point.y;
|
||||
if (mods)
|
||||
*mods = clutter_input_device_get_modifier_state (cdevice);
|
||||
g_signal_emit (tracker, signals[CURSOR_MOVED], 0);
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *mods)
|
||||
{
|
||||
/* We can't use the clutter interface when not running as a wayland compositor,
|
||||
because we need to query the server, rather than using the last cached value.
|
||||
OTOH, on wayland we can't use GDK, because that only sees the events
|
||||
we forward to xwayland.
|
||||
*/
|
||||
if (meta_is_wayland_compositor ())
|
||||
get_pointer_position_clutter (x, y, (int*)mods);
|
||||
else
|
||||
get_pointer_position_gdk (x, y, (int*)mods);
|
||||
ClutterSeat *seat;
|
||||
ClutterInputDevice *cdevice;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
cdevice = clutter_seat_get_pointer (seat);
|
||||
|
||||
clutter_seat_query_state (seat, cdevice, NULL, coords, mods);
|
||||
}
|
||||
|
||||
void
|
||||
@ -579,16 +505,6 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
|
||||
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
MetaCursorTrackerPrivate *priv =
|
||||
meta_cursor_tracker_get_instance_private (tracker);
|
||||
|
||||
return priv->displayed_cursor;
|
||||
}
|
||||
|
||||
MetaBackend *
|
||||
meta_cursor_tracker_get_backend (MetaCursorTracker *tracker)
|
||||
{
|
||||
|
@ -180,10 +180,11 @@ meta_cursor_sprite_get_texture_transform (MetaCursorSprite *sprite)
|
||||
|
||||
void
|
||||
meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
|
||||
float best_scale,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
g_signal_emit (sprite, signals[PREPARE_AT], 0, x, y);
|
||||
g_signal_emit (sprite, signals[PREPARE_AT], 0, best_scale, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
@ -226,7 +227,8 @@ meta_cursor_sprite_class_init (MetaCursorSpriteClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_NONE, 3,
|
||||
G_TYPE_FLOAT,
|
||||
G_TYPE_INT,
|
||||
G_TYPE_INT);
|
||||
signals[TEXTURE_CHANGED] = g_signal_new ("texture-changed",
|
||||
|
@ -43,6 +43,7 @@ struct _MetaCursorSpriteClass
|
||||
};
|
||||
|
||||
void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
|
||||
float best_scale,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
|
@ -23,7 +23,8 @@
|
||||
#define META_INPUT_MAPPER_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-monitor-manager-private.h"
|
||||
|
||||
#include "backends/meta-backend-types.h"
|
||||
|
||||
#define META_TYPE_INPUT_MAPPER (meta_input_mapper_get_type ())
|
||||
|
||||
@ -33,8 +34,7 @@ G_DECLARE_FINAL_TYPE (MetaInputMapper, meta_input_mapper,
|
||||
MetaInputMapper * meta_input_mapper_new (void);
|
||||
|
||||
void meta_input_mapper_add_device (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device,
|
||||
gboolean builtin);
|
||||
ClutterInputDevice *device);
|
||||
void meta_input_mapper_remove_device (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
@ -46,4 +46,7 @@ MetaLogicalMonitor *
|
||||
meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GSettings * meta_input_mapper_get_tablet_settings (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
#endif /* META_INPUT_MAPPER_H */
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <gudev/gudev.h>
|
||||
#endif
|
||||
|
||||
#include "backends/meta-input-device-private.h"
|
||||
#include "meta-input-mapper-private.h"
|
||||
#include "meta-monitor-manager-private.h"
|
||||
#include "meta-logical-monitor.h"
|
||||
@ -59,6 +60,7 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_MATCH_CONFIG, /* Specified by config */
|
||||
META_MATCH_IS_BUILTIN, /* Output is builtin, applies mainly to system-integrated devices */
|
||||
META_MATCH_SIZE, /* Size from input device and output match */
|
||||
META_MATCH_EDID_FULL, /* Full EDID model match, eg. "Cintiq 12WX" */
|
||||
@ -72,6 +74,7 @@ struct _MetaMapperInputInfo
|
||||
ClutterInputDevice *device;
|
||||
MetaInputMapper *mapper;
|
||||
MetaMapperOutputInfo *output;
|
||||
GSettings *settings;
|
||||
guint builtin : 1;
|
||||
};
|
||||
|
||||
@ -99,24 +102,149 @@ struct _DeviceCandidates
|
||||
enum
|
||||
{
|
||||
DEVICE_MAPPED,
|
||||
DEVICE_ENABLED,
|
||||
DEVICE_ASPECT_RATIO,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals[N_SIGNALS] = { 0, };
|
||||
|
||||
static void mapper_recalculate_input (MetaInputMapper *mapper,
|
||||
MetaMapperInputInfo *input);
|
||||
|
||||
G_DEFINE_TYPE (MetaInputMapper, meta_input_mapper, G_TYPE_OBJECT)
|
||||
|
||||
static GSettings *
|
||||
get_device_settings (ClutterInputDevice *device)
|
||||
{
|
||||
const gchar *group, *schema, *vendor, *product;
|
||||
ClutterInputDeviceType type;
|
||||
GSettings *settings;
|
||||
gchar *path;
|
||||
|
||||
type = clutter_input_device_get_device_type (device);
|
||||
|
||||
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||
{
|
||||
group = "touchscreens";
|
||||
schema = "org.gnome.desktop.peripherals.touchscreen";
|
||||
}
|
||||
else if (type == CLUTTER_TABLET_DEVICE ||
|
||||
type == CLUTTER_PEN_DEVICE ||
|
||||
type == CLUTTER_ERASER_DEVICE ||
|
||||
type == CLUTTER_CURSOR_DEVICE ||
|
||||
type == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
group = "tablets";
|
||||
schema = "org.gnome.desktop.peripherals.tablet";
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
vendor = clutter_input_device_get_vendor_id (device);
|
||||
product = clutter_input_device_get_product_id (device);
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/%s/%s:%s/",
|
||||
group, vendor, product);
|
||||
|
||||
settings = g_settings_new_with_path (schema, path);
|
||||
g_free (path);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static MetaMonitor *
|
||||
logical_monitor_find_monitor (MetaLogicalMonitor *logical_monitor,
|
||||
const char *vendor,
|
||||
const char *product,
|
||||
const char *serial)
|
||||
{
|
||||
GList *monitors;
|
||||
GList *l;
|
||||
|
||||
monitors = meta_logical_monitor_get_monitors (logical_monitor);
|
||||
for (l = monitors; l; l = l->next)
|
||||
{
|
||||
MetaMonitor *monitor = l->data;
|
||||
|
||||
if (g_strcmp0 (meta_monitor_get_vendor (monitor), vendor) == 0 &&
|
||||
g_strcmp0 (meta_monitor_get_product (monitor), product) == 0 &&
|
||||
g_strcmp0 (meta_monitor_get_serial (monitor), serial) == 0)
|
||||
return monitor;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
find_settings_monitor (MetaInputMapper *mapper,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaMonitor **out_monitor,
|
||||
MetaLogicalMonitor **out_logical_monitor)
|
||||
{
|
||||
MetaMonitor *monitor;
|
||||
guint n_values;
|
||||
GList *logical_monitors;
|
||||
GList *l;
|
||||
gchar **edid;
|
||||
|
||||
edid = g_settings_get_strv (settings, "output");
|
||||
n_values = g_strv_length (edid);
|
||||
|
||||
if (n_values != 3)
|
||||
{
|
||||
g_warning ("EDID configuration for device '%s' "
|
||||
"is incorrect, must have 3 values",
|
||||
clutter_input_device_get_device_name (device));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!*edid[0] && !*edid[1] && !*edid[2])
|
||||
goto out;
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (mapper->monitor_manager);
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
|
||||
monitor = logical_monitor_find_monitor (logical_monitor,
|
||||
edid[0], edid[1], edid[2]);
|
||||
if (monitor)
|
||||
{
|
||||
if (out_monitor)
|
||||
*out_monitor = monitor;
|
||||
if (out_logical_monitor)
|
||||
*out_logical_monitor = logical_monitor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
g_strfreev (edid);
|
||||
}
|
||||
|
||||
static void
|
||||
settings_output_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
MetaMapperInputInfo *info)
|
||||
{
|
||||
mapper_recalculate_input (info->mapper, info);
|
||||
}
|
||||
|
||||
static MetaMapperInputInfo *
|
||||
mapper_input_info_new (ClutterInputDevice *device,
|
||||
MetaInputMapper *mapper,
|
||||
gboolean builtin)
|
||||
MetaInputMapper *mapper)
|
||||
{
|
||||
MetaMapperInputInfo *info;
|
||||
|
||||
info = g_new0 (MetaMapperInputInfo, 1);
|
||||
info->mapper = mapper;
|
||||
info->device = device;
|
||||
info->builtin = builtin;
|
||||
info->settings = get_device_settings (device);
|
||||
|
||||
g_signal_connect (info->settings, "changed::output",
|
||||
G_CALLBACK (settings_output_changed_cb), info);
|
||||
|
||||
return info;
|
||||
}
|
||||
@ -124,6 +252,7 @@ mapper_input_info_new (ClutterInputDevice *device,
|
||||
static void
|
||||
mapper_input_info_free (MetaMapperInputInfo *info)
|
||||
{
|
||||
g_object_unref (info->settings);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
@ -174,13 +303,36 @@ mapper_input_info_set_output (MetaMapperInputInfo *input,
|
||||
MetaMapperOutputInfo *output,
|
||||
MetaMonitor *monitor)
|
||||
{
|
||||
MetaInputMapper *mapper = input->mapper;
|
||||
float matrix[6] = { 1, 0, 0, 0, 1, 0 };
|
||||
double aspect_ratio;
|
||||
int width, height;
|
||||
|
||||
if (input->output == output)
|
||||
return;
|
||||
|
||||
input->output = output;
|
||||
|
||||
if (output && monitor)
|
||||
{
|
||||
meta_monitor_manager_get_monitor_matrix (mapper->monitor_manager,
|
||||
monitor,
|
||||
output->logical_monitor,
|
||||
matrix);
|
||||
meta_monitor_get_current_resolution (monitor, &width, &height);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_monitor_manager_get_screen_size (mapper->monitor_manager,
|
||||
&width, &height);
|
||||
}
|
||||
|
||||
aspect_ratio = (double) width / height;
|
||||
|
||||
g_signal_emit (input->mapper, signals[DEVICE_MAPPED], 0,
|
||||
input->device,
|
||||
output ? output->logical_monitor : NULL, monitor);
|
||||
input->device, matrix);
|
||||
g_signal_emit (input->mapper, signals[DEVICE_ASPECT_RATIO], 0,
|
||||
input->device, aspect_ratio);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -361,6 +513,32 @@ guess_candidates (MetaInputMapper *mapper,
|
||||
MetaOutputMatchType best = N_OUTPUT_MATCHES;
|
||||
GList *monitors, *l;
|
||||
MetaMonitor *matched_monitor = NULL;
|
||||
gboolean builtin = FALSE;
|
||||
gboolean integrated = TRUE;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (clutter_input_device_get_device_type (input->device) != CLUTTER_TOUCHSCREEN_DEVICE)
|
||||
{
|
||||
WacomDevice *wacom_device;
|
||||
WacomIntegrationFlags flags = 0;
|
||||
|
||||
wacom_device =
|
||||
meta_input_device_get_wacom_device (META_INPUT_DEVICE (input->device));
|
||||
|
||||
if (wacom_device)
|
||||
{
|
||||
flags = libwacom_get_integration_flags (wacom_device);
|
||||
|
||||
if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
|
||||
WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0)
|
||||
return;
|
||||
|
||||
integrated = (flags & (WACOM_DEVICE_INTEGRATED_SYSTEM |
|
||||
WACOM_DEVICE_INTEGRATED_DISPLAY)) != 0;
|
||||
builtin = (flags & WACOM_DEVICE_INTEGRATED_SYSTEM) != 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
monitors = meta_monitor_manager_get_monitors (mapper->monitor_manager);
|
||||
|
||||
@ -375,18 +553,23 @@ guess_candidates (MetaInputMapper *mapper,
|
||||
}
|
||||
}
|
||||
|
||||
if (find_size_match (input, monitors, &matched_monitor))
|
||||
if (integrated && find_size_match (input, monitors, &matched_monitor))
|
||||
{
|
||||
best = MIN (best, META_MATCH_SIZE);
|
||||
info->candidates[META_MATCH_SIZE] = matched_monitor;
|
||||
}
|
||||
|
||||
if (input->builtin || best == N_OUTPUT_MATCHES)
|
||||
if (builtin || best == N_OUTPUT_MATCHES)
|
||||
{
|
||||
best = MIN (best, META_MATCH_IS_BUILTIN);
|
||||
find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]);
|
||||
}
|
||||
|
||||
find_settings_monitor (mapper, input->settings, input->device,
|
||||
&info->candidates[META_MATCH_CONFIG], NULL);
|
||||
if (info->candidates[META_MATCH_CONFIG])
|
||||
best = MIN (best, META_MATCH_CONFIG);
|
||||
|
||||
info->best = best;
|
||||
}
|
||||
|
||||
@ -524,6 +707,37 @@ input_mapper_monitors_changed_cb (MetaMonitorManager *monitor_manager,
|
||||
mapper_update_outputs (mapper);
|
||||
}
|
||||
|
||||
static void
|
||||
input_mapper_power_save_mode_changed_cb (MetaMonitorManager *monitor_manager,
|
||||
MetaInputMapper *mapper)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
MetaMonitor *builtin;
|
||||
MetaPowerSave power_save_mode;
|
||||
gboolean on;
|
||||
|
||||
power_save_mode =
|
||||
meta_monitor_manager_get_power_save_mode (mapper->monitor_manager);
|
||||
on = power_save_mode == META_POWER_SAVE_ON;
|
||||
|
||||
if (!find_builtin_output (mapper, &builtin))
|
||||
return;
|
||||
|
||||
logical_monitor = meta_monitor_get_logical_monitor (builtin);
|
||||
if (!logical_monitor)
|
||||
return;
|
||||
|
||||
device =
|
||||
meta_input_mapper_get_logical_monitor_device (mapper,
|
||||
logical_monitor,
|
||||
CLUTTER_TOUCHSCREEN_DEVICE);
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
g_signal_emit (mapper, signals[DEVICE_ENABLED], 0, device, on);
|
||||
}
|
||||
|
||||
static void
|
||||
input_mapper_device_removed_cb (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
@ -576,6 +790,9 @@ meta_input_mapper_constructed (GObject *object)
|
||||
mapper->monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
g_signal_connect (mapper->monitor_manager, "monitors-changed-internal",
|
||||
G_CALLBACK (input_mapper_monitors_changed_cb), mapper);
|
||||
g_signal_connect (mapper->monitor_manager, "power-save-mode-changed",
|
||||
G_CALLBACK (input_mapper_power_save_mode_changed_cb),
|
||||
mapper);
|
||||
|
||||
mapper_update_outputs (mapper);
|
||||
}
|
||||
@ -594,9 +811,27 @@ meta_input_mapper_class_init (MetaInputMapperClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 3,
|
||||
G_TYPE_NONE, 2,
|
||||
CLUTTER_TYPE_INPUT_DEVICE,
|
||||
G_TYPE_POINTER, G_TYPE_POINTER);
|
||||
G_TYPE_POINTER);
|
||||
signals[DEVICE_ENABLED] =
|
||||
g_signal_new ("device-enabled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2,
|
||||
CLUTTER_TYPE_INPUT_DEVICE,
|
||||
G_TYPE_BOOLEAN);
|
||||
signals[DEVICE_ASPECT_RATIO] =
|
||||
g_signal_new ("device-aspect-ratio",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 2,
|
||||
CLUTTER_TYPE_INPUT_DEVICE,
|
||||
G_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -618,8 +853,7 @@ meta_input_mapper_new (void)
|
||||
|
||||
void
|
||||
meta_input_mapper_add_device (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device,
|
||||
gboolean builtin)
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaMapperInputInfo *info;
|
||||
|
||||
@ -629,7 +863,7 @@ meta_input_mapper_add_device (MetaInputMapper *mapper,
|
||||
if (g_hash_table_contains (mapper->input_devices, device))
|
||||
return;
|
||||
|
||||
info = mapper_input_info_new (device, mapper, builtin);
|
||||
info = mapper_input_info_new (device, mapper);
|
||||
g_hash_table_insert (mapper->input_devices, device, info);
|
||||
mapper_recalculate_input (mapper, info);
|
||||
}
|
||||
@ -676,6 +910,43 @@ meta_input_mapper_get_logical_monitor_device (MetaInputMapper *mapper,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ClutterInputDevice *
|
||||
find_grouped_pen (ClutterInputDevice *device)
|
||||
{
|
||||
GList *l, *devices;
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterInputDevice *pen = NULL;
|
||||
ClutterSeat *seat;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
|
||||
if (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE)
|
||||
return device;
|
||||
|
||||
seat = clutter_input_device_get_seat (device);
|
||||
devices = clutter_seat_list_devices (seat);
|
||||
|
||||
for (l = devices; l; l = l->next)
|
||||
{
|
||||
ClutterInputDevice *other_device = l->data;
|
||||
|
||||
device_type = clutter_input_device_get_device_type (other_device);
|
||||
|
||||
if ((device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE) &&
|
||||
clutter_input_device_is_grouped (device, other_device))
|
||||
{
|
||||
pen = other_device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free (devices);
|
||||
|
||||
return pen;
|
||||
}
|
||||
|
||||
MetaLogicalMonitor *
|
||||
meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device)
|
||||
@ -685,6 +956,13 @@ meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper,
|
||||
GHashTableIter iter;
|
||||
GList *l;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
device = find_grouped_pen (device);
|
||||
if (!device)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, mapper->output_devices);
|
||||
|
||||
while (g_hash_table_iter_next (&iter, (gpointer *) &logical_monitor,
|
||||
@ -701,3 +979,19 @@ meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper,
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GSettings *
|
||||
meta_input_mapper_get_tablet_settings (MetaInputMapper *mapper,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaMapperInputInfo *input;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_MAPPER (mapper), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL);
|
||||
|
||||
input = g_hash_table_lookup (mapper->input_devices, device);
|
||||
if (!input)
|
||||
return NULL;
|
||||
|
||||
return input->settings;
|
||||
}
|
||||
|
@ -36,6 +36,62 @@
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaInputSettings, meta_input_settings,
|
||||
META, INPUT_SETTINGS, GObject)
|
||||
|
||||
/**
|
||||
* MetaKeyboardA11yFlags:
|
||||
* @CLUTTER_A11Y_KEYBOARD_ENABLED:
|
||||
* @CLUTTER_A11Y_TIMEOUT_ENABLED:
|
||||
* @CLUTTER_A11Y_MOUSE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT:
|
||||
* @CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT:
|
||||
* @CLUTTER_A11Y_TOGGLE_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_ENABLED:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF:
|
||||
* @CLUTTER_A11Y_STICKY_KEYS_BEEP:
|
||||
* @CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP:
|
||||
*
|
||||
* Keyboard accessibility features applied to a ClutterInputDevice keyboard.
|
||||
*
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_A11Y_KEYBOARD_ENABLED = 1 << 0,
|
||||
META_A11Y_TIMEOUT_ENABLED = 1 << 1,
|
||||
META_A11Y_MOUSE_KEYS_ENABLED = 1 << 2,
|
||||
META_A11Y_SLOW_KEYS_ENABLED = 1 << 3,
|
||||
META_A11Y_SLOW_KEYS_BEEP_PRESS = 1 << 4,
|
||||
META_A11Y_SLOW_KEYS_BEEP_ACCEPT = 1 << 5,
|
||||
META_A11Y_SLOW_KEYS_BEEP_REJECT = 1 << 6,
|
||||
META_A11Y_BOUNCE_KEYS_ENABLED = 1 << 7,
|
||||
META_A11Y_BOUNCE_KEYS_BEEP_REJECT = 1 << 8,
|
||||
META_A11Y_TOGGLE_KEYS_ENABLED = 1 << 9,
|
||||
META_A11Y_STICKY_KEYS_ENABLED = 1 << 10,
|
||||
META_A11Y_STICKY_KEYS_TWO_KEY_OFF = 1 << 11,
|
||||
META_A11Y_STICKY_KEYS_BEEP = 1 << 12,
|
||||
META_A11Y_FEATURE_STATE_CHANGE_BEEP = 1 << 13,
|
||||
} MetaKeyboardA11yFlags;
|
||||
|
||||
/**
|
||||
* MetaKbdA11ySettings:
|
||||
*
|
||||
* The #MetaKbdA11ySettings structure contains keyboard accessibility
|
||||
* settings
|
||||
*
|
||||
*/
|
||||
typedef struct _MetaKbdA11ySettings
|
||||
{
|
||||
MetaKeyboardA11yFlags controls;
|
||||
gint slowkeys_delay;
|
||||
gint debounce_delay;
|
||||
gint timeout_delay;
|
||||
gint mousekeys_init_delay;
|
||||
gint mousekeys_max_speed;
|
||||
gint mousekeys_accel_time;
|
||||
} MetaKbdA11ySettings;
|
||||
|
||||
struct _MetaInputSettingsClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
@ -92,10 +148,9 @@ struct _MetaInputSettingsClass
|
||||
void (* set_tablet_mapping) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping);
|
||||
void (* set_tablet_keep_aspect) (MetaInputSettings *settings,
|
||||
void (* set_tablet_aspect_ratio) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaLogicalMonitor *logical_monitor,
|
||||
gboolean keep_aspect);
|
||||
double ratio);
|
||||
void (* set_tablet_area) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gdouble padding_left,
|
||||
@ -137,26 +192,31 @@ struct _MetaInputSettingsClass
|
||||
ClutterInputDevice *device);
|
||||
};
|
||||
|
||||
GSettings * meta_input_settings_get_tablet_settings (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
MetaLogicalMonitor * meta_input_settings_get_tablet_logical_monitor (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GDesktopTabletMapping meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
gboolean meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
||||
gboolean meta_input_settings_handle_pad_event (MetaInputSettings *input_settings,
|
||||
const ClutterEvent *event);
|
||||
gchar * meta_input_settings_get_pad_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action,
|
||||
guint number);
|
||||
|
||||
void meta_input_settings_maybe_save_numlock_state (MetaInputSettings *input_settings);
|
||||
void meta_input_settings_maybe_restore_numlock_state (MetaInputSettings *input_settings);
|
||||
|
||||
void meta_input_settings_set_device_matrix (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
float matrix[6]);
|
||||
void meta_input_settings_set_device_enabled (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
gboolean enabled);
|
||||
void meta_input_settings_set_device_aspect_ratio (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
double aspect_ratio);
|
||||
|
||||
void meta_input_settings_get_kbd_a11y_settings (MetaInputSettings *input_settings,
|
||||
MetaKbdA11ySettings *a11y_settings);
|
||||
|
||||
void meta_input_settings_add_device (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device);
|
||||
void meta_input_settings_remove_device (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device);
|
||||
void meta_input_settings_notify_tool_change (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
void meta_input_settings_notify_kbd_a11y_change (MetaInputSettings *input_settings,
|
||||
MetaKeyboardA11yFlags new_flags,
|
||||
MetaKeyboardA11yFlags what_changed);
|
||||
|
||||
#endif /* META_INPUT_SETTINGS_PRIVATE_H */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -31,6 +31,7 @@
|
||||
#include "backends/meta-cursor.h"
|
||||
#include "backends/meta-display-config-shared.h"
|
||||
#include "backends/meta-monitor-transform.h"
|
||||
#include "backends/meta-viewport-info.h"
|
||||
#include "core/util-private.h"
|
||||
#include "meta/display.h"
|
||||
#include "meta/meta-monitor-manager.h"
|
||||
@ -405,4 +406,6 @@ meta_find_output_assignment (MetaOutputAssignment **outputs,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaViewportInfo * meta_monitor_manager_get_viewports (MetaMonitorManager *manager);
|
||||
|
||||
#endif /* META_MONITOR_MANAGER_PRIVATE_H */
|
||||
|
@ -3175,3 +3175,37 @@ meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager,
|
||||
|
||||
return gnome_pnp_ids_get_pnp_id (manager->pnp_ids, vendor);
|
||||
}
|
||||
|
||||
MetaViewportInfo *
|
||||
meta_monitor_manager_get_viewports (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaViewportInfo *info;
|
||||
GArray *views, *scales;
|
||||
GList *logical_monitors, *l;
|
||||
|
||||
views = g_array_new (FALSE, FALSE, sizeof (cairo_rectangle_int_t));
|
||||
scales = g_array_new (FALSE, FALSE, sizeof (float));
|
||||
|
||||
logical_monitors = meta_monitor_manager_get_logical_monitors (manager);
|
||||
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
cairo_rectangle_int_t rect;
|
||||
float scale;
|
||||
|
||||
rect = logical_monitor->rect;
|
||||
g_array_append_val (views, rect);
|
||||
|
||||
scale = logical_monitor->scale;
|
||||
g_array_append_val (scales, scale);
|
||||
}
|
||||
|
||||
info = meta_viewport_info_new ((cairo_rectangle_int_t *) views->data,
|
||||
(float *) scales->data,
|
||||
views->len);
|
||||
g_array_unref (views);
|
||||
g_array_unref (scales);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
@ -39,8 +39,19 @@
|
||||
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-pointer-constraint-native.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
struct _MetaPointerConstraint
|
||||
{
|
||||
GObject parent_instance;
|
||||
cairo_region_t *region;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaPointerConstraint, meta_pointer_constraint, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
@ -53,9 +64,40 @@ meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
MetaPointerConstraint *
|
||||
meta_pointer_constraint_new (const cairo_region_t *region)
|
||||
{
|
||||
MetaPointerConstraint *constraint;
|
||||
|
||||
constraint = g_object_new (META_TYPE_POINTER_CONSTRAINT, NULL);
|
||||
constraint->region = cairo_region_copy (region);
|
||||
|
||||
return constraint;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
meta_pointer_constraint_get_region (MetaPointerConstraint *constraint)
|
||||
{
|
||||
return constraint->region;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE (MetaPointerConstraintImpl, meta_pointer_constraint_impl,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_init (MetaPointerConstraintImpl *impl)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_class_init (MetaPointerConstraintImplClass *klass)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_pointer_constraint_constrain:
|
||||
* @constraint: a #MetaPointerConstraint.
|
||||
* meta_pointer_constraint_impl_constrain:
|
||||
* @impl: a #MetaPointerConstraintImpl.
|
||||
* @device; the device of the pointer.
|
||||
* @time: the timestamp (in ms) of the event.
|
||||
* @prev_x: X-coordinate of the previous pointer position.
|
||||
@ -67,17 +109,25 @@ meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass)
|
||||
* if needed.
|
||||
*/
|
||||
void
|
||||
meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
|
||||
meta_pointer_constraint_impl_constrain (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
uint32_t time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
META_POINTER_CONSTRAINT_GET_CLASS (constraint)->constrain (constraint,
|
||||
META_POINTER_CONSTRAINT_IMPL_GET_CLASS (impl)->constrain (impl,
|
||||
device,
|
||||
time,
|
||||
prev_x, prev_y,
|
||||
x, y);
|
||||
}
|
||||
|
||||
void
|
||||
meta_pointer_constraint_impl_ensure_constrained (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
META_POINTER_CONSTRAINT_IMPL_GET_CLASS (impl)->ensure_constrained (impl,
|
||||
device);
|
||||
}
|
||||
|
@ -32,34 +32,45 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_POINTER_CONSTRAINT (meta_pointer_constraint_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraint, meta_pointer_constraint,
|
||||
G_DECLARE_FINAL_TYPE (MetaPointerConstraint, meta_pointer_constraint,
|
||||
META, POINTER_CONSTRAINT, GObject);
|
||||
|
||||
MetaPointerConstraint * meta_pointer_constraint_new (const cairo_region_t *region);
|
||||
cairo_region_t * meta_pointer_constraint_get_region (MetaPointerConstraint *constraint);
|
||||
|
||||
#define META_TYPE_POINTER_CONSTRAINT_IMPL (meta_pointer_constraint_impl_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaPointerConstraintImpl, meta_pointer_constraint_impl,
|
||||
META, POINTER_CONSTRAINT_IMPL, GObject);
|
||||
|
||||
/**
|
||||
* MetaPointerConstraintClass:
|
||||
* MetaPointerConstraintImplClass:
|
||||
* @constrain: the virtual function pointer for
|
||||
* meta_pointer_constraint_constrain().
|
||||
* meta_pointer_constraint_impl_constrain().
|
||||
*/
|
||||
struct _MetaPointerConstraintClass
|
||||
struct _MetaPointerConstraintImplClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (*constrain) (MetaPointerConstraint *constraint,
|
||||
void (* constrain) (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
uint32_t time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y);
|
||||
void (* ensure_constrained) (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device);
|
||||
};
|
||||
|
||||
void meta_pointer_constraint_constrain (MetaPointerConstraint *constraint,
|
||||
void meta_pointer_constraint_impl_constrain (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
uint32_t time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y);
|
||||
void meta_pointer_constraint_impl_ensure_constrained (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -83,19 +83,6 @@ get_backend (MetaScreenCastAreaStreamSrc *area_src)
|
||||
return meta_screen_cast_get_backend (screen_cast);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
get_cursor_renderer (MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
|
||||
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
MetaBackend *backend = meta_screen_cast_get_backend (screen_cast);
|
||||
|
||||
return meta_backend_get_cursor_renderer (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_area_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
||||
int *width,
|
||||
@ -142,9 +129,11 @@ is_cursor_in_stream (MetaScreenCastAreaStreamSrc *area_src)
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
graphene_point_t cursor_position;
|
||||
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
return graphene_rect_contains_point (&area_rect, &cursor_position);
|
||||
}
|
||||
}
|
||||
@ -184,8 +173,6 @@ sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
|
||||
|
||||
static void
|
||||
cursor_moved (MetaCursorTracker *cursor_tracker,
|
||||
float x,
|
||||
float y,
|
||||
MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
sync_cursor_state (area_src);
|
||||
@ -202,14 +189,14 @@ cursor_changed (MetaCursorTracker *cursor_tracker,
|
||||
static void
|
||||
inhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaHwCursorInhibitor *inhibitor;
|
||||
MetaBackend *backend;
|
||||
|
||||
g_return_if_fail (!area_src->hw_cursor_inhibited);
|
||||
|
||||
cursor_renderer = get_cursor_renderer (area_src);
|
||||
backend = get_backend (area_src);
|
||||
inhibitor = META_HW_CURSOR_INHIBITOR (area_src);
|
||||
meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||
meta_backend_add_hw_cursor_inhibitor (backend, inhibitor);
|
||||
|
||||
area_src->hw_cursor_inhibited = TRUE;
|
||||
}
|
||||
@ -217,14 +204,14 @@ inhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src)
|
||||
static void
|
||||
uninhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaHwCursorInhibitor *inhibitor;
|
||||
MetaBackend *backend;
|
||||
|
||||
g_return_if_fail (area_src->hw_cursor_inhibited);
|
||||
|
||||
cursor_renderer = get_cursor_renderer (area_src);
|
||||
backend = get_backend (area_src);
|
||||
inhibitor = META_HW_CURSOR_INHIBITOR (area_src);
|
||||
meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||
meta_backend_remove_hw_cursor_inhibitor (backend, inhibitor);
|
||||
|
||||
area_src->hw_cursor_inhibited = FALSE;
|
||||
}
|
||||
@ -506,6 +493,8 @@ meta_screen_cast_area_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *s
|
||||
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
|
||||
MetaBackend *backend = get_backend (area_src);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
@ -526,7 +515,7 @@ meta_screen_cast_area_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *s
|
||||
area = meta_screen_cast_area_stream_get_area (area_stream);
|
||||
scale = meta_screen_cast_area_stream_get_scale (area_stream);
|
||||
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
cursor_position.x -= area->x;
|
||||
cursor_position.y -= area->y;
|
||||
cursor_position.x *= scale;
|
||||
@ -568,8 +557,7 @@ meta_screen_cast_area_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *s
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_area_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
meta_screen_cast_area_stream_src_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaScreenCastAreaStreamSrc *area_src =
|
||||
META_SCREEN_CAST_AREA_STREAM_SRC (inhibitor);
|
||||
@ -580,8 +568,8 @@ meta_screen_cast_area_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhibit
|
||||
static void
|
||||
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface)
|
||||
{
|
||||
iface->is_cursor_sprite_inhibited =
|
||||
meta_screen_cast_area_stream_src_is_cursor_sprite_inhibited;
|
||||
iface->is_cursor_inhibited =
|
||||
meta_screen_cast_area_stream_src_is_cursor_inhibited;
|
||||
}
|
||||
|
||||
MetaScreenCastAreaStreamSrc *
|
||||
|
@ -170,9 +170,11 @@ is_cursor_in_stream (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
graphene_point_t cursor_position;
|
||||
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
return graphene_rect_contains_point (&logical_monitor_rect,
|
||||
&cursor_position);
|
||||
}
|
||||
@ -221,8 +223,6 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
|
||||
static void
|
||||
cursor_moved (MetaCursorTracker *cursor_tracker,
|
||||
float x,
|
||||
float y,
|
||||
MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
sync_cursor_state (monitor_src);
|
||||
@ -236,30 +236,17 @@ cursor_changed (MetaCursorTracker *cursor_tracker,
|
||||
sync_cursor_state (monitor_src);
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
get_cursor_renderer (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||
MetaScreenCast *screen_cast =
|
||||
meta_screen_cast_session_get_screen_cast (session);
|
||||
MetaBackend *backend = meta_screen_cast_get_backend (screen_cast);
|
||||
|
||||
return meta_backend_get_cursor_renderer (backend);
|
||||
}
|
||||
|
||||
static void
|
||||
inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaHwCursorInhibitor *inhibitor;
|
||||
MetaBackend *backend;
|
||||
|
||||
g_return_if_fail (!monitor_src->hw_cursor_inhibited);
|
||||
|
||||
cursor_renderer = get_cursor_renderer (monitor_src);
|
||||
backend = get_backend (monitor_src);
|
||||
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
|
||||
meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||
meta_backend_add_hw_cursor_inhibitor (backend, inhibitor);
|
||||
|
||||
monitor_src->hw_cursor_inhibited = TRUE;
|
||||
}
|
||||
@ -267,14 +254,14 @@ inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
static void
|
||||
uninhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaHwCursorInhibitor *inhibitor;
|
||||
MetaBackend *backend;
|
||||
|
||||
g_return_if_fail (monitor_src->hw_cursor_inhibited);
|
||||
|
||||
cursor_renderer = get_cursor_renderer (monitor_src);
|
||||
backend = get_backend (monitor_src);
|
||||
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
|
||||
meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||
meta_backend_remove_hw_cursor_inhibitor (backend, inhibitor);
|
||||
|
||||
monitor_src->hw_cursor_inhibited = FALSE;
|
||||
}
|
||||
@ -598,6 +585,8 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
|
||||
MetaBackend *backend = get_backend (monitor_src);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
MetaMonitor *monitor;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
@ -627,7 +616,7 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
|
||||
else
|
||||
view_scale = 1.0;
|
||||
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
cursor_position.x -= logical_monitor_rect.origin.x;
|
||||
cursor_position.y -= logical_monitor_rect.origin.y;
|
||||
cursor_position.x *= view_scale;
|
||||
@ -669,8 +658,7 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_monitor_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
meta_screen_cast_monitor_stream_src_is_cursor_inhibited (MetaHwCursorInhibitor *inhibitor)
|
||||
{
|
||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (inhibitor);
|
||||
@ -681,8 +669,8 @@ meta_screen_cast_monitor_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhi
|
||||
static void
|
||||
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface)
|
||||
{
|
||||
iface->is_cursor_sprite_inhibited =
|
||||
meta_screen_cast_monitor_stream_src_is_cursor_sprite_inhibited;
|
||||
iface->is_cursor_inhibited =
|
||||
meta_screen_cast_monitor_stream_src_is_cursor_inhibited;
|
||||
}
|
||||
|
||||
MetaScreenCastMonitorStreamSrc *
|
||||
|
@ -110,6 +110,8 @@ maybe_draw_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
||||
MetaBackend *backend = get_backend (window_src);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
CoglTexture *cursor_texture;
|
||||
MetaScreenCastWindow *screen_cast_window;
|
||||
@ -133,7 +135,7 @@ maybe_draw_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
||||
return;
|
||||
|
||||
screen_cast_window = window_src->screen_cast_window;
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window,
|
||||
cursor_sprite,
|
||||
&cursor_position,
|
||||
@ -189,6 +191,8 @@ maybe_blit_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
||||
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaScreenCastWindow *screen_cast_window;
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
graphene_point_t relative_cursor_position;
|
||||
@ -209,7 +213,7 @@ maybe_blit_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src,
|
||||
return;
|
||||
|
||||
screen_cast_window = window_src->screen_cast_window;
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window,
|
||||
cursor_sprite,
|
||||
&cursor_position,
|
||||
@ -360,13 +364,15 @@ is_cursor_in_stream (MetaScreenCastWindowStreamSrc *window_src)
|
||||
MetaBackend *backend = get_backend (window_src);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
graphene_point_t cursor_position;
|
||||
MetaScreenCastWindow *screen_cast_window;
|
||||
|
||||
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
||||
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
|
||||
screen_cast_window = window_src->screen_cast_window;
|
||||
return meta_screen_cast_window_transform_cursor_position (screen_cast_window,
|
||||
@ -394,8 +400,6 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
||||
|
||||
static void
|
||||
cursor_moved (MetaCursorTracker *cursor_tracker,
|
||||
float x,
|
||||
float y,
|
||||
MetaScreenCastWindowStreamSrc *window_src)
|
||||
{
|
||||
sync_cursor_state (window_src);
|
||||
@ -541,6 +545,8 @@ meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
|
||||
MetaBackend *backend = get_backend (window_src);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaScreenCastWindow *screen_cast_window = window_src->screen_cast_window;
|
||||
MetaCursorSprite *cursor_sprite;
|
||||
graphene_point_t cursor_position;
|
||||
@ -549,7 +555,7 @@ meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
|
||||
int x, y;
|
||||
|
||||
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
||||
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &cursor_position, NULL);
|
||||
|
||||
if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window,
|
||||
cursor_sprite,
|
||||
|
212
src/backends/meta-viewport-info.c
Normal file
212
src/backends/meta-viewport-info.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-viewport-info.h"
|
||||
#include "core/main-private.h"
|
||||
#include "core/boxes-private.h"
|
||||
|
||||
typedef struct _ViewInfo ViewInfo;
|
||||
|
||||
struct _ViewInfo
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
float scale;
|
||||
};
|
||||
|
||||
struct _MetaViewportInfo
|
||||
{
|
||||
GObject parent_class;
|
||||
GArray *views;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaViewportInfo, meta_viewport_info, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_viewport_info_finalize (GObject *object)
|
||||
{
|
||||
MetaViewportInfo *info = META_VIEWPORT_INFO (object);
|
||||
|
||||
g_array_unref (info->views);
|
||||
|
||||
G_OBJECT_CLASS (meta_viewport_info_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_viewport_info_class_init (MetaViewportInfoClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_viewport_info_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_viewport_info_init (MetaViewportInfo *info)
|
||||
{
|
||||
info->views = g_array_new (FALSE, FALSE, sizeof (ViewInfo));
|
||||
}
|
||||
|
||||
MetaViewportInfo *
|
||||
meta_viewport_info_new (cairo_rectangle_int_t *views,
|
||||
float *scales,
|
||||
guint n_views)
|
||||
{
|
||||
MetaViewportInfo *viewport_info;
|
||||
int i;
|
||||
|
||||
viewport_info = g_object_new (META_TYPE_VIEWPORT_INFO, NULL);
|
||||
|
||||
for (i = 0; i < n_views; i++)
|
||||
{
|
||||
ViewInfo info;
|
||||
|
||||
info.rect = views[i];
|
||||
info.scale = scales[i];
|
||||
g_array_append_val (viewport_info->views, info);
|
||||
}
|
||||
|
||||
return viewport_info;
|
||||
}
|
||||
|
||||
int
|
||||
meta_viewport_info_get_view_at (MetaViewportInfo *viewport_info,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < viewport_info->views->len; i++)
|
||||
{
|
||||
ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i);
|
||||
|
||||
if (META_POINT_IN_RECT (x, y, info->rect))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_viewport_info_get_view (MetaViewportInfo *viewport_info,
|
||||
int idx,
|
||||
cairo_rectangle_int_t *rect,
|
||||
float *scale)
|
||||
{
|
||||
ViewInfo *info;
|
||||
|
||||
if (idx < 0 || idx >= viewport_info->views->len)
|
||||
return FALSE;
|
||||
|
||||
info = &g_array_index (viewport_info->views, ViewInfo, idx);
|
||||
if (rect)
|
||||
*rect = info->rect;
|
||||
if (scale)
|
||||
*scale = info->scale;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
view_has_neighbor (cairo_rectangle_int_t *view,
|
||||
cairo_rectangle_int_t *neighbor,
|
||||
MetaDisplayDirection neighbor_direction)
|
||||
{
|
||||
switch (neighbor_direction)
|
||||
{
|
||||
case META_DISPLAY_RIGHT:
|
||||
if (neighbor->x == (view->x + view->width) &&
|
||||
meta_rectangle_vert_overlap (neighbor, view))
|
||||
return TRUE;
|
||||
break;
|
||||
case META_DISPLAY_LEFT:
|
||||
if (view->x == (neighbor->x + neighbor->width) &&
|
||||
meta_rectangle_vert_overlap (neighbor, view))
|
||||
return TRUE;
|
||||
break;
|
||||
case META_DISPLAY_UP:
|
||||
if (view->y == (neighbor->y + neighbor->height) &&
|
||||
meta_rectangle_horiz_overlap (neighbor, view))
|
||||
return TRUE;
|
||||
break;
|
||||
case META_DISPLAY_DOWN:
|
||||
if (neighbor->y == (view->y + view->height) &&
|
||||
meta_rectangle_horiz_overlap (neighbor, view))
|
||||
return TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
meta_viewport_info_get_neighbor (MetaViewportInfo *viewport_info,
|
||||
int idx,
|
||||
MetaDisplayDirection direction)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int i;
|
||||
|
||||
if (!meta_viewport_info_get_view (viewport_info, idx, &rect, NULL))
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < viewport_info->views->len; i++)
|
||||
{
|
||||
ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i);
|
||||
|
||||
if (idx == i)
|
||||
continue;
|
||||
if (view_has_neighbor (&rect, &info->rect, direction))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
meta_viewport_info_get_num_views (MetaViewportInfo *info)
|
||||
{
|
||||
return info->views->len;
|
||||
}
|
||||
|
||||
void
|
||||
meta_viewport_info_get_extents (MetaViewportInfo *viewport_info,
|
||||
float *width,
|
||||
float *height)
|
||||
{
|
||||
int min_x = G_MAXINT, min_y = G_MAXINT, max_x = G_MININT, max_y = G_MININT, i;
|
||||
|
||||
for (i = 0; i < viewport_info->views->len; i++)
|
||||
{
|
||||
ViewInfo *info = &g_array_index (viewport_info->views, ViewInfo, i);
|
||||
|
||||
min_x = MIN (min_x, info->rect.x);
|
||||
max_x = MAX (max_x, info->rect.x + info->rect.width);
|
||||
min_y = MIN (min_y, info->rect.y);
|
||||
max_y = MAX (max_y, info->rect.y + info->rect.height);
|
||||
}
|
||||
|
||||
if (width)
|
||||
*width = (float) max_x - min_x;
|
||||
if (height)
|
||||
*height = (float) max_y - min_y;
|
||||
}
|
57
src/backends/meta-viewport-info.h
Normal file
57
src/backends/meta-viewport-info.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_VIEWPORT_INFO_H
|
||||
#define META_VIEWPORT_INFO_H
|
||||
|
||||
#include <cairo.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "meta/display.h"
|
||||
|
||||
#define META_TYPE_VIEWPORT_INFO (meta_viewport_info_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaViewportInfo, meta_viewport_info,
|
||||
META, VIEWPORT_INFO, GObject)
|
||||
|
||||
MetaViewportInfo * meta_viewport_info_new (cairo_rectangle_int_t *views,
|
||||
float *scales,
|
||||
guint n_views);
|
||||
|
||||
int meta_viewport_info_get_view_at (MetaViewportInfo *info,
|
||||
float x,
|
||||
float y);
|
||||
|
||||
gboolean meta_viewport_info_get_view (MetaViewportInfo *viewport_info,
|
||||
int idx,
|
||||
cairo_rectangle_int_t *rect,
|
||||
float *scale);
|
||||
|
||||
int meta_viewport_info_get_neighbor (MetaViewportInfo *info,
|
||||
int idx,
|
||||
MetaDisplayDirection direction);
|
||||
int meta_viewport_info_get_num_views (MetaViewportInfo *info);
|
||||
|
||||
void meta_viewport_info_get_extents (MetaViewportInfo *info,
|
||||
float *width,
|
||||
float *height);
|
||||
|
||||
#endif /* META_VIEWPORT_INFO_H */
|
@ -22,5 +22,6 @@
|
||||
#define META_BACKEND_NATIVE_TYPES_H
|
||||
|
||||
typedef struct _MetaBackendNative MetaBackendNative;
|
||||
typedef struct _MetaSeatNative MetaSeatNative;
|
||||
|
||||
#endif /* META_BACKEND_NATIVE_TYPES_H */
|
||||
|
@ -48,10 +48,9 @@
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "backends/meta-settings-private.h"
|
||||
#include "backends/meta-stage-private.h"
|
||||
#include "backends/native/meta-barrier-native.h"
|
||||
#include "backends/native/meta-clutter-backend-native.h"
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#include "backends/native/meta-event-native.h"
|
||||
#include "backends/native/meta-input-device-native.h"
|
||||
#include "backends/native/meta-input-settings-native.h"
|
||||
#include "backends/native/meta-kms.h"
|
||||
#include "backends/native/meta-kms-device.h"
|
||||
@ -71,7 +70,7 @@ struct _MetaBackendNative
|
||||
MetaLauncher *launcher;
|
||||
MetaUdev *udev;
|
||||
MetaKms *kms;
|
||||
MetaBarrierManagerNative *barrier_manager;
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
gulong udev_device_added_handler_id;
|
||||
};
|
||||
@ -99,239 +98,11 @@ meta_backend_native_finalize (GObject *object)
|
||||
g_clear_object (&native->udev);
|
||||
g_clear_object (&native->kms);
|
||||
meta_launcher_free (native->launcher);
|
||||
g_clear_object (&native->input_settings);
|
||||
|
||||
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_to_barriers (ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float *new_x,
|
||||
float *new_y)
|
||||
{
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (meta_get_backend ());
|
||||
|
||||
meta_barrier_manager_native_process (native->barrier_manager,
|
||||
device,
|
||||
time,
|
||||
new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
constrain_to_client_constraint (ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaPointerConstraint *constraint =
|
||||
meta_backend_get_client_pointer_constraint (backend);
|
||||
|
||||
if (!constraint)
|
||||
return;
|
||||
|
||||
meta_pointer_constraint_constrain (constraint, device,
|
||||
time, prev_x, prev_y, x, y);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pointer constrain code is mostly a rip-off of the XRandR code from Xorg.
|
||||
* (from xserver/randr/rrcrtc.c, RRConstrainCursorHarder)
|
||||
*
|
||||
* Copyright © 2006 Keith Packard
|
||||
* Copyright 2010 Red Hat, Inc
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
constrain_all_screen_monitors (ClutterInputDevice *device,
|
||||
MetaMonitorManager *monitor_manager,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
graphene_point_t current;
|
||||
float cx, cy;
|
||||
GList *logical_monitors, *l;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||
|
||||
cx = current.x;
|
||||
cy = current.y;
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
int left, right, top, bottom;
|
||||
|
||||
left = logical_monitor->rect.x;
|
||||
right = left + logical_monitor->rect.width;
|
||||
top = logical_monitor->rect.y;
|
||||
bottom = top + logical_monitor->rect.height;
|
||||
|
||||
if ((cx >= left) && (cx < right) && (cy >= top) && (cy < bottom))
|
||||
{
|
||||
if (*x < left)
|
||||
*x = left;
|
||||
if (*x >= right)
|
||||
*x = right - 1;
|
||||
if (*y < top)
|
||||
*y = top;
|
||||
if (*y >= bottom)
|
||||
*y = bottom - 1;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_constrain_callback (ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *new_x,
|
||||
float *new_y,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
|
||||
/* Constrain to barriers */
|
||||
constrain_to_barriers (device, time, new_x, new_y);
|
||||
|
||||
/* Constrain to pointer lock */
|
||||
constrain_to_client_constraint (device, time, prev_x, prev_y, new_x, new_y);
|
||||
|
||||
/* if we're moving inside a monitor, we're fine */
|
||||
if (meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
*new_x, *new_y))
|
||||
return;
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
constrain_all_screen_monitors (device, monitor_manager, new_x, new_y);
|
||||
}
|
||||
|
||||
static void
|
||||
relative_motion_across_outputs (MetaMonitorManager *monitor_manager,
|
||||
MetaLogicalMonitor *current,
|
||||
float cur_x,
|
||||
float cur_y,
|
||||
float *dx_inout,
|
||||
float *dy_inout)
|
||||
{
|
||||
MetaLogicalMonitor *cur = current;
|
||||
float x = cur_x, y = cur_y;
|
||||
float target_x = cur_x, target_y = cur_y;
|
||||
float dx = *dx_inout, dy = *dy_inout;
|
||||
MetaDisplayDirection direction = -1;
|
||||
|
||||
while (cur)
|
||||
{
|
||||
MetaLine2 left, right, top, bottom, motion;
|
||||
MetaVector2 intersection;
|
||||
|
||||
motion = (MetaLine2) {
|
||||
.a = { x, y },
|
||||
.b = { x + (dx * cur->scale), y + (dy * cur->scale) }
|
||||
};
|
||||
left = (MetaLine2) {
|
||||
{ cur->rect.x, cur->rect.y },
|
||||
{ cur->rect.x, cur->rect.y + cur->rect.height }
|
||||
};
|
||||
right = (MetaLine2) {
|
||||
{ cur->rect.x + cur->rect.width, cur->rect.y },
|
||||
{ cur->rect.x + cur->rect.width, cur->rect.y + cur->rect.height }
|
||||
};
|
||||
top = (MetaLine2) {
|
||||
{ cur->rect.x, cur->rect.y },
|
||||
{ cur->rect.x + cur->rect.width, cur->rect.y }
|
||||
};
|
||||
bottom = (MetaLine2) {
|
||||
{ cur->rect.x, cur->rect.y + cur->rect.height },
|
||||
{ cur->rect.x + cur->rect.width, cur->rect.y + cur->rect.height }
|
||||
};
|
||||
|
||||
target_x = motion.b.x;
|
||||
target_y = motion.b.y;
|
||||
|
||||
if (direction != META_DISPLAY_RIGHT &&
|
||||
meta_line2_intersects_with (&motion, &left, &intersection))
|
||||
direction = META_DISPLAY_LEFT;
|
||||
else if (direction != META_DISPLAY_LEFT &&
|
||||
meta_line2_intersects_with (&motion, &right, &intersection))
|
||||
direction = META_DISPLAY_RIGHT;
|
||||
else if (direction != META_DISPLAY_DOWN &&
|
||||
meta_line2_intersects_with (&motion, &top, &intersection))
|
||||
direction = META_DISPLAY_UP;
|
||||
else if (direction != META_DISPLAY_UP &&
|
||||
meta_line2_intersects_with (&motion, &bottom, &intersection))
|
||||
direction = META_DISPLAY_DOWN;
|
||||
else
|
||||
/* We reached the dest logical monitor */
|
||||
break;
|
||||
|
||||
x = intersection.x;
|
||||
y = intersection.y;
|
||||
dx -= intersection.x - motion.a.x;
|
||||
dy -= intersection.y - motion.a.y;
|
||||
|
||||
cur = meta_monitor_manager_get_logical_monitor_neighbor (monitor_manager,
|
||||
cur, direction);
|
||||
}
|
||||
|
||||
*dx_inout = target_x - cur_x;
|
||||
*dy_inout = target_y - cur_y;
|
||||
}
|
||||
|
||||
static void
|
||||
relative_motion_filter (ClutterInputDevice *device,
|
||||
float x,
|
||||
float y,
|
||||
float *dx,
|
||||
float *dy,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager = user_data;
|
||||
MetaLogicalMonitor *logical_monitor, *dest_logical_monitor;
|
||||
float new_dx, new_dy;
|
||||
|
||||
if (meta_is_stage_views_scaled ())
|
||||
return;
|
||||
|
||||
logical_monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
x, y);
|
||||
if (!logical_monitor)
|
||||
return;
|
||||
|
||||
new_dx = (*dx) * logical_monitor->scale;
|
||||
new_dy = (*dy) * logical_monitor->scale;
|
||||
|
||||
dest_logical_monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
x + new_dx,
|
||||
y + new_dy);
|
||||
if (dest_logical_monitor &&
|
||||
dest_logical_monitor != logical_monitor)
|
||||
{
|
||||
/* If we are crossing monitors, attempt to bisect the distance on each
|
||||
* axis and apply the relative scale for each of them.
|
||||
*/
|
||||
new_dx = *dx;
|
||||
new_dy = *dy;
|
||||
relative_motion_across_outputs (monitor_manager, logical_monitor,
|
||||
x, y, &new_dx, &new_dy);
|
||||
}
|
||||
|
||||
*dx = new_dx;
|
||||
*dy = new_dy;
|
||||
}
|
||||
|
||||
static ClutterBackend *
|
||||
meta_backend_native_create_clutter_backend (MetaBackend *backend)
|
||||
{
|
||||
@ -339,18 +110,47 @@ meta_backend_native_create_clutter_backend (MetaBackend *backend)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_post_init (MetaBackend *backend)
|
||||
update_viewports (MetaBackend *backend)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
|
||||
MetaViewportInfo *viewports;
|
||||
|
||||
viewports = meta_monitor_manager_get_viewports (monitor_manager);
|
||||
meta_seat_native_set_viewports (seat, viewports);
|
||||
g_object_unref (viewports);
|
||||
}
|
||||
|
||||
static void
|
||||
kbd_a11y_changed_cb (MetaInputSettings *input_settings,
|
||||
MetaKbdA11ySettings *a11y_settings,
|
||||
MetaBackend *backend)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
||||
ClutterInputDevice *device;
|
||||
|
||||
meta_seat_native_set_pointer_constrain_callback (META_SEAT_NATIVE (seat),
|
||||
pointer_constrain_callback,
|
||||
NULL, NULL);
|
||||
meta_seat_native_set_relative_motion_filter (META_SEAT_NATIVE (seat),
|
||||
relative_motion_filter,
|
||||
meta_backend_get_monitor_manager (backend));
|
||||
device = clutter_seat_get_keyboard (seat);
|
||||
if (device)
|
||||
meta_input_device_native_apply_kbd_a11y_settings (META_INPUT_DEVICE_NATIVE (device),
|
||||
a11y_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
|
||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
|
||||
|
||||
native->input_settings = meta_seat_impl_get_input_settings (seat->impl);
|
||||
g_signal_connect_object (native->input_settings, "kbd-a11y-changed",
|
||||
G_CALLBACK (kbd_a11y_changed_cb), backend, 0);
|
||||
|
||||
META_BACKEND_CLASS (meta_backend_native_parent_class)->post_init (backend);
|
||||
|
||||
@ -368,6 +168,8 @@ meta_backend_native_post_init (MetaBackend *backend)
|
||||
g_warning ("Failed to set RT scheduler: %m");
|
||||
}
|
||||
|
||||
update_viewports (backend);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
meta_backend_init_wayland (backend);
|
||||
#endif
|
||||
@ -377,15 +179,26 @@ static MetaMonitorManager *
|
||||
meta_backend_native_create_monitor_manager (MetaBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
return g_initable_new (META_TYPE_MONITOR_MANAGER_KMS, NULL, error,
|
||||
MetaMonitorManager *manager;
|
||||
|
||||
manager = g_initable_new (META_TYPE_MONITOR_MANAGER_KMS, NULL, error,
|
||||
"backend", backend,
|
||||
NULL);
|
||||
g_signal_connect_swapped (manager, "monitors-changed-internal",
|
||||
G_CALLBACK (update_viewports), backend);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_native_create_cursor_renderer (MetaBackend *backend)
|
||||
meta_backend_native_get_cursor_renderer (MetaBackend *backend,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return META_CURSOR_RENDERER (meta_cursor_renderer_native_new (backend));
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
META_SEAT_NATIVE (clutter_backend_get_default_seat (clutter_backend));
|
||||
|
||||
return meta_seat_native_get_cursor_renderer (seat, device);
|
||||
}
|
||||
|
||||
static MetaRenderer *
|
||||
@ -405,7 +218,9 @@ meta_backend_native_create_renderer (MetaBackend *backend,
|
||||
static MetaInputSettings *
|
||||
meta_backend_native_create_input_settings (MetaBackend *backend)
|
||||
{
|
||||
return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE, NULL);
|
||||
MetaBackendNative *native = META_BACKEND_NATIVE (backend);
|
||||
|
||||
return native->input_settings;
|
||||
}
|
||||
|
||||
static MetaLogicalMonitor *
|
||||
@ -414,10 +229,11 @@ meta_backend_native_get_current_logical_monitor (MetaBackend *backend)
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
int x, y;
|
||||
graphene_point_t point;
|
||||
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
|
||||
return meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
|
||||
return meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
point.x, point.y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -427,27 +243,13 @@ meta_backend_native_set_keymap (MetaBackend *backend,
|
||||
const char *options)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
struct xkb_rule_names names;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_context *context;
|
||||
ClutterSeat *seat;
|
||||
|
||||
names.rules = DEFAULT_XKB_RULES_FILE;
|
||||
names.model = DEFAULT_XKB_MODEL;
|
||||
names.layout = layouts;
|
||||
names.variant = variants;
|
||||
names.options = options;
|
||||
|
||||
context = meta_create_xkb_context ();
|
||||
keymap = xkb_keymap_new_from_names (context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
xkb_context_unref (context);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat), keymap);
|
||||
meta_seat_native_set_keyboard_map (META_SEAT_NATIVE (seat),
|
||||
layouts, variants, options);
|
||||
|
||||
meta_backend_notify_keymap_changed (backend);
|
||||
|
||||
xkb_keymap_unref (keymap);
|
||||
}
|
||||
|
||||
static struct xkb_keymap *
|
||||
@ -499,6 +301,25 @@ meta_backend_native_set_numlock (MetaBackend *backend,
|
||||
numlock_state);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_set_pointer_constraint (MetaBackend *backend,
|
||||
MetaPointerConstraint *constraint)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
MetaPointerConstraintImpl *constraint_impl = NULL;
|
||||
cairo_region_t *region;
|
||||
|
||||
if (constraint)
|
||||
{
|
||||
region = meta_pointer_constraint_get_region (constraint);
|
||||
constraint_impl = meta_pointer_constraint_impl_native_new (constraint, region);
|
||||
}
|
||||
|
||||
meta_seat_native_set_pointer_constraint (META_SEAT_NATIVE (seat),
|
||||
constraint_impl);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_native_update_screen_size (MetaBackend *backend,
|
||||
int width, int height)
|
||||
@ -662,7 +483,6 @@ meta_backend_native_initable_init (GInitable *initable,
|
||||
#endif
|
||||
|
||||
native->udev = meta_udev_new (native);
|
||||
native->barrier_manager = meta_barrier_manager_native_new ();
|
||||
|
||||
native->kms = meta_kms_new (META_BACKEND (native), error);
|
||||
if (!native->kms)
|
||||
@ -695,7 +515,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
backend_class->post_init = meta_backend_native_post_init;
|
||||
|
||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||
backend_class->get_cursor_renderer = meta_backend_native_get_cursor_renderer;
|
||||
backend_class->create_renderer = meta_backend_native_create_renderer;
|
||||
backend_class->create_input_settings = meta_backend_native_create_input_settings;
|
||||
|
||||
@ -707,6 +527,8 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
||||
backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
|
||||
backend_class->update_screen_size = meta_backend_native_update_screen_size;
|
||||
backend_class->set_numlock = meta_backend_native_set_numlock;
|
||||
|
||||
backend_class->set_pointer_constraint = meta_backend_native_set_pointer_constraint;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -742,12 +564,6 @@ meta_activate_vt (int vt, GError **error)
|
||||
return meta_launcher_activate_vt (launcher, vt, error);
|
||||
}
|
||||
|
||||
MetaBarrierManagerNative *
|
||||
meta_backend_native_get_barrier_manager (MetaBackendNative *native)
|
||||
{
|
||||
return native->barrier_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_activate_session:
|
||||
*
|
||||
@ -809,7 +625,6 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerKms *monitor_manager_kms =
|
||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||
MetaInputSettings *input_settings;
|
||||
MetaIdleMonitor *idle_monitor;
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
MetaSeatNative *seat =
|
||||
@ -831,8 +646,7 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
||||
idle_monitor = meta_idle_monitor_get_core ();
|
||||
meta_idle_monitor_reset_idletime (idle_monitor);
|
||||
|
||||
input_settings = meta_backend_get_input_settings (backend);
|
||||
meta_input_settings_maybe_restore_numlock_state (input_settings);
|
||||
meta_input_settings_maybe_restore_numlock_state (native->input_settings);
|
||||
|
||||
clutter_seat_ensure_a11y_state (CLUTTER_SEAT (seat));
|
||||
}
|
||||
|
@ -36,14 +36,14 @@
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-barrier-private.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-backend-native-private.h"
|
||||
#include "backends/native/meta-seat-native.h"
|
||||
#include "meta/barrier.h"
|
||||
#include "meta/util.h"
|
||||
|
||||
struct _MetaBarrierManagerNative
|
||||
{
|
||||
GHashTable *barriers;
|
||||
GMutex mutex;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
@ -78,6 +78,7 @@ struct _MetaBarrierImplNative
|
||||
int trigger_serial;
|
||||
guint32 last_event_time;
|
||||
MetaBarrierDirection blocked_dir;
|
||||
GMainContext *context;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaBarrierImplNative,
|
||||
@ -341,6 +342,48 @@ typedef struct _MetaBarrierEventData
|
||||
float dy;
|
||||
} MetaBarrierEventData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaBarrierEvent *event;
|
||||
MetaBarrier *barrier;
|
||||
MetaBarrierState state;
|
||||
} MetaBarrierIdleData;
|
||||
|
||||
static gboolean
|
||||
emit_event_idle (MetaBarrierIdleData *idle_data)
|
||||
{
|
||||
if (idle_data->state == META_BARRIER_STATE_HELD)
|
||||
_meta_barrier_emit_hit_signal (idle_data->barrier, idle_data->event);
|
||||
else
|
||||
_meta_barrier_emit_left_signal (idle_data->barrier, idle_data->event);
|
||||
|
||||
meta_barrier_event_unref (idle_data->event);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_event (MetaBarrierImplNative *self,
|
||||
MetaBarrierEvent *event)
|
||||
{
|
||||
MetaBarrierIdleData *idle_data;
|
||||
GSource *source;
|
||||
|
||||
idle_data = g_new0 (MetaBarrierIdleData, 1);
|
||||
idle_data->state = self->state;
|
||||
idle_data->barrier = self->barrier;
|
||||
idle_data->event = event;
|
||||
|
||||
source = g_idle_source_new ();
|
||||
g_source_set_priority (source, G_PRIORITY_HIGH);
|
||||
g_source_set_callback (source,
|
||||
(GSourceFunc) emit_event_idle,
|
||||
idle_data,
|
||||
g_free);
|
||||
|
||||
g_source_attach (source, self->context);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_barrier_event (MetaBarrierImplNative *self,
|
||||
guint32 time,
|
||||
@ -351,7 +394,6 @@ emit_barrier_event (MetaBarrierImplNative *self,
|
||||
float dx,
|
||||
float dy)
|
||||
{
|
||||
MetaBarrier *barrier = self->barrier;
|
||||
MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
|
||||
MetaBarrierState old_state = self->state;
|
||||
|
||||
@ -390,12 +432,7 @@ emit_barrier_event (MetaBarrierImplNative *self,
|
||||
|
||||
self->last_event_time = time;
|
||||
|
||||
if (self->state == META_BARRIER_STATE_HELD)
|
||||
_meta_barrier_emit_hit_signal (barrier, event);
|
||||
else
|
||||
_meta_barrier_emit_left_signal (barrier, event);
|
||||
|
||||
meta_barrier_event_unref (event);
|
||||
emit_event (self, event);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -480,6 +517,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
|
||||
if (!clutter_input_device_get_coords (device, NULL, &prev_pos))
|
||||
return;
|
||||
|
||||
g_mutex_lock (&manager->mutex);
|
||||
|
||||
prev_x = prev_pos.x;
|
||||
prev_y = prev_pos.y;
|
||||
|
||||
@ -524,6 +563,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
|
||||
g_hash_table_foreach (manager->barriers,
|
||||
maybe_emit_barrier_event,
|
||||
&barrier_event_data);
|
||||
|
||||
g_mutex_unlock (&manager->mutex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -550,7 +591,10 @@ _meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
|
||||
{
|
||||
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
|
||||
|
||||
g_mutex_lock (&self->manager->mutex);
|
||||
g_hash_table_remove (self->manager->barriers, self);
|
||||
g_mutex_unlock (&self->manager->mutex);
|
||||
g_main_context_unref (self->context);
|
||||
self->is_active = FALSE;
|
||||
}
|
||||
|
||||
@ -558,18 +602,21 @@ MetaBarrierImpl *
|
||||
meta_barrier_impl_native_new (MetaBarrier *barrier)
|
||||
{
|
||||
MetaBarrierImplNative *self;
|
||||
MetaBackendNative *native;
|
||||
MetaBarrierManagerNative *manager;
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
||||
|
||||
self = g_object_new (META_TYPE_BARRIER_IMPL_NATIVE, NULL);
|
||||
|
||||
self->barrier = barrier;
|
||||
self->is_active = TRUE;
|
||||
self->context = g_main_context_ref_thread_default ();
|
||||
|
||||
native = META_BACKEND_NATIVE (meta_get_backend ());
|
||||
manager = meta_backend_native_get_barrier_manager (native);
|
||||
manager = meta_seat_native_get_barrier_manager (META_SEAT_NATIVE (seat));
|
||||
self->manager = manager;
|
||||
g_mutex_lock (&manager->mutex);
|
||||
g_hash_table_add (manager->barriers, self);
|
||||
g_mutex_unlock (&manager->mutex);
|
||||
|
||||
return META_BARRIER_IMPL (self);
|
||||
}
|
||||
@ -597,6 +644,7 @@ meta_barrier_manager_native_new (void)
|
||||
manager = g_new0 (MetaBarrierManagerNative, 1);
|
||||
|
||||
manager->barriers = g_hash_table_new (NULL, NULL);
|
||||
g_mutex_init (&manager->mutex);
|
||||
|
||||
return manager;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -26,6 +26,7 @@
|
||||
#define META_CURSOR_RENDERER_NATIVE_H
|
||||
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
#include "backends/native/meta-kms-cursor-renderer.h"
|
||||
#include "meta/meta-backend.h"
|
||||
|
||||
#define META_TYPE_CURSOR_RENDERER_NATIVE (meta_cursor_renderer_native_get_type ())
|
||||
@ -33,6 +34,10 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native,
|
||||
META, CURSOR_RENDERER_NATIVE,
|
||||
MetaCursorRenderer)
|
||||
|
||||
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend);
|
||||
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_cursor_renderer_native_set_kms_cursor_renderer (MetaCursorRendererNative *native,
|
||||
MetaKmsCursorRenderer *kms_cursor_renderer);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
||||
|
@ -24,9 +24,10 @@
|
||||
#include <math.h>
|
||||
#include <cairo-gobject.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/native/meta-input-device-tool-native.h"
|
||||
#include "backends/native/meta-input-device-native.h"
|
||||
#include "backends/native/meta-seat-native.h"
|
||||
#include "backends/native/meta-seat-impl.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaInputDeviceNative,
|
||||
@ -61,19 +62,11 @@ meta_input_device_native_finalize (GObject *object)
|
||||
{
|
||||
ClutterInputDevice *device = CLUTTER_INPUT_DEVICE (object);
|
||||
MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (object);
|
||||
ClutterBackend *backend;
|
||||
ClutterSeat *seat;
|
||||
|
||||
if (device_evdev->libinput_device)
|
||||
libinput_device_unref (device_evdev->libinput_device);
|
||||
|
||||
meta_input_device_native_release_touch_slots (device_evdev,
|
||||
g_get_monotonic_time ());
|
||||
g_clear_pointer (&device_evdev->touches, g_hash_table_unref);
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
meta_seat_native_release_device_id (META_SEAT_NATIVE (seat), device);
|
||||
meta_seat_impl_release_device_id (device_evdev->seat_impl, device);
|
||||
|
||||
clear_slow_keys (device_evdev);
|
||||
stop_bounce_keys (device_evdev);
|
||||
@ -225,7 +218,7 @@ meta_input_device_native_is_grouped (ClutterInputDevice *device,
|
||||
static void
|
||||
meta_input_device_native_bell_notify (MetaInputDeviceNative *device)
|
||||
{
|
||||
clutter_seat_bell_notify (CLUTTER_SEAT (device->seat));
|
||||
meta_seat_impl_notify_bell (device->seat_impl);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -250,10 +243,11 @@ static guint
|
||||
get_slow_keys_delay (ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device);
|
||||
ClutterKbdA11ySettings a11y_settings;
|
||||
MetaKbdA11ySettings a11y_settings;
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
clutter_seat_get_kbd_a11y_settings (CLUTTER_SEAT (device_native->seat),
|
||||
&a11y_settings);
|
||||
input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl);
|
||||
meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings);
|
||||
/* Settings use int, we use uint, make sure we dont go negative */
|
||||
return MAX (0, a11y_settings.slowkeys_delay);
|
||||
}
|
||||
@ -274,7 +268,7 @@ trigger_slow_keys (gpointer data)
|
||||
device->slow_keys_list = g_list_remove (device->slow_keys_list, slow_keys_event);
|
||||
meta_input_device_native_free_pending_slow_key (slow_keys_event);
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT)
|
||||
if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_ACCEPT)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
@ -312,7 +306,7 @@ start_slow_keys (ClutterEvent *event,
|
||||
slow_keys_event);
|
||||
device->slow_keys_list = g_list_append (device->slow_keys_list, slow_keys_event);
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS)
|
||||
if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_PRESS)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
}
|
||||
|
||||
@ -332,7 +326,7 @@ stop_slow_keys (ClutterEvent *event,
|
||||
device->slow_keys_list = g_list_delete_link (device->slow_keys_list, item);
|
||||
meta_input_device_native_free_pending_slow_key (slow_keys_event);
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT)
|
||||
if (device->a11y_flags & META_A11Y_SLOW_KEYS_BEEP_REJECT)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
|
||||
return;
|
||||
@ -346,10 +340,11 @@ static guint
|
||||
get_debounce_delay (ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device);
|
||||
ClutterKbdA11ySettings a11y_settings;
|
||||
MetaKbdA11ySettings a11y_settings;
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
clutter_seat_get_kbd_a11y_settings (CLUTTER_SEAT (device_native->seat),
|
||||
&a11y_settings);
|
||||
input_settings = meta_seat_impl_get_input_settings (device_native->seat_impl);
|
||||
meta_input_settings_get_kbd_a11y_settings (input_settings, &a11y_settings);
|
||||
/* Settings use int, we use uint, make sure we dont go negative */
|
||||
return MAX (0, a11y_settings.debounce_delay);
|
||||
}
|
||||
@ -387,7 +382,7 @@ stop_bounce_keys (MetaInputDeviceNative *device)
|
||||
static void
|
||||
notify_bounce_keys_reject (MetaInputDeviceNative *device)
|
||||
{
|
||||
if (device->a11y_flags & CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT)
|
||||
if (device->a11y_flags & META_A11Y_BOUNCE_KEYS_BEEP_REJECT)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
}
|
||||
|
||||
@ -426,8 +421,7 @@ key_event_is_modifier (ClutterEvent *event)
|
||||
static void
|
||||
notify_stickykeys_mask (MetaInputDeviceNative *device)
|
||||
{
|
||||
g_signal_emit_by_name (device->seat,
|
||||
"kbd-a11y-mods-state-changed",
|
||||
meta_seat_impl_notify_kbd_a11y_mods_state_changed (device->seat_impl,
|
||||
device->stickykeys_latched_mask,
|
||||
device->stickykeys_locked_mask);
|
||||
}
|
||||
@ -437,15 +431,19 @@ update_internal_xkb_state (MetaInputDeviceNative *device,
|
||||
xkb_mod_mask_t new_latched_mask,
|
||||
xkb_mod_mask_t new_locked_mask)
|
||||
{
|
||||
MetaSeatNative *seat = device->seat;
|
||||
MetaSeatImpl *seat_impl = device->seat_impl;
|
||||
xkb_mod_mask_t depressed_mods;
|
||||
xkb_mod_mask_t latched_mods;
|
||||
xkb_mod_mask_t locked_mods;
|
||||
xkb_mod_mask_t group_mods;
|
||||
struct xkb_state *xkb_state;
|
||||
|
||||
depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||
latched_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED);
|
||||
g_rw_lock_writer_lock (&seat_impl->state_lock);
|
||||
|
||||
xkb_state = meta_seat_impl_get_xkb_state (seat_impl);
|
||||
depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||
latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED);
|
||||
|
||||
latched_mods &= ~device->stickykeys_latched_mask;
|
||||
locked_mods &= ~device->stickykeys_locked_mask;
|
||||
@ -456,14 +454,16 @@ update_internal_xkb_state (MetaInputDeviceNative *device,
|
||||
latched_mods |= device->stickykeys_latched_mask;
|
||||
locked_mods |= device->stickykeys_locked_mask;
|
||||
|
||||
group_mods = xkb_state_serialize_layout (seat->xkb, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
group_mods = xkb_state_serialize_layout (xkb_state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
|
||||
xkb_state_update_mask (seat->xkb,
|
||||
xkb_state_update_mask (xkb_state,
|
||||
depressed_mods,
|
||||
latched_mods,
|
||||
locked_mods,
|
||||
0, 0, group_mods);
|
||||
notify_stickykeys_mask (device);
|
||||
|
||||
g_rw_lock_writer_unlock (&seat_impl->state_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -472,23 +472,25 @@ update_stickykeys_event (ClutterEvent *event,
|
||||
xkb_mod_mask_t new_latched_mask,
|
||||
xkb_mod_mask_t new_locked_mask)
|
||||
{
|
||||
MetaSeatNative *seat = device->seat;
|
||||
MetaSeatImpl *seat_impl = device->seat_impl;
|
||||
xkb_mod_mask_t effective_mods;
|
||||
xkb_mod_mask_t latched_mods;
|
||||
xkb_mod_mask_t locked_mods;
|
||||
struct xkb_state *xkb_state;
|
||||
|
||||
update_internal_xkb_state (device, new_latched_mask, new_locked_mask);
|
||||
|
||||
effective_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_EFFECTIVE);
|
||||
latched_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_LOCKED);
|
||||
xkb_state = meta_seat_impl_get_xkb_state (seat_impl);
|
||||
effective_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_EFFECTIVE);
|
||||
latched_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LATCHED);
|
||||
locked_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_LOCKED);
|
||||
|
||||
_clutter_event_set_state_full (event,
|
||||
seat->button_state,
|
||||
seat_impl->button_state,
|
||||
device->stickykeys_depressed_mask,
|
||||
latched_mods,
|
||||
locked_mods,
|
||||
effective_mods | seat->button_state);
|
||||
effective_mods | seat_impl->button_state);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -498,23 +500,22 @@ notify_stickykeys_change (MetaInputDeviceNative *device)
|
||||
device->stickykeys_depressed_mask = 0;
|
||||
update_internal_xkb_state (device, 0, 0);
|
||||
|
||||
g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->seat,
|
||||
"kbd-a11y-flags-changed",
|
||||
meta_seat_impl_notify_kbd_a11y_flags_changed (device->seat_impl,
|
||||
device->a11y_flags,
|
||||
CLUTTER_A11Y_STICKY_KEYS_ENABLED);
|
||||
META_A11Y_STICKY_KEYS_ENABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
set_stickykeys_off (MetaInputDeviceNative *device)
|
||||
{
|
||||
device->a11y_flags &= ~CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
device->a11y_flags &= ~META_A11Y_STICKY_KEYS_ENABLED;
|
||||
notify_stickykeys_change (device);
|
||||
}
|
||||
|
||||
static void
|
||||
set_stickykeys_on (MetaInputDeviceNative *device)
|
||||
{
|
||||
device->a11y_flags |= CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
device->a11y_flags |= META_A11Y_STICKY_KEYS_ENABLED;
|
||||
notify_stickykeys_change (device);
|
||||
}
|
||||
|
||||
@ -529,45 +530,45 @@ clear_stickykeys_event (ClutterEvent *event,
|
||||
static void
|
||||
set_slowkeys_off (MetaInputDeviceNative *device)
|
||||
{
|
||||
device->a11y_flags &= ~CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
device->a11y_flags &= ~META_A11Y_SLOW_KEYS_ENABLED;
|
||||
|
||||
g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->seat,
|
||||
"kbd-a11y-flags-changed",
|
||||
meta_seat_impl_notify_kbd_a11y_flags_changed (device->seat_impl,
|
||||
device->a11y_flags,
|
||||
CLUTTER_A11Y_SLOW_KEYS_ENABLED);
|
||||
META_A11Y_SLOW_KEYS_ENABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
set_slowkeys_on (MetaInputDeviceNative *device)
|
||||
{
|
||||
device->a11y_flags |= CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
device->a11y_flags |= META_A11Y_SLOW_KEYS_ENABLED;
|
||||
|
||||
g_signal_emit_by_name (CLUTTER_INPUT_DEVICE (device)->seat,
|
||||
"kbd-a11y-flags-changed",
|
||||
meta_seat_impl_notify_kbd_a11y_flags_changed (device->seat_impl,
|
||||
device->a11y_flags,
|
||||
CLUTTER_A11Y_SLOW_KEYS_ENABLED);
|
||||
META_A11Y_SLOW_KEYS_ENABLED);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_stickykeys_press (ClutterEvent *event,
|
||||
MetaInputDeviceNative *device)
|
||||
{
|
||||
MetaSeatNative *seat = device->seat;
|
||||
MetaSeatImpl *seat_impl = device->seat_impl;
|
||||
xkb_mod_mask_t depressed_mods;
|
||||
xkb_mod_mask_t new_latched_mask;
|
||||
xkb_mod_mask_t new_locked_mask;
|
||||
struct xkb_state *xkb_state;
|
||||
|
||||
if (!key_event_is_modifier (event))
|
||||
return;
|
||||
|
||||
if (device->stickykeys_depressed_mask &&
|
||||
(device->a11y_flags & CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF))
|
||||
(device->a11y_flags & META_A11Y_STICKY_KEYS_TWO_KEY_OFF))
|
||||
{
|
||||
clear_stickykeys_event (event, device);
|
||||
return;
|
||||
}
|
||||
|
||||
depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||
xkb_state = meta_seat_impl_get_xkb_state (seat_impl);
|
||||
depressed_mods = xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||
/* Ignore the lock modifier mask, that one cannot be sticky, yet the
|
||||
* CAPS_LOCK key itself counts as a modifier as it might be remapped
|
||||
* to some other modifier which can be sticky.
|
||||
@ -600,14 +601,16 @@ static void
|
||||
handle_stickykeys_release (ClutterEvent *event,
|
||||
MetaInputDeviceNative *device)
|
||||
{
|
||||
MetaSeatNative *seat = device->seat;
|
||||
MetaSeatImpl *seat_impl = device->seat_impl;
|
||||
struct xkb_state *xkb_state;
|
||||
|
||||
xkb_state = meta_seat_impl_get_xkb_state (seat_impl);
|
||||
device->stickykeys_depressed_mask =
|
||||
xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||
xkb_state_serialize_mods (xkb_state, XKB_STATE_MODS_DEPRESSED);
|
||||
|
||||
if (key_event_is_modifier (event))
|
||||
{
|
||||
if (device->a11y_flags & CLUTTER_A11Y_STICKY_KEYS_BEEP)
|
||||
if (device->a11y_flags & META_A11Y_STICKY_KEYS_BEEP)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
|
||||
return;
|
||||
@ -626,10 +629,10 @@ trigger_toggle_slowkeys (gpointer data)
|
||||
|
||||
device->toggle_slowkeys_timer = 0;
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP)
|
||||
if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_ENABLED)
|
||||
if (device->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED)
|
||||
set_slowkeys_off (device);
|
||||
else
|
||||
set_slowkeys_on (device);
|
||||
@ -688,10 +691,10 @@ handle_enablekeys_release (ClutterEvent *event,
|
||||
{
|
||||
device->shift_count = 0;
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP)
|
||||
if (device->a11y_flags & META_A11Y_FEATURE_STATE_CHANGE_BEEP)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
|
||||
if (device->a11y_flags & CLUTTER_A11Y_STICKY_KEYS_ENABLED)
|
||||
if (device->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED)
|
||||
set_stickykeys_off (device);
|
||||
else
|
||||
set_stickykeys_on (device);
|
||||
@ -759,7 +762,7 @@ emulate_button_click (MetaInputDeviceNative *device)
|
||||
|
||||
static void
|
||||
update_mousekeys_params (MetaInputDeviceNative *device,
|
||||
ClutterKbdA11ySettings *settings)
|
||||
MetaKbdA11ySettings *settings)
|
||||
{
|
||||
/* Prevent us from broken settings values */
|
||||
device->mousekeys_max_speed = MAX (1, settings->mousekeys_max_speed);
|
||||
@ -841,8 +844,12 @@ emulate_pointer_motion (MetaInputDeviceNative *device_evdev,
|
||||
static gboolean
|
||||
is_numlock_active (MetaInputDeviceNative *device)
|
||||
{
|
||||
MetaSeatNative *seat = device->seat;
|
||||
return xkb_state_mod_name_is_active (seat->xkb,
|
||||
MetaSeatImpl *seat_impl = device->seat_impl;
|
||||
struct xkb_state *xkb_state;
|
||||
|
||||
xkb_state = meta_seat_impl_get_xkb_state (seat_impl);
|
||||
|
||||
return xkb_state_mod_name_is_active (xkb_state,
|
||||
"Mod2",
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
}
|
||||
@ -862,7 +869,7 @@ enable_mousekeys (MetaInputDeviceNative *device_evdev)
|
||||
return;
|
||||
|
||||
device->accessibility_virtual_device =
|
||||
clutter_seat_create_virtual_device (CLUTTER_SEAT (device_evdev->seat),
|
||||
clutter_seat_create_virtual_device (clutter_input_device_get_seat (device),
|
||||
CLUTTER_POINTER_DEVICE);
|
||||
}
|
||||
|
||||
@ -1128,7 +1135,7 @@ meta_input_device_native_process_kbd_a11y_event (ClutterEvent *eve
|
||||
if (event->key.flags & CLUTTER_EVENT_FLAG_INPUT_METHOD)
|
||||
goto emit_event;
|
||||
|
||||
if (device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
||||
if (device_evdev->a11y_flags & META_A11Y_KEYBOARD_ENABLED)
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS)
|
||||
handle_enablekeys_press (event, device_evdev);
|
||||
@ -1136,7 +1143,7 @@ meta_input_device_native_process_kbd_a11y_event (ClutterEvent *eve
|
||||
handle_enablekeys_release (event, device_evdev);
|
||||
}
|
||||
|
||||
if (device_evdev->a11y_flags & CLUTTER_A11Y_MOUSE_KEYS_ENABLED)
|
||||
if (device_evdev->a11y_flags & META_A11Y_MOUSE_KEYS_ENABLED)
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS &&
|
||||
handle_mousekeys_press (event, device_evdev))
|
||||
@ -1146,7 +1153,7 @@ meta_input_device_native_process_kbd_a11y_event (ClutterEvent *eve
|
||||
return; /* swallow event */
|
||||
}
|
||||
|
||||
if ((device_evdev->a11y_flags & CLUTTER_A11Y_BOUNCE_KEYS_ENABLED) &&
|
||||
if ((device_evdev->a11y_flags & META_A11Y_BOUNCE_KEYS_ENABLED) &&
|
||||
(get_debounce_delay (device) != 0))
|
||||
{
|
||||
if ((event->type == CLUTTER_KEY_PRESS) && debounce_key (event, device_evdev))
|
||||
@ -1159,7 +1166,7 @@ meta_input_device_native_process_kbd_a11y_event (ClutterEvent *eve
|
||||
start_bounce_keys (event, device_evdev);
|
||||
}
|
||||
|
||||
if ((device_evdev->a11y_flags & CLUTTER_A11Y_SLOW_KEYS_ENABLED) &&
|
||||
if ((device_evdev->a11y_flags & META_A11Y_SLOW_KEYS_ENABLED) &&
|
||||
(get_slow_keys_delay (device) != 0))
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS)
|
||||
@ -1170,7 +1177,7 @@ meta_input_device_native_process_kbd_a11y_event (ClutterEvent *eve
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_evdev->a11y_flags & CLUTTER_A11Y_STICKY_KEYS_ENABLED)
|
||||
if (device_evdev->a11y_flags & META_A11Y_STICKY_KEYS_ENABLED)
|
||||
{
|
||||
if (event->type == CLUTTER_KEY_PRESS)
|
||||
handle_stickykeys_press (event, device_evdev);
|
||||
@ -1184,33 +1191,33 @@ emit_event:
|
||||
|
||||
void
|
||||
meta_input_device_native_apply_kbd_a11y_settings (MetaInputDeviceNative *device,
|
||||
ClutterKbdA11ySettings *settings)
|
||||
MetaKbdA11ySettings *settings)
|
||||
{
|
||||
ClutterKeyboardA11yFlags changed_flags = (device->a11y_flags ^ settings->controls);
|
||||
MetaKeyboardA11yFlags changed_flags = (device->a11y_flags ^ settings->controls);
|
||||
|
||||
if (changed_flags & (CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_SLOW_KEYS_ENABLED))
|
||||
if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_SLOW_KEYS_ENABLED))
|
||||
clear_slow_keys (device);
|
||||
|
||||
if (changed_flags & (CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_BOUNCE_KEYS_ENABLED))
|
||||
if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_BOUNCE_KEYS_ENABLED))
|
||||
device->debounce_key = 0;
|
||||
|
||||
if (changed_flags & (CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_STICKY_KEYS_ENABLED))
|
||||
if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_STICKY_KEYS_ENABLED))
|
||||
{
|
||||
device->stickykeys_depressed_mask = 0;
|
||||
update_internal_xkb_state (device, 0, 0);
|
||||
}
|
||||
|
||||
if (changed_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
||||
if (changed_flags & META_A11Y_KEYBOARD_ENABLED)
|
||||
{
|
||||
device->toggle_slowkeys_timer = 0;
|
||||
device->shift_count = 0;
|
||||
device->last_shift_time = 0;
|
||||
}
|
||||
|
||||
if (changed_flags & (CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_MOUSE_KEYS_ENABLED))
|
||||
if (changed_flags & (META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED))
|
||||
{
|
||||
if (settings->controls &
|
||||
(CLUTTER_A11Y_KEYBOARD_ENABLED | CLUTTER_A11Y_MOUSE_KEYS_ENABLED))
|
||||
(META_A11Y_KEYBOARD_ENABLED | META_A11Y_MOUSE_KEYS_ENABLED))
|
||||
enable_mousekeys (device);
|
||||
else
|
||||
disable_mousekeys (device);
|
||||
@ -1224,48 +1231,10 @@ meta_input_device_native_apply_kbd_a11y_settings (MetaInputDeviceNative *device
|
||||
void
|
||||
meta_input_device_native_a11y_maybe_notify_toggle_keys (MetaInputDeviceNative *device)
|
||||
{
|
||||
if (device->a11y_flags & CLUTTER_A11Y_TOGGLE_KEYS_ENABLED)
|
||||
if (device->a11y_flags & META_A11Y_TOGGLE_KEYS_ENABLED)
|
||||
meta_input_device_native_bell_notify (device);
|
||||
}
|
||||
|
||||
static void
|
||||
release_device_touch_slot (gpointer value)
|
||||
{
|
||||
MetaTouchState *touch_state = value;
|
||||
|
||||
meta_seat_native_release_touch_state (touch_state->seat, touch_state);
|
||||
}
|
||||
|
||||
MetaTouchState *
|
||||
meta_input_device_native_acquire_touch_state (MetaInputDeviceNative *device,
|
||||
int device_slot)
|
||||
{
|
||||
MetaTouchState *touch_state;
|
||||
|
||||
touch_state = meta_seat_native_acquire_touch_state (device->seat,
|
||||
device_slot);
|
||||
g_hash_table_insert (device->touches,
|
||||
GINT_TO_POINTER (device_slot),
|
||||
touch_state);
|
||||
|
||||
return touch_state;
|
||||
}
|
||||
|
||||
MetaTouchState *
|
||||
meta_input_device_native_lookup_touch_state (MetaInputDeviceNative *device,
|
||||
int device_slot)
|
||||
{
|
||||
return g_hash_table_lookup (device->touches, GINT_TO_POINTER (device_slot));
|
||||
}
|
||||
|
||||
void
|
||||
meta_input_device_native_release_touch_state (MetaInputDeviceNative *device,
|
||||
MetaTouchState *touch_state)
|
||||
{
|
||||
g_hash_table_remove (device->touches,
|
||||
GINT_TO_POINTER (touch_state->device_slot));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_device_native_class_init (MetaInputDeviceNativeClass *klass)
|
||||
{
|
||||
@ -1305,9 +1274,6 @@ meta_input_device_native_init (MetaInputDeviceNative *self)
|
||||
cairo_matrix_init_identity (&self->device_matrix);
|
||||
self->device_aspect_ratio = 0;
|
||||
self->output_ratio = 0;
|
||||
|
||||
self->touches = g_hash_table_new_full (NULL, NULL,
|
||||
NULL, release_device_touch_slot);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1320,7 +1286,7 @@ meta_input_device_native_init (MetaInputDeviceNative *self)
|
||||
* it with the provided seat.
|
||||
*/
|
||||
ClutterInputDevice *
|
||||
meta_input_device_native_new (MetaSeatNative *seat,
|
||||
meta_input_device_native_new (MetaSeatImpl *seat_impl,
|
||||
struct libinput_device *libinput_device)
|
||||
{
|
||||
MetaInputDeviceNative *device;
|
||||
@ -1333,7 +1299,7 @@ meta_input_device_native_new (MetaSeatNative *seat,
|
||||
type = meta_input_device_native_determine_type (libinput_device);
|
||||
vendor = g_strdup_printf ("%.4x", libinput_device_get_id_vendor (libinput_device));
|
||||
product = g_strdup_printf ("%.4x", libinput_device_get_id_product (libinput_device));
|
||||
device_id = meta_seat_native_acquire_device_id (seat);
|
||||
device_id = meta_seat_impl_acquire_device_id (seat_impl);
|
||||
node_path = g_strdup_printf ("/dev/input/%s", libinput_device_get_sysname (libinput_device));
|
||||
|
||||
if (libinput_device_has_capability (libinput_device,
|
||||
@ -1349,17 +1315,16 @@ meta_input_device_native_new (MetaSeatNative *seat,
|
||||
"name", libinput_device_get_name (libinput_device),
|
||||
"device-type", type,
|
||||
"device-mode", CLUTTER_INPUT_MODE_SLAVE,
|
||||
"enabled", TRUE,
|
||||
"vendor-id", vendor,
|
||||
"product-id", product,
|
||||
"n-rings", n_rings,
|
||||
"n-strips", n_strips,
|
||||
"n-mode-groups", n_groups,
|
||||
"device-node", node_path,
|
||||
"seat", seat,
|
||||
"seat", seat_impl->seat,
|
||||
NULL);
|
||||
|
||||
device->seat = seat;
|
||||
device->seat_impl = seat_impl;
|
||||
device->libinput_device = libinput_device;
|
||||
|
||||
libinput_device_set_user_data (libinput_device, device);
|
||||
@ -1382,7 +1347,7 @@ meta_input_device_native_new (MetaSeatNative *seat,
|
||||
* Create a new virtual ClutterInputDevice of the given type.
|
||||
*/
|
||||
ClutterInputDevice *
|
||||
meta_input_device_native_new_virtual (MetaSeatNative *seat,
|
||||
meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl,
|
||||
ClutterInputDeviceType type,
|
||||
ClutterInputMode mode)
|
||||
{
|
||||
@ -1406,25 +1371,24 @@ meta_input_device_native_new_virtual (MetaSeatNative *seat,
|
||||
break;
|
||||
};
|
||||
|
||||
device_id = meta_seat_native_acquire_device_id (seat);
|
||||
device_id = meta_seat_impl_acquire_device_id (seat_impl);
|
||||
device = g_object_new (META_TYPE_INPUT_DEVICE_NATIVE,
|
||||
"id", device_id,
|
||||
"name", name,
|
||||
"device-type", type,
|
||||
"device-mode", mode,
|
||||
"enabled", TRUE,
|
||||
"seat", seat,
|
||||
"seat", seat_impl->seat,
|
||||
NULL);
|
||||
|
||||
device->seat = seat;
|
||||
device->seat_impl = seat_impl;
|
||||
|
||||
return CLUTTER_INPUT_DEVICE (device);
|
||||
}
|
||||
|
||||
MetaSeatNative *
|
||||
meta_input_device_native_get_seat (MetaInputDeviceNative *device)
|
||||
MetaSeatImpl *
|
||||
meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device)
|
||||
{
|
||||
return device->seat;
|
||||
return device->seat_impl;
|
||||
}
|
||||
|
||||
void
|
||||
@ -1484,17 +1448,16 @@ meta_input_device_native_get_libinput_device (ClutterInputDevice *device)
|
||||
|
||||
void
|
||||
meta_input_device_native_translate_coordinates (ClutterInputDevice *device,
|
||||
ClutterStage *stage,
|
||||
MetaViewportInfo *viewports,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
MetaInputDeviceNative *device_evdev = META_INPUT_DEVICE_NATIVE (device);
|
||||
double min_x = 0, min_y = 0, max_x = 1, max_y = 1;
|
||||
double stage_width, stage_height;
|
||||
float stage_width, stage_height;
|
||||
double x_d, y_d;
|
||||
|
||||
stage_width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
|
||||
stage_height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
|
||||
meta_viewport_info_get_extents (viewports, &stage_width, &stage_height);
|
||||
x_d = *x / stage_width;
|
||||
y_d = *y / stage_height;
|
||||
|
||||
@ -1518,23 +1481,50 @@ meta_input_device_native_translate_coordinates (ClutterInputDevice *device,
|
||||
*y = CLAMP (y_d, MIN (min_y, max_y), MAX (min_y, max_y)) * stage_height;
|
||||
}
|
||||
|
||||
void
|
||||
meta_input_device_native_release_touch_slots (MetaInputDeviceNative *device_evdev,
|
||||
uint64_t time_us)
|
||||
MetaInputDeviceMapping
|
||||
meta_input_device_native_get_mapping_mode (ClutterInputDevice *device)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
MetaTouchState *touch_state;
|
||||
MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device);
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
g_hash_table_iter_init (&iter, device_evdev->touches);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &touch_state))
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device),
|
||||
META_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
g_return_val_if_fail (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE,
|
||||
META_INPUT_DEVICE_MAPPING_ABSOLUTE);
|
||||
|
||||
return device_native->mapping_mode;
|
||||
}
|
||||
|
||||
void
|
||||
meta_input_device_native_set_mapping_mode (ClutterInputDevice *device,
|
||||
MetaInputDeviceMapping mapping)
|
||||
{
|
||||
meta_seat_native_notify_touch_event (touch_state->seat,
|
||||
CLUTTER_INPUT_DEVICE (device_evdev),
|
||||
CLUTTER_TOUCH_CANCEL,
|
||||
time_us,
|
||||
touch_state->seat_slot,
|
||||
touch_state->coords.x,
|
||||
touch_state->coords.y);
|
||||
g_hash_table_iter_remove (&iter);
|
||||
MetaInputDeviceNative *device_native = META_INPUT_DEVICE_NATIVE (device);
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
g_return_if_fail (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE);
|
||||
|
||||
if (device_native->mapping_mode == mapping)
|
||||
return;
|
||||
|
||||
device_native->mapping_mode = mapping;
|
||||
g_object_notify (G_OBJECT (device), "mapping-mode");
|
||||
}
|
||||
|
||||
void
|
||||
meta_input_device_native_update_coords (MetaInputDeviceNative *device_native,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
device_native->pointer_x = x;
|
||||
device_native->pointer_y = y;
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-input-device-private.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/native/meta-seat-native.h"
|
||||
#include "clutter/clutter-mutter.h"
|
||||
|
||||
@ -54,6 +55,12 @@
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
META_TYPE_INPUT_DEVICE_NATIVE, MetaInputDeviceNativeClass))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_INPUT_DEVICE_MAPPING_ABSOLUTE,
|
||||
META_INPUT_DEVICE_MAPPING_RELATIVE,
|
||||
} MetaInputDeviceMapping;
|
||||
|
||||
typedef struct _MetaInputDeviceNative MetaInputDeviceNative;
|
||||
typedef struct _MetaInputDeviceNativeClass MetaInputDeviceNativeClass;
|
||||
|
||||
@ -62,17 +69,20 @@ struct _MetaInputDeviceNative
|
||||
ClutterInputDevice parent;
|
||||
|
||||
struct libinput_device *libinput_device;
|
||||
MetaSeatNative *seat;
|
||||
MetaSeatImpl *seat_impl;
|
||||
ClutterInputDeviceTool *last_tool;
|
||||
|
||||
cairo_matrix_t device_matrix;
|
||||
double device_aspect_ratio; /* w:h */
|
||||
double output_ratio; /* w:h */
|
||||
MetaInputDeviceMapping mapping_mode;
|
||||
|
||||
GHashTable *touches;
|
||||
/* Pointer position */
|
||||
double pointer_x;
|
||||
double pointer_y;
|
||||
|
||||
/* Keyboard a11y */
|
||||
ClutterKeyboardA11yFlags a11y_flags;
|
||||
MetaKeyboardA11yFlags a11y_flags;
|
||||
GList *slow_keys_list;
|
||||
guint debounce_timer;
|
||||
uint16_t debounce_key;
|
||||
@ -99,17 +109,16 @@ struct _MetaInputDeviceNativeClass
|
||||
ClutterInputDeviceClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
GType meta_input_device_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterInputDevice * meta_input_device_native_new (MetaSeatNative *seat,
|
||||
ClutterInputDevice * meta_input_device_native_new (MetaSeatImpl *seat_impl,
|
||||
struct libinput_device *libinput_device);
|
||||
|
||||
ClutterInputDevice * meta_input_device_native_new_virtual (MetaSeatNative *seat,
|
||||
ClutterInputDevice * meta_input_device_native_new_virtual (MetaSeatImpl *seat_impl,
|
||||
ClutterInputDeviceType type,
|
||||
ClutterInputMode mode);
|
||||
|
||||
MetaSeatNative * meta_input_device_native_get_seat (MetaInputDeviceNative *device);
|
||||
MetaSeatImpl * meta_input_device_native_get_seat_impl (MetaInputDeviceNative *device);
|
||||
|
||||
void meta_input_device_native_update_leds (MetaInputDeviceNative *device,
|
||||
enum libinput_led leds);
|
||||
@ -118,27 +127,23 @@ ClutterInputDeviceType meta_input_device_native_determine_type (struct libin
|
||||
|
||||
|
||||
void meta_input_device_native_translate_coordinates (ClutterInputDevice *device,
|
||||
ClutterStage *stage,
|
||||
MetaViewportInfo *viewports,
|
||||
float *x,
|
||||
float *y);
|
||||
|
||||
MetaInputDeviceMapping meta_input_device_native_get_mapping_mode (ClutterInputDevice *device);
|
||||
void meta_input_device_native_set_mapping_mode (ClutterInputDevice *device,
|
||||
MetaInputDeviceMapping mapping);
|
||||
|
||||
void meta_input_device_native_apply_kbd_a11y_settings (MetaInputDeviceNative *device,
|
||||
ClutterKbdA11ySettings *settings);
|
||||
|
||||
MetaTouchState * meta_input_device_native_acquire_touch_state (MetaInputDeviceNative *device,
|
||||
int device_slot);
|
||||
|
||||
MetaTouchState * meta_input_device_native_lookup_touch_state (MetaInputDeviceNative *device,
|
||||
int device_slot);
|
||||
|
||||
void meta_input_device_native_release_touch_state (MetaInputDeviceNative *device,
|
||||
MetaTouchState *touch_state);
|
||||
|
||||
void meta_input_device_native_release_touch_slots (MetaInputDeviceNative *device_evdev,
|
||||
uint64_t time_us);
|
||||
MetaKbdA11ySettings *settings);
|
||||
|
||||
void meta_input_device_native_a11y_maybe_notify_toggle_keys (MetaInputDeviceNative *device_evdev);
|
||||
|
||||
struct libinput_device * meta_input_device_native_get_libinput_device (ClutterInputDevice *device);
|
||||
|
||||
void meta_input_device_native_update_coords (MetaInputDeviceNative *device_native,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
#endif /* META_INPUT_DEVICE_NATIVE_H */
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <libinput.h>
|
||||
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/native/meta-input-device-native.h"
|
||||
#include "backends/native/meta-input-device-tool-native.h"
|
||||
@ -34,6 +33,55 @@
|
||||
|
||||
G_DEFINE_TYPE (MetaInputSettingsNative, meta_input_settings_native, META_TYPE_INPUT_SETTINGS)
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SEAT_IMPL,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
GParamSpec *props[N_PROPS] = { 0 };
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaInputSettingsNative *input_settings_native =
|
||||
META_INPUT_SETTINGS_NATIVE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEAT_IMPL:
|
||||
input_settings_native->seat_impl = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaInputSettingsNative *input_settings_native =
|
||||
META_INPUT_SETTINGS_NATIVE (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_SEAT_IMPL:
|
||||
g_value_set_object (value, input_settings_native->seat_impl);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_send_events (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
@ -70,8 +118,19 @@ meta_input_settings_native_set_matrix (MetaInputSettings *settings,
|
||||
{
|
||||
cairo_matrix_t dev_matrix;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_TOUCHSCREEN_DEVICE ||
|
||||
meta_input_device_native_get_mapping_mode (device) ==
|
||||
META_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
||||
{
|
||||
cairo_matrix_init (&dev_matrix, matrix[0], matrix[3], matrix[1],
|
||||
matrix[4], matrix[2], matrix[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_matrix_init_identity (&dev_matrix);
|
||||
}
|
||||
|
||||
g_object_set (device, "device-matrix", &dev_matrix, NULL);
|
||||
}
|
||||
|
||||
@ -376,10 +435,10 @@ meta_input_settings_native_set_keyboard_repeat (MetaInputSettings *settings,
|
||||
guint delay,
|
||||
guint interval)
|
||||
{
|
||||
ClutterSeat *seat;
|
||||
MetaInputSettingsNative *input_settings_native;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
meta_seat_native_set_keyboard_repeat (META_SEAT_NATIVE (seat),
|
||||
input_settings_native = META_INPUT_SETTINGS_NATIVE (settings);
|
||||
meta_seat_impl_set_keyboard_repeat (input_settings_native->seat_impl,
|
||||
enabled, delay, interval);
|
||||
}
|
||||
|
||||
@ -502,49 +561,26 @@ meta_input_settings_native_set_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping)
|
||||
{
|
||||
ClutterInputDeviceMapping dev_mapping;
|
||||
MetaInputDeviceMapping dev_mapping;
|
||||
|
||||
if (mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE)
|
||||
dev_mapping = CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE;
|
||||
dev_mapping = META_INPUT_DEVICE_MAPPING_ABSOLUTE;
|
||||
else if (mapping == G_DESKTOP_TABLET_MAPPING_RELATIVE)
|
||||
dev_mapping = CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE;
|
||||
dev_mapping = META_INPUT_DEVICE_MAPPING_RELATIVE;
|
||||
else
|
||||
return;
|
||||
|
||||
clutter_input_device_set_mapping_mode (device, dev_mapping);
|
||||
meta_input_device_native_set_mapping_mode (device, dev_mapping);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
meta_input_settings_native_set_tablet_aspect_ratio (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaLogicalMonitor *logical_monitor,
|
||||
gboolean keep_aspect)
|
||||
gdouble aspect_ratio)
|
||||
{
|
||||
double aspect_ratio = 0;
|
||||
|
||||
if (keep_aspect)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
if (logical_monitor)
|
||||
{
|
||||
width = logical_monitor->rect.width;
|
||||
height = logical_monitor->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaBackend *backend;
|
||||
|
||||
backend = meta_get_backend ();
|
||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
meta_monitor_manager_get_screen_size (monitor_manager,
|
||||
&width,
|
||||
&height);
|
||||
}
|
||||
|
||||
aspect_ratio = (double) width / height;
|
||||
}
|
||||
if (meta_input_device_native_get_mapping_mode (device) ==
|
||||
META_INPUT_DEVICE_MAPPING_RELATIVE)
|
||||
aspect_ratio = 0;
|
||||
|
||||
g_object_set (device, "output-aspect-ratio", aspect_ratio, NULL);
|
||||
}
|
||||
@ -688,6 +724,10 @@ static void
|
||||
meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class = META_INPUT_SETTINGS_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->set_property = meta_input_settings_native_set_property;
|
||||
object_class->get_property = meta_input_settings_native_get_property;
|
||||
|
||||
input_settings_class->set_send_events = meta_input_settings_native_set_send_events;
|
||||
input_settings_class->set_matrix = meta_input_settings_native_set_matrix;
|
||||
@ -707,7 +747,7 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
input_settings_class->set_disable_while_typing = meta_input_settings_native_set_disable_while_typing;
|
||||
|
||||
input_settings_class->set_tablet_mapping = meta_input_settings_native_set_tablet_mapping;
|
||||
input_settings_class->set_tablet_keep_aspect = meta_input_settings_native_set_tablet_keep_aspect;
|
||||
input_settings_class->set_tablet_aspect_ratio = meta_input_settings_native_set_tablet_aspect_ratio;
|
||||
input_settings_class->set_tablet_area = meta_input_settings_native_set_tablet_area;
|
||||
|
||||
input_settings_class->set_mouse_accel_profile = meta_input_settings_native_set_mouse_accel_profile;
|
||||
@ -722,9 +762,27 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
|
||||
input_settings_class->has_two_finger_scroll = meta_input_settings_native_has_two_finger_scroll;
|
||||
input_settings_class->is_trackball_device = meta_input_settings_native_is_trackball_device;
|
||||
|
||||
props[PROP_SEAT_IMPL] =
|
||||
g_param_spec_object ("seat-impl",
|
||||
"Seat Impl",
|
||||
"Seat Impl",
|
||||
PROP_SEAT_IMPL,
|
||||
CLUTTER_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_init (MetaInputSettingsNative *settings)
|
||||
{
|
||||
}
|
||||
|
||||
MetaInputSettings *
|
||||
meta_input_settings_native_new (MetaSeatImpl *seat)
|
||||
{
|
||||
return g_object_new (META_TYPE_INPUT_SETTINGS_NATIVE,
|
||||
"seat-impl", seat,
|
||||
NULL);
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ typedef struct _MetaInputSettingsNativeClass MetaInputSettingsNativeClass;
|
||||
struct _MetaInputSettingsNative
|
||||
{
|
||||
MetaInputSettings parent_instance;
|
||||
MetaSeatImpl *seat_impl;
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsNativeClass
|
||||
@ -46,4 +47,6 @@ struct _MetaInputSettingsNativeClass
|
||||
|
||||
GType meta_input_settings_native_get_type (void) G_GNUC_CONST;
|
||||
|
||||
MetaInputSettings * meta_input_settings_native_new (MetaSeatImpl *seat);
|
||||
|
||||
#endif /* META_INPUT_SETTINGS_NATIVE_H */
|
||||
|
@ -25,10 +25,6 @@
|
||||
#include "backends/native/meta-keymap-native.h"
|
||||
#include "backends/native/meta-seat-native.h"
|
||||
|
||||
static const char *option_xkb_layout = "us";
|
||||
static const char *option_xkb_variant = "";
|
||||
static const char *option_xkb_options = "";
|
||||
|
||||
typedef struct _MetaKeymapNative MetaKeymapNative;
|
||||
|
||||
struct _MetaKeymapNative
|
||||
@ -36,6 +32,8 @@ struct _MetaKeymapNative
|
||||
ClutterKeymap parent_instance;
|
||||
|
||||
struct xkb_keymap *keymap;
|
||||
gboolean num_lock;
|
||||
gboolean caps_lock;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaKeymapNative, meta_keymap_native,
|
||||
@ -54,31 +52,17 @@ meta_keymap_native_finalize (GObject *object)
|
||||
static gboolean
|
||||
meta_keymap_native_get_num_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
struct xkb_state *xkb_state;
|
||||
ClutterSeat *seat;
|
||||
MetaKeymapNative *keymap_native = META_KEYMAP_NATIVE (keymap);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
xkb_state = meta_seat_native_get_xkb_state (META_SEAT_NATIVE (seat));
|
||||
|
||||
return xkb_state_mod_name_is_active (xkb_state,
|
||||
XKB_MOD_NAME_NUM,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
return keymap_native->num_lock;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_keymap_native_get_caps_lock_state (ClutterKeymap *keymap)
|
||||
{
|
||||
struct xkb_state *xkb_state;
|
||||
ClutterSeat *seat;
|
||||
MetaKeymapNative *keymap_native = META_KEYMAP_NATIVE (keymap);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
xkb_state = meta_seat_native_get_xkb_state (META_SEAT_NATIVE (seat));
|
||||
|
||||
return xkb_state_mod_name_is_active (xkb_state,
|
||||
XKB_MOD_NAME_CAPS,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
return keymap_native->caps_lock;
|
||||
}
|
||||
|
||||
static PangoDirection
|
||||
@ -103,19 +87,6 @@ meta_keymap_native_class_init (MetaKeymapNativeClass *klass)
|
||||
static void
|
||||
meta_keymap_native_init (MetaKeymapNative *keymap)
|
||||
{
|
||||
struct xkb_context *ctx;
|
||||
struct xkb_rule_names names;
|
||||
|
||||
names.rules = "evdev";
|
||||
names.model = "pc105";
|
||||
names.layout = option_xkb_layout;
|
||||
names.variant = option_xkb_variant;
|
||||
names.options = option_xkb_options;
|
||||
|
||||
ctx = meta_create_xkb_context ();
|
||||
g_assert (ctx);
|
||||
keymap->keymap = xkb_keymap_new_from_names (ctx, &names, 0);
|
||||
xkb_context_unref (ctx);
|
||||
}
|
||||
|
||||
void
|
||||
@ -132,3 +103,24 @@ meta_keymap_native_get_keyboard_map (MetaKeymapNative *keymap)
|
||||
{
|
||||
return keymap->keymap;
|
||||
}
|
||||
|
||||
void
|
||||
meta_keymap_native_update (MetaKeymapNative *keymap)
|
||||
{
|
||||
struct xkb_state *xkb_state;
|
||||
ClutterSeat *seat;
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
xkb_state = meta_seat_impl_get_xkb_state (META_SEAT_NATIVE (seat)->impl);
|
||||
|
||||
keymap->num_lock =
|
||||
xkb_state_mod_name_is_active (xkb_state,
|
||||
XKB_MOD_NAME_NUM,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
keymap->caps_lock =
|
||||
xkb_state_mod_name_is_active (xkb_state,
|
||||
XKB_MOD_NAME_CAPS,
|
||||
XKB_STATE_MODS_LATCHED |
|
||||
XKB_STATE_MODS_LOCKED);
|
||||
}
|
||||
|
@ -32,5 +32,6 @@ G_DECLARE_FINAL_TYPE (MetaKeymapNative, meta_keymap_native,
|
||||
void meta_keymap_native_set_keyboard_map (MetaKeymapNative *keymap,
|
||||
struct xkb_keymap *xkb_keymap);
|
||||
struct xkb_keymap * meta_keymap_native_get_keyboard_map (MetaKeymapNative *keymap);
|
||||
void meta_keymap_native_update (MetaKeymapNative *keymap);
|
||||
|
||||
#endif /* META_KEYMAP_NATIVE_H */
|
||||
|
1700
src/backends/native/meta-kms-cursor-renderer.c
Normal file
1700
src/backends/native/meta-kms-cursor-renderer.c
Normal file
File diff suppressed because it is too large
Load Diff
43
src/backends/native/meta-kms-cursor-renderer.h
Normal file
43
src/backends/native/meta-kms-cursor-renderer.h
Normal file
@ -0,0 +1,43 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef META_KMS_CURSOR_RENDERER_H
|
||||
#define META_KMS_CURSOR_RENDERER_H
|
||||
|
||||
#include "backends/meta-cursor-renderer.h"
|
||||
#include "meta/meta-backend.h"
|
||||
|
||||
#define META_TYPE_KMS_CURSOR_RENDERER (meta_kms_cursor_renderer_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaKmsCursorRenderer, meta_kms_cursor_renderer,
|
||||
META, KMS_CURSOR_RENDERER,
|
||||
GObject)
|
||||
|
||||
MetaKmsCursorRenderer * meta_kms_cursor_renderer_new (MetaBackend *backend);
|
||||
void meta_kms_cursor_renderer_invalidate_state (MetaKmsCursorRenderer *kms_renderer);
|
||||
gboolean meta_kms_cursor_renderer_update_cursor (MetaKmsCursorRenderer *kms_cursor_renderer,
|
||||
MetaCursorSprite *sprite);
|
||||
void meta_kms_cursor_renderer_set_cursor_renderer (MetaKmsCursorRenderer *kms_renderer,
|
||||
MetaCursorRenderer *renderer);
|
||||
|
||||
#endif /* META_KMS_CURSOR_RENDERER_H */
|
@ -528,7 +528,7 @@ meta_launcher_new (GError **error)
|
||||
|
||||
meta_clutter_backend_native_set_seat_id (self->seat_id);
|
||||
|
||||
meta_seat_native_set_device_callbacks (on_evdev_device_open,
|
||||
meta_seat_impl_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
self);
|
||||
|
||||
|
676
src/backends/native/meta-pointer-constraint-native.c
Normal file
676
src/backends/native/meta-pointer-constraint-native.c
Normal file
@ -0,0 +1,676 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "core/meta-border.h"
|
||||
#include "meta-pointer-constraint-native.h"
|
||||
|
||||
struct _MetaPointerConstraintImplNative
|
||||
{
|
||||
MetaPointerConstraintImpl parent;
|
||||
MetaPointerConstraint *constraint;
|
||||
cairo_region_t *region;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaPointerConstraintImplNative,
|
||||
meta_pointer_constraint_impl_native,
|
||||
META_TYPE_POINTER_CONSTRAINT_IMPL);
|
||||
|
||||
typedef struct _MetaBox
|
||||
{
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
} MetaBox;
|
||||
|
||||
static MetaBorder *
|
||||
add_border (GArray *borders,
|
||||
float x1,
|
||||
float y1,
|
||||
float x2,
|
||||
float y2,
|
||||
MetaBorderMotionDirection blocking_directions)
|
||||
{
|
||||
MetaBorder border;
|
||||
|
||||
border = (MetaBorder) {
|
||||
.line = (MetaLine2) {
|
||||
.a = (MetaVector2) {
|
||||
.x = x1,
|
||||
.y = y1,
|
||||
},
|
||||
.b = (MetaVector2) {
|
||||
.x = x2,
|
||||
.y = y2,
|
||||
},
|
||||
},
|
||||
.blocking_directions = blocking_directions,
|
||||
};
|
||||
|
||||
g_array_append_val (borders, border);
|
||||
|
||||
return &g_array_index (borders, MetaBorder, borders->len - 1);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_lines_x (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
const MetaBorder *border_a = a;
|
||||
const MetaBorder *border_b = b;
|
||||
|
||||
if (border_a->line.a.x == border_b->line.a.x)
|
||||
return border_a->line.b.x < border_b->line.b.x;
|
||||
else
|
||||
return border_a->line.a.x > border_b->line.a.x;
|
||||
}
|
||||
|
||||
static void
|
||||
add_non_overlapping_edges (MetaBox *boxes,
|
||||
unsigned int band_above_start,
|
||||
unsigned int band_below_start,
|
||||
unsigned int band_below_end,
|
||||
GArray *borders)
|
||||
{
|
||||
unsigned int i;
|
||||
GArray *band_merge;
|
||||
MetaBorder *border;
|
||||
MetaBorder *prev_border;
|
||||
MetaBorder *new_border;
|
||||
|
||||
band_merge = g_array_new (FALSE, FALSE, sizeof *border);
|
||||
|
||||
/* Add bottom band of previous row, and top band of current row, and
|
||||
* sort them so lower left x coordinate comes first. If there are two
|
||||
* borders with the same left x coordinate, the wider one comes first.
|
||||
*/
|
||||
for (i = band_above_start; i < band_below_start; i++)
|
||||
{
|
||||
MetaBox *box = &boxes[i];
|
||||
add_border (band_merge, box->x1, box->y2, box->x2, box->y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
for (i = band_below_start; i < band_below_end; i++)
|
||||
{
|
||||
MetaBox *box= &boxes[i];
|
||||
add_border (band_merge, box->x1, box->y1, box->x2, box->y1,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
g_array_sort (band_merge, compare_lines_x);
|
||||
|
||||
/* Combine the two combined bands so that any overlapping border is
|
||||
* eliminated. */
|
||||
prev_border = NULL;
|
||||
for (i = 0; i < band_merge->len; i++)
|
||||
{
|
||||
border = &g_array_index (band_merge, MetaBorder, i);
|
||||
|
||||
g_assert (border->line.a.y == border->line.b.y);
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.a.y == border->line.a.y);
|
||||
g_assert (!prev_border ||
|
||||
(prev_border->line.a.x != border->line.a.x ||
|
||||
prev_border->line.b.x != border->line.b.x));
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.a.x <= border->line.a.x);
|
||||
|
||||
if (prev_border &&
|
||||
prev_border->line.a.x == border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* ------------ +
|
||||
* ------- =
|
||||
* [ ]-----
|
||||
*/
|
||||
prev_border->line.a.x = border->line.b.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x == border->line.b.x)
|
||||
{
|
||||
/*
|
||||
* ------------ +
|
||||
* ------ =
|
||||
* ------[ ]
|
||||
*/
|
||||
prev_border->line.b.x = border->line.a.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x == border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* -------- +
|
||||
* ------ =
|
||||
* --------------
|
||||
*/
|
||||
prev_border->line.b.x = border->line.b.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x >= border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* --------------- +
|
||||
* ------ =
|
||||
* -----[ ]----
|
||||
*/
|
||||
new_border = add_border (borders,
|
||||
border->line.b.x,
|
||||
border->line.b.y,
|
||||
prev_border->line.b.x,
|
||||
prev_border->line.b.y,
|
||||
prev_border->blocking_directions);
|
||||
prev_border->line.b.x = border->line.a.x;
|
||||
prev_border = new_border;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.b.x < border->line.a.x);
|
||||
/*
|
||||
* First border or non-overlapping.
|
||||
*
|
||||
* ----- +
|
||||
* ----- =
|
||||
* ----- -----
|
||||
*/
|
||||
g_array_append_val (borders, *border);
|
||||
prev_border = &g_array_index (borders, MetaBorder, borders->len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
g_array_free (band_merge, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_band_bottom_edges (MetaBox *boxes,
|
||||
int band_start,
|
||||
int band_end,
|
||||
GArray *borders)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = band_start; i < band_end; i++)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
region_to_outline (cairo_region_t *region,
|
||||
GArray *borders)
|
||||
{
|
||||
MetaBox *boxes;
|
||||
int num_boxes;
|
||||
int i;
|
||||
int top_most, bottom_most;
|
||||
int current_roof;
|
||||
int prev_top;
|
||||
int band_start, prev_band_start;
|
||||
|
||||
/*
|
||||
* Remove any overlapping lines from the set of rectangles. Note that
|
||||
* pixman regions are grouped as rows of rectangles, where rectangles
|
||||
* in one row never touch or overlap and are all of the same height.
|
||||
*
|
||||
* -------- --- -------- ---
|
||||
* | | | | | | | |
|
||||
* ----------====---- --- ----------- ----- ---
|
||||
* | | => | |
|
||||
* ----==========--------- ----- ----------
|
||||
* | | | |
|
||||
* ------------------- -------------------
|
||||
*
|
||||
*/
|
||||
|
||||
num_boxes = cairo_region_num_rectangles (region);
|
||||
boxes = g_new (MetaBox, num_boxes);
|
||||
for (i = 0; i < num_boxes; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
boxes[i] = (MetaBox) {
|
||||
.x1 = rect.x,
|
||||
.y1 = rect.y,
|
||||
.x2 = rect.x + rect.width,
|
||||
.y2 = rect.y + rect.height,
|
||||
};
|
||||
}
|
||||
prev_top = 0;
|
||||
top_most = boxes[0].y1;
|
||||
current_roof = top_most;
|
||||
bottom_most = boxes[num_boxes - 1].y2;
|
||||
band_start = 0;
|
||||
prev_band_start = 0;
|
||||
for (i = 0; i < num_boxes; i++)
|
||||
{
|
||||
/* Detect if there is a vertical empty space, and add the lower
|
||||
* level of the previous band if so was the case. */
|
||||
if (i > 0 &&
|
||||
boxes[i].y1 != prev_top &&
|
||||
boxes[i].y1 != boxes[i - 1].y2)
|
||||
{
|
||||
current_roof = boxes[i].y1;
|
||||
add_band_bottom_edges (boxes,
|
||||
band_start,
|
||||
i,
|
||||
borders);
|
||||
}
|
||||
|
||||
/* Special case adding the last band, since it won't be handled
|
||||
* by the band change detection below. */
|
||||
if (boxes[i].y1 != current_roof && i == num_boxes - 1)
|
||||
{
|
||||
if (boxes[i].y1 != prev_top)
|
||||
{
|
||||
/* The last band is a single box, so we don't
|
||||
* have a prev_band_start to tell us when the
|
||||
* previous band started. */
|
||||
add_non_overlapping_edges (boxes,
|
||||
band_start,
|
||||
i,
|
||||
i + 1,
|
||||
borders);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_non_overlapping_edges (boxes,
|
||||
prev_band_start,
|
||||
band_start,
|
||||
i + 1,
|
||||
borders);
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect when passing a band and combine the top border of the
|
||||
* just passed band with the bottom band of the previous band.
|
||||
*/
|
||||
if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top)
|
||||
{
|
||||
/* Combine the two passed bands. */
|
||||
if (prev_top != current_roof)
|
||||
{
|
||||
add_non_overlapping_edges (boxes,
|
||||
prev_band_start,
|
||||
band_start,
|
||||
i,
|
||||
borders);
|
||||
}
|
||||
|
||||
prev_band_start = band_start;
|
||||
band_start = i;
|
||||
}
|
||||
|
||||
/* Add the top border if the box is part of the current roof. */
|
||||
if (boxes[i].y1 == current_roof)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y1,
|
||||
boxes[i].x2, boxes[i].y1,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
|
||||
/* Add the bottom border of the last band. */
|
||||
if (boxes[i].y2 == bottom_most)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
|
||||
/* Always add the left border. */
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y1,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X);
|
||||
|
||||
/* Always add the right border. */
|
||||
add_border (borders,
|
||||
boxes[i].x2, boxes[i].y1,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_X);
|
||||
|
||||
prev_top = boxes[i].y1;
|
||||
}
|
||||
|
||||
g_free (boxes);
|
||||
}
|
||||
|
||||
static MetaBorder *
|
||||
get_closest_border (GArray *borders,
|
||||
MetaLine2 *motion,
|
||||
uint32_t directions)
|
||||
{
|
||||
MetaBorder *border;
|
||||
MetaVector2 intersection;
|
||||
MetaVector2 delta;
|
||||
float distance_2;
|
||||
MetaBorder *closest_border = NULL;
|
||||
float closest_distance_2 = DBL_MAX;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < borders->len; i++)
|
||||
{
|
||||
border = &g_array_index (borders, MetaBorder, i);
|
||||
|
||||
if (!meta_border_is_blocking_directions (border, directions))
|
||||
continue;
|
||||
|
||||
if (!meta_line2_intersects_with (&border->line, motion, &intersection))
|
||||
continue;
|
||||
|
||||
delta = meta_vector2_subtract (intersection, motion->a);
|
||||
distance_2 = delta.x*delta.x + delta.y*delta.y;
|
||||
if (distance_2 < closest_distance_2)
|
||||
{
|
||||
closest_border = border;
|
||||
closest_distance_2 = distance_2;
|
||||
}
|
||||
}
|
||||
|
||||
return closest_border;
|
||||
}
|
||||
|
||||
static void
|
||||
clamp_to_border (MetaBorder *border,
|
||||
MetaLine2 *motion,
|
||||
uint32_t *motion_dir)
|
||||
{
|
||||
/*
|
||||
* When clamping either rightward or downward motions, the motion needs to be
|
||||
* clamped so that the destination coordinate does not end up on the border
|
||||
* (see weston_pointer_clamp_event_to_region). Do this by clamping such
|
||||
* motions to the border minus the smallest possible wl_fixed_t value.
|
||||
*
|
||||
* When clamping in either leftward or upward motion, the resulting coordinate
|
||||
* needs to be clamped so that it is enough on the inside to avoid the
|
||||
* inaccuracies of clutter's stage to actor transformation algorithm (the one
|
||||
* used in clutter_actor_transform_stage_point) to make it end up outside the
|
||||
* next motion. It also needs to be clamped so that to the wl_fixed_t
|
||||
* coordinate may still be right on the border (i.e. at .0). Testing shows
|
||||
* that the smallest wl_fixed_t value divided by 10 is small enough to make
|
||||
* the wl_fixed_t coordinate .0 and large enough to avoid the inaccuracies of
|
||||
* clutters transform algorithm.
|
||||
*/
|
||||
if (meta_border_is_horizontal (border))
|
||||
{
|
||||
if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_Y)
|
||||
motion->b.y = border->line.a.y - wl_fixed_to_double (1);
|
||||
else
|
||||
motion->b.y = border->line.a.y + wl_fixed_to_double (1) / 10;
|
||||
*motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_X)
|
||||
motion->b.x = border->line.a.x - wl_fixed_to_double (1);
|
||||
else
|
||||
motion->b.x = border->line.a.x + wl_fixed_to_double (1) / 10;
|
||||
*motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_motion_directions (MetaLine2 *motion)
|
||||
{
|
||||
uint32_t directions = 0;
|
||||
|
||||
if (motion->a.x < motion->b.x)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_X;
|
||||
else if (motion->a.x > motion->b.x)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_X;
|
||||
if (motion->a.y < motion->b.y)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_Y;
|
||||
else if (motion->a.y > motion->b.y)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_Y;
|
||||
|
||||
return directions;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_native_constraint (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device,
|
||||
uint32_t time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x_inout,
|
||||
float *y_inout)
|
||||
{
|
||||
MetaPointerConstraintImplNative *native = META_POINTER_CONSTRAINT_IMPL_NATIVE (impl);
|
||||
cairo_region_t *region;
|
||||
float x, y;
|
||||
GArray *borders;
|
||||
MetaLine2 motion;
|
||||
MetaBorder *closest_border;
|
||||
uint32_t directions;
|
||||
|
||||
region = cairo_region_reference (native->region);
|
||||
x = *x_inout;
|
||||
y = *y_inout;
|
||||
|
||||
/* For motions in a positive direction on any axis, append the smallest
|
||||
* possible value representable in a Wayland absolute coordinate. This is
|
||||
* in order to avoid not clamping motion that as a floating point number
|
||||
* won't be clamped, but will be rounded up to be outside of the range
|
||||
* of wl_fixed_t. */
|
||||
if (x > prev_x)
|
||||
x += (float) wl_fixed_to_double(1);
|
||||
if (y > prev_y)
|
||||
y += (float) wl_fixed_to_double(1);
|
||||
|
||||
borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder));
|
||||
|
||||
/*
|
||||
* Generate borders given the confine region we are to use. The borders
|
||||
* are defined to be the outer region of the allowed area. This means
|
||||
* top/left borders are "within" the allowed area, while bottom/right
|
||||
* borders are outside. This needs to be considered when clamping
|
||||
* confined motion vectors.
|
||||
*/
|
||||
region_to_outline (region, borders);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
motion = (MetaLine2) {
|
||||
.a = (MetaVector2) {
|
||||
.x = prev_x,
|
||||
.y = prev_y,
|
||||
},
|
||||
.b = (MetaVector2) {
|
||||
.x = x,
|
||||
.y = y,
|
||||
},
|
||||
};
|
||||
directions = get_motion_directions (&motion);
|
||||
|
||||
while (directions)
|
||||
{
|
||||
closest_border = get_closest_border (borders,
|
||||
&motion,
|
||||
directions);
|
||||
if (closest_border)
|
||||
clamp_to_border (closest_border, &motion, &directions);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
*x_inout = motion.b.x;
|
||||
*y_inout = motion.b.y;
|
||||
g_array_free (borders, FALSE);
|
||||
}
|
||||
|
||||
static float
|
||||
point_to_border_distance_2 (MetaBorder *border,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
float orig_x, orig_y;
|
||||
float dx, dy;
|
||||
|
||||
if (meta_border_is_horizontal (border))
|
||||
{
|
||||
if (x < border->line.a.x)
|
||||
orig_x = border->line.a.x;
|
||||
else if (x > border->line.b.x)
|
||||
orig_x = border->line.b.x;
|
||||
else
|
||||
orig_x = x;
|
||||
orig_y = border->line.a.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y < border->line.a.y)
|
||||
orig_y = border->line.a.y;
|
||||
else if (y > border->line.b.y)
|
||||
orig_y = border->line.b.y;
|
||||
else
|
||||
orig_y = y;
|
||||
orig_x = border->line.a.x;
|
||||
}
|
||||
|
||||
dx = fabsf (orig_x - x);
|
||||
dy = fabsf (orig_y - y);
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
static void
|
||||
closest_point_behind_border (MetaBorder *border,
|
||||
float *sx,
|
||||
float *sy)
|
||||
{
|
||||
switch (border->blocking_directions)
|
||||
{
|
||||
case META_BORDER_MOTION_DIRECTION_POSITIVE_X:
|
||||
case META_BORDER_MOTION_DIRECTION_NEGATIVE_X:
|
||||
if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_X)
|
||||
*sx = border->line.a.x - wl_fixed_to_double (1);
|
||||
else
|
||||
*sx = border->line.a.x + wl_fixed_to_double (1);
|
||||
if (*sy < border->line.a.y)
|
||||
*sy = border->line.a.y + wl_fixed_to_double (1);
|
||||
else if (*sy > border->line.b.y)
|
||||
*sy = border->line.b.y - wl_fixed_to_double (1);
|
||||
break;
|
||||
case META_BORDER_MOTION_DIRECTION_POSITIVE_Y:
|
||||
case META_BORDER_MOTION_DIRECTION_NEGATIVE_Y:
|
||||
if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_Y)
|
||||
*sy = border->line.a.y - wl_fixed_to_double (1);
|
||||
else
|
||||
*sy = border->line.a.y + wl_fixed_to_double (1);
|
||||
if (*sx < border->line.a.x)
|
||||
*sx = border->line.a.x + wl_fixed_to_double (1);
|
||||
else if (*sx > (border->line.b.x))
|
||||
*sx = border->line.b.x - wl_fixed_to_double (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImpl *impl,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaPointerConstraintImplNative *impl_native;
|
||||
graphene_point_t point;
|
||||
cairo_region_t *region;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (impl);
|
||||
region = cairo_region_reference (impl_native->region);
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, &point);
|
||||
x = point.x;
|
||||
y = point.y;
|
||||
|
||||
if (!cairo_region_contains_point (region, (int) x, (int) y))
|
||||
{
|
||||
GArray *borders;
|
||||
float closest_distance_2 = FLT_MAX;
|
||||
MetaBorder *closest_border = NULL;
|
||||
ClutterSeat *seat;
|
||||
unsigned int i;
|
||||
|
||||
borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder));
|
||||
|
||||
region_to_outline (region, borders);
|
||||
|
||||
for (i = 0; i < borders->len; i++)
|
||||
{
|
||||
MetaBorder *border = &g_array_index (borders, MetaBorder, i);
|
||||
float distance_2;
|
||||
|
||||
distance_2 = point_to_border_distance_2 (border, x, y);
|
||||
if (distance_2 < closest_distance_2)
|
||||
{
|
||||
closest_border = border;
|
||||
closest_distance_2 = distance_2;
|
||||
}
|
||||
}
|
||||
|
||||
closest_point_behind_border (closest_border, &x, &y);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
clutter_seat_warp_pointer (seat, x, y);
|
||||
}
|
||||
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_native_init (MetaPointerConstraintImplNative *constraint)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_constraint_impl_native_class_init (MetaPointerConstraintImplNativeClass *klass)
|
||||
{
|
||||
MetaPointerConstraintImplClass *constraint_impl;
|
||||
|
||||
constraint_impl = META_POINTER_CONSTRAINT_IMPL_CLASS (klass);
|
||||
constraint_impl->constrain = meta_pointer_constraint_impl_native_constraint;
|
||||
constraint_impl->ensure_constrained =
|
||||
meta_pointer_constraint_impl_native_ensure_constrained;
|
||||
}
|
||||
|
||||
|
||||
MetaPointerConstraintImpl *
|
||||
meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint,
|
||||
const cairo_region_t *region)
|
||||
{
|
||||
MetaPointerConstraintImplNative *impl;
|
||||
|
||||
impl = g_object_new (META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE, NULL);
|
||||
impl->constraint = constraint;
|
||||
impl->region = cairo_region_copy (region);
|
||||
|
||||
return META_POINTER_CONSTRAINT_IMPL (impl);
|
||||
}
|
46
src/backends/native/meta-pointer-constraint-native.h
Normal file
46
src/backends/native/meta-pointer-constraint-native.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_POINTER_CONSTRAINT_NATIVE_H
|
||||
#define META_POINTER_CONSTRAINT_NATIVE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_POINTER_CONSTRAINT_IMPL_NATIVE (meta_pointer_constraint_impl_native_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaPointerConstraintImplNative,
|
||||
meta_pointer_constraint_impl_native,
|
||||
META, POINTER_CONSTRAINT_IMPL_NATIVE,
|
||||
MetaPointerConstraintImpl)
|
||||
|
||||
MetaPointerConstraintImpl * meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint,
|
||||
const cairo_region_t *region);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* META_POINTER_CONSTRAINT_NATIVE_H */
|
3428
src/backends/native/meta-seat-impl.c
Normal file
3428
src/backends/native/meta-seat-impl.c
Normal file
File diff suppressed because it is too large
Load Diff
276
src/backends/native/meta-seat-impl.h
Normal file
276
src/backends/native/meta-seat-impl.h
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* 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 META_SEAT_IMPL_H
|
||||
#define META_SEAT_IMPL_H
|
||||
|
||||
#include <gudev/gudev.h>
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/meta-viewport-info.h"
|
||||
#include "backends/native/meta-backend-native-types.h"
|
||||
#include "backends/native/meta-barrier-native.h"
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#include "backends/native/meta-keymap-native.h"
|
||||
#include "backends/native/meta-pointer-constraint-native.h"
|
||||
#include "backends/native/meta-xkb-utils.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
typedef struct _MetaTouchState MetaTouchState;
|
||||
typedef struct _MetaSeatImpl MetaSeatImpl;
|
||||
typedef struct _MetaEventSource MetaEventSource;
|
||||
|
||||
struct _MetaTouchState
|
||||
{
|
||||
MetaSeatImpl *seat;
|
||||
|
||||
int device_slot;
|
||||
int seat_slot;
|
||||
graphene_point_t coords;
|
||||
};
|
||||
|
||||
struct _MetaSeatImpl
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GMainContext *caller_context;
|
||||
GMainContext *input_context;
|
||||
GMainLoop *input_loop;
|
||||
GThread *input_thread;
|
||||
|
||||
MetaSeatNative *seat;
|
||||
char *seat_id;
|
||||
MetaEventSource *event_source;
|
||||
struct libinput *libinput;
|
||||
struct libinput_seat *libinput_seat;
|
||||
GRWLock state_lock;
|
||||
|
||||
GSList *devices;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
|
||||
GHashTable *touch_states;
|
||||
GHashTable *cursor_renderers;
|
||||
|
||||
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;
|
||||
xkb_layout_index_t layout_idx;
|
||||
uint32_t button_state;
|
||||
int button_count[KEY_CNT];
|
||||
|
||||
int device_id_next;
|
||||
GList *free_device_ids;
|
||||
|
||||
MetaBarrierManagerNative *barrier_manager;
|
||||
MetaPointerConstraintImpl *pointer_constraint;
|
||||
|
||||
MetaKeymapNative *keymap;
|
||||
MetaInputSettings *input_settings;
|
||||
|
||||
MetaViewportInfo *viewports;
|
||||
|
||||
GUdevClient *udev_client;
|
||||
guint tablet_mode_switch_state : 1;
|
||||
guint has_touchscreen : 1;
|
||||
guint has_tablet_switch : 1;
|
||||
guint touch_mode : 1;
|
||||
guint input_thread_initialized : 1;
|
||||
|
||||
/* keyboard repeat */
|
||||
gboolean repeat;
|
||||
uint32_t repeat_delay;
|
||||
uint32_t repeat_interval;
|
||||
uint32_t repeat_key;
|
||||
uint32_t repeat_count;
|
||||
uint32_t repeat_timer;
|
||||
ClutterInputDevice *repeat_device;
|
||||
|
||||
float pointer_x;
|
||||
float pointer_y;
|
||||
|
||||
/* Emulation of discrete scroll events out of smooth ones */
|
||||
float accum_scroll_dx;
|
||||
float accum_scroll_dy;
|
||||
|
||||
gboolean released;
|
||||
};
|
||||
|
||||
#define META_TYPE_SEAT_IMPL meta_seat_impl_get_type ()
|
||||
G_DECLARE_FINAL_TYPE (MetaSeatImpl, meta_seat_impl,
|
||||
META, SEAT_IMPL, GObject)
|
||||
|
||||
MetaSeatImpl * meta_seat_impl_new (MetaSeatNative *seat,
|
||||
const gchar *seat_id);
|
||||
|
||||
void meta_seat_impl_run_input_task (MetaSeatImpl *impl,
|
||||
GTask *task,
|
||||
GSourceFunc dispatch_func);
|
||||
|
||||
void meta_seat_impl_notify_key (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
uint32_t state,
|
||||
gboolean update_keys);
|
||||
|
||||
void meta_seat_impl_notify_relative_motion (MetaSeatImpl *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float dx,
|
||||
float dy,
|
||||
float dx_unaccel,
|
||||
float dy_unaccel);
|
||||
|
||||
void meta_seat_impl_notify_absolute_motion (MetaSeatImpl *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
double *axes);
|
||||
|
||||
void meta_seat_impl_notify_button (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
uint32_t state);
|
||||
|
||||
void meta_seat_impl_notify_scroll_continuous (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy,
|
||||
ClutterScrollSource source,
|
||||
ClutterScrollFinishFlags flags);
|
||||
|
||||
void meta_seat_impl_notify_discrete_scroll (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
double discrete_dx,
|
||||
double discrete_dy,
|
||||
ClutterScrollSource source);
|
||||
|
||||
void meta_seat_impl_notify_touch_event (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
ClutterEventType evtype,
|
||||
uint64_t time_us,
|
||||
int slot,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
void meta_seat_impl_set_libinput_seat (MetaSeatImpl *seat,
|
||||
struct libinput_seat *libinput_seat);
|
||||
|
||||
void meta_seat_impl_sync_leds (MetaSeatImpl *seat);
|
||||
|
||||
MetaTouchState * meta_seat_impl_acquire_touch_state (MetaSeatImpl *seat,
|
||||
int seat_slot);
|
||||
MetaTouchState * meta_seat_impl_lookup_touch_state (MetaSeatImpl *seat,
|
||||
int seat_slot);
|
||||
|
||||
void meta_seat_impl_release_touch_state (MetaSeatImpl *seat,
|
||||
int seat_slot);
|
||||
|
||||
gint meta_seat_impl_acquire_device_id (MetaSeatImpl *seat);
|
||||
void meta_seat_impl_release_device_id (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_seat_impl_update_xkb_state (MetaSeatImpl *seat);
|
||||
|
||||
/**
|
||||
* MetaOpenDeviceCallback:
|
||||
* @path: the device path
|
||||
* @flags: flags to be passed to open
|
||||
*
|
||||
* This callback will be called when Clutter needs to access an input
|
||||
* device. It should return an open file descriptor for the file at @path,
|
||||
* or -1 if opening failed.
|
||||
*/
|
||||
typedef int (* MetaOpenDeviceCallback) (const char *path,
|
||||
int flags,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
typedef void (* MetaCloseDeviceCallback) (int fd,
|
||||
gpointer user_data);
|
||||
|
||||
void meta_seat_impl_set_device_callbacks (MetaOpenDeviceCallback open_callback,
|
||||
MetaCloseDeviceCallback close_callback,
|
||||
gpointer user_data);
|
||||
|
||||
void meta_seat_impl_release_devices (MetaSeatImpl *seat);
|
||||
void meta_seat_impl_reclaim_devices (MetaSeatImpl *seat);
|
||||
|
||||
struct xkb_state * meta_seat_impl_get_xkb_state (MetaSeatImpl *seat);
|
||||
|
||||
void meta_seat_impl_set_keyboard_map (MetaSeatImpl *seat,
|
||||
struct xkb_keymap *keymap);
|
||||
|
||||
void meta_seat_impl_set_keyboard_layout_index (MetaSeatImpl *seat,
|
||||
xkb_layout_index_t idx);
|
||||
|
||||
void meta_seat_impl_set_keyboard_numlock (MetaSeatImpl *seat,
|
||||
gboolean numlock_state);
|
||||
|
||||
void meta_seat_impl_set_keyboard_repeat (MetaSeatImpl *seat,
|
||||
gboolean repeat,
|
||||
uint32_t delay,
|
||||
uint32_t interval);
|
||||
|
||||
MetaBarrierManagerNative * meta_seat_impl_get_barrier_manager (MetaSeatImpl *seat);
|
||||
|
||||
void meta_seat_impl_set_pointer_constraint (MetaSeatImpl *seat,
|
||||
MetaPointerConstraintImpl *impl);
|
||||
void meta_seat_impl_set_viewports (MetaSeatImpl *seat,
|
||||
MetaViewportInfo *viewports);
|
||||
|
||||
void meta_seat_impl_warp_pointer (MetaSeatImpl *seat,
|
||||
int x,
|
||||
int y);
|
||||
ClutterVirtualInputDevice *
|
||||
meta_seat_impl_create_virtual_device (MetaSeatImpl *seat,
|
||||
ClutterInputDeviceType device_type);
|
||||
gboolean meta_seat_impl_query_state (MetaSeatImpl *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *modifiers);
|
||||
ClutterInputDevice * meta_seat_impl_get_pointer (MetaSeatImpl *seat);
|
||||
ClutterInputDevice * meta_seat_impl_get_keyboard (MetaSeatImpl *seat);
|
||||
GSList * meta_seat_impl_get_devices (MetaSeatImpl *seat);
|
||||
|
||||
MetaKeymapNative * meta_seat_impl_get_keymap (MetaSeatImpl *seat);
|
||||
|
||||
void meta_seat_impl_notify_kbd_a11y_flags_changed (MetaSeatImpl *impl,
|
||||
MetaKeyboardA11yFlags new_flags,
|
||||
MetaKeyboardA11yFlags what_changed);
|
||||
void meta_seat_impl_notify_kbd_a11y_mods_state_changed (MetaSeatImpl *impl,
|
||||
xkb_mod_mask_t new_latched_mods,
|
||||
xkb_mod_mask_t new_locked_mods);
|
||||
void meta_seat_impl_notify_bell (MetaSeatImpl *impl);
|
||||
|
||||
MetaInputSettings * meta_seat_impl_get_input_settings (MetaSeatImpl *impl);
|
||||
|
||||
#endif /* META_SEAT_IMPL_H */
|
File diff suppressed because it is too large
Load Diff
@ -27,220 +27,49 @@
|
||||
#include <libinput.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
|
||||
#include "backends/meta-viewport-info.h"
|
||||
#include "backends/native/meta-barrier-native.h"
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#include "backends/native/meta-keymap-native.h"
|
||||
#include "backends/native/meta-pointer-constraint-native.h"
|
||||
#include "backends/native/meta-seat-impl.h"
|
||||
#include "backends/native/meta-xkb-utils.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
typedef struct _MetaTouchState MetaTouchState;
|
||||
typedef struct _MetaSeatNative MetaSeatNative;
|
||||
typedef struct _MetaEventSource MetaEventSource;
|
||||
|
||||
/**
|
||||
* MetaPointerConstrainCallback:
|
||||
* @device: the core pointer device
|
||||
* @time: the event time in milliseconds
|
||||
* @x: (inout): the new X coordinate
|
||||
* @y: (inout): the new Y coordinate
|
||||
* @user_data: user data passed to this function
|
||||
*
|
||||
* This callback will be called for all pointer motion events, and should
|
||||
* update (@x, @y) to constrain the pointer position appropriately.
|
||||
* The subsequent motion event will use the updated values as the new coordinates.
|
||||
* Note that the coordinates are not clamped to the stage size, and the callback
|
||||
* must make sure that this happens before it returns.
|
||||
* Also note that the event will be emitted even if the pointer is constrained
|
||||
* to be in the same position.
|
||||
*/
|
||||
typedef void (* MetaPointerConstrainCallback) (ClutterInputDevice *device,
|
||||
uint32_t time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y,
|
||||
gpointer user_data);
|
||||
typedef void (* MetaRelativeMotionFilter) (ClutterInputDevice *device,
|
||||
float x,
|
||||
float y,
|
||||
float *dx,
|
||||
float *dy,
|
||||
gpointer user_data);
|
||||
|
||||
struct _MetaTouchState
|
||||
{
|
||||
MetaSeatNative *seat;
|
||||
|
||||
int device_slot;
|
||||
int seat_slot;
|
||||
graphene_point_t coords;
|
||||
};
|
||||
|
||||
struct _MetaSeatNative
|
||||
{
|
||||
ClutterSeat parent_instance;
|
||||
|
||||
MetaSeatImpl *impl;
|
||||
char *seat_id;
|
||||
MetaEventSource *event_source;
|
||||
struct libinput *libinput;
|
||||
struct libinput_seat *libinput_seat;
|
||||
|
||||
GSList *devices;
|
||||
GList *devices;
|
||||
struct xkb_keymap *xkb_keymap;
|
||||
xkb_layout_index_t xkb_layout_index;
|
||||
|
||||
ClutterInputDevice *core_pointer;
|
||||
ClutterInputDevice *core_keyboard;
|
||||
|
||||
MetaTouchState **touch_states;
|
||||
int n_alloc_touch_states;
|
||||
|
||||
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;
|
||||
xkb_layout_index_t layout_idx;
|
||||
uint32_t button_state;
|
||||
int button_count[KEY_CNT];
|
||||
|
||||
ClutterStage *stage;
|
||||
ClutterStageManager *stage_manager;
|
||||
gulong stage_added_handler;
|
||||
gulong stage_removed_handler;
|
||||
|
||||
int device_id_next;
|
||||
GList *free_device_ids;
|
||||
|
||||
MetaPointerConstrainCallback constrain_callback;
|
||||
gpointer constrain_data;
|
||||
GDestroyNotify constrain_data_notify;
|
||||
|
||||
MetaRelativeMotionFilter relative_motion_filter;
|
||||
gpointer relative_motion_filter_user_data;
|
||||
|
||||
GSList *event_filters;
|
||||
|
||||
MetaKeymapNative *keymap;
|
||||
|
||||
GUdevClient *udev_client;
|
||||
guint tablet_mode_switch_state : 1;
|
||||
guint has_touchscreen : 1;
|
||||
guint has_tablet_switch : 1;
|
||||
guint touch_mode : 1;
|
||||
|
||||
/* keyboard repeat */
|
||||
gboolean repeat;
|
||||
uint32_t repeat_delay;
|
||||
uint32_t repeat_interval;
|
||||
uint32_t repeat_key;
|
||||
uint32_t repeat_count;
|
||||
uint32_t repeat_timer;
|
||||
ClutterInputDevice *repeat_device;
|
||||
|
||||
float pointer_x;
|
||||
float pointer_y;
|
||||
|
||||
/* Emulation of discrete scroll events out of smooth ones */
|
||||
float accum_scroll_dx;
|
||||
float accum_scroll_dy;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaKmsCursorRenderer *kms_cursor_renderer;
|
||||
GHashTable *tablet_cursors;
|
||||
|
||||
gboolean released;
|
||||
gboolean touch_mode;
|
||||
};
|
||||
|
||||
#define META_TYPE_SEAT_NATIVE meta_seat_native_get_type ()
|
||||
G_DECLARE_FINAL_TYPE (MetaSeatNative, meta_seat_native,
|
||||
META, SEAT_NATIVE, ClutterSeat)
|
||||
|
||||
void meta_seat_native_notify_key (MetaSeatNative *seat,
|
||||
ClutterInputDevice *device,
|
||||
uint64_t time_us,
|
||||
uint32_t key,
|
||||
uint32_t state,
|
||||
gboolean update_keys);
|
||||
|
||||
void meta_seat_native_notify_relative_motion (MetaSeatNative *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float dx,
|
||||
float dy,
|
||||
float dx_unaccel,
|
||||
float dy_unaccel);
|
||||
|
||||
void meta_seat_native_notify_absolute_motion (MetaSeatNative *seat_evdev,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
double *axes);
|
||||
|
||||
void meta_seat_native_notify_button (MetaSeatNative *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
uint32_t state);
|
||||
|
||||
void meta_seat_native_notify_scroll_continuous (MetaSeatNative *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
double dx,
|
||||
double dy,
|
||||
ClutterScrollSource source,
|
||||
ClutterScrollFinishFlags flags);
|
||||
|
||||
void meta_seat_native_notify_discrete_scroll (MetaSeatNative *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
uint64_t time_us,
|
||||
double discrete_dx,
|
||||
double discrete_dy,
|
||||
ClutterScrollSource source);
|
||||
|
||||
void meta_seat_native_notify_touch_event (MetaSeatNative *seat,
|
||||
ClutterInputDevice *input_device,
|
||||
ClutterEventType evtype,
|
||||
uint64_t time_us,
|
||||
int slot,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
void meta_seat_native_set_libinput_seat (MetaSeatNative *seat,
|
||||
struct libinput_seat *libinput_seat);
|
||||
|
||||
void meta_seat_native_sync_leds (MetaSeatNative *seat);
|
||||
|
||||
ClutterInputDevice * meta_seat_native_get_device (MetaSeatNative *seat,
|
||||
int id);
|
||||
|
||||
MetaTouchState * meta_seat_native_acquire_touch_state (MetaSeatNative *seat,
|
||||
int device_slot);
|
||||
|
||||
void meta_seat_native_release_touch_state (MetaSeatNative *seat,
|
||||
MetaTouchState *touch_state);
|
||||
|
||||
void meta_seat_native_set_stage (MetaSeatNative *seat,
|
||||
ClutterStage *stage);
|
||||
ClutterStage * meta_seat_native_get_stage (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_clear_repeat_timer (MetaSeatNative *seat);
|
||||
|
||||
gint meta_seat_native_acquire_device_id (MetaSeatNative *seat);
|
||||
void meta_seat_native_release_device_id (MetaSeatNative *seat,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_seat_native_update_xkb_state (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_constrain_pointer (MetaSeatNative *seat,
|
||||
ClutterInputDevice *core_pointer,
|
||||
uint64_t time_us,
|
||||
float x,
|
||||
float y,
|
||||
float *new_x,
|
||||
float *new_y);
|
||||
|
||||
void meta_seat_native_filter_relative_motion (MetaSeatNative *seat,
|
||||
ClutterInputDevice *device,
|
||||
float x,
|
||||
float y,
|
||||
float *dx,
|
||||
float *dy);
|
||||
|
||||
void meta_seat_native_dispatch (MetaSeatNative *seat);
|
||||
|
||||
/**
|
||||
* MetaOpenDeviceCallback:
|
||||
* @path: the device path
|
||||
@ -264,30 +93,10 @@ void meta_seat_native_set_device_callbacks (MetaOpenDeviceCallback open_callba
|
||||
void meta_seat_native_release_devices (MetaSeatNative *seat);
|
||||
void meta_seat_native_reclaim_devices (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_set_pointer_constrain_callback (MetaSeatNative *seat,
|
||||
MetaPointerConstrainCallback callback,
|
||||
gpointer user_data,
|
||||
GDestroyNotify user_data_notify);
|
||||
|
||||
void meta_seat_native_set_relative_motion_filter (MetaSeatNative *seat,
|
||||
MetaRelativeMotionFilter filter,
|
||||
gpointer user_data);
|
||||
|
||||
typedef gboolean (* MetaEvdevFilterFunc) (struct libinput_event *event,
|
||||
gpointer data);
|
||||
|
||||
void meta_seat_native_add_filter (MetaSeatNative *seat,
|
||||
MetaEvdevFilterFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify destroy_notify);
|
||||
void meta_seat_native_remove_filter (MetaSeatNative *seat,
|
||||
MetaEvdevFilterFunc func,
|
||||
gpointer data);
|
||||
|
||||
struct xkb_state * meta_seat_native_get_xkb_state (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_set_keyboard_map (MetaSeatNative *seat,
|
||||
struct xkb_keymap *keymap);
|
||||
const char *layouts,
|
||||
const char *variants,
|
||||
const char *options);
|
||||
|
||||
struct xkb_keymap * meta_seat_native_get_keyboard_map (MetaSeatNative *seat);
|
||||
|
||||
@ -304,4 +113,17 @@ void meta_seat_native_set_keyboard_repeat (MetaSeatNative *seat,
|
||||
uint32_t delay,
|
||||
uint32_t interval);
|
||||
|
||||
MetaBarrierManagerNative * meta_seat_native_get_barrier_manager (MetaSeatNative *seat);
|
||||
|
||||
void meta_seat_native_set_pointer_constraint (MetaSeatNative *seat,
|
||||
MetaPointerConstraintImpl *impl);
|
||||
MetaCursorRenderer * meta_seat_native_get_cursor_renderer (MetaSeatNative *seat,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
void meta_seat_native_set_viewports (MetaSeatNative *seat,
|
||||
MetaViewportInfo *viewports);
|
||||
void meta_seat_native_notify_kbd_a11y_change (MetaSeatNative *seat,
|
||||
MetaKeyboardA11yFlags new_flags,
|
||||
MetaKeyboardA11yFlags what_changed);
|
||||
|
||||
#endif /* META_SEAT_NATIVE_H */
|
||||
|
@ -49,6 +49,45 @@ struct _MetaVirtualInputDeviceNative
|
||||
int button_count[KEY_CNT];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t time_us;
|
||||
double x;
|
||||
double y;
|
||||
} MetaVirtualEventMotion;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t time_us;
|
||||
uint32_t button;
|
||||
ClutterButtonState button_state;
|
||||
} MetaVirtualEventButton;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t time_us;
|
||||
double dx;
|
||||
double dy;
|
||||
ClutterScrollDirection direction;
|
||||
ClutterScrollSource scroll_source;
|
||||
ClutterScrollFinishFlags finish_flags;
|
||||
} MetaVirtualEventScroll;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t time_us;
|
||||
uint32_t key;
|
||||
ClutterKeyState key_state;
|
||||
} MetaVirtualEventKey;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t time_us;
|
||||
int device_slot;
|
||||
double x;
|
||||
double y;
|
||||
} MetaVirtualEventTouch;
|
||||
|
||||
G_DEFINE_TYPE (MetaVirtualInputDeviceNative,
|
||||
meta_virtual_input_device_native,
|
||||
CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE)
|
||||
@ -107,11 +146,10 @@ get_button_type (uint16_t code)
|
||||
return EVDEV_BUTTON_TYPE_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
static gboolean
|
||||
release_device (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
MetaVirtualInputDeviceNative *virtual_evdev = g_task_get_task_data (task);
|
||||
int code;
|
||||
uint64_t time_us;
|
||||
|
||||
@ -119,7 +157,7 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
|
||||
meta_topic (META_DEBUG_INPUT,
|
||||
"Releasing pressed buttons while destroying virtual input device "
|
||||
"(device %p)\n", virtual_device);
|
||||
"(device %p)\n", virtual_evdev);
|
||||
|
||||
for (code = 0; code < G_N_ELEMENTS (virtual_evdev->button_count); code++)
|
||||
{
|
||||
@ -129,7 +167,7 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
switch (get_button_type (code))
|
||||
{
|
||||
case EVDEV_BUTTON_TYPE_KEY:
|
||||
meta_seat_native_notify_key (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_key (virtual_evdev->seat->impl,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
code,
|
||||
@ -137,7 +175,7 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
TRUE);
|
||||
break;
|
||||
case EVDEV_BUTTON_TYPE_BUTTON:
|
||||
meta_seat_native_notify_button (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_button (virtual_evdev->seat->impl,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
code,
|
||||
@ -149,6 +187,31 @@ release_pressed_buttons (ClutterVirtualInputDevice *virtual_device)
|
||||
|
||||
update_button_count (virtual_evdev, code, 0);
|
||||
}
|
||||
|
||||
g_clear_object (&virtual_evdev->device);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_relative_motion (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventMotion *event = g_task_get_task_data (task);
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
meta_seat_impl_notify_relative_motion (seat,
|
||||
virtual_evdev->device,
|
||||
event->time_us,
|
||||
event->x, event->y,
|
||||
event->x, event->y);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -157,19 +220,43 @@ meta_virtual_input_device_native_notify_relative_motion (ClutterVirtualInputDevi
|
||||
double dx,
|
||||
double dy)
|
||||
{
|
||||
MetaVirtualEventMotion *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventMotion, 1);
|
||||
event->time_us = time_us;
|
||||
event->x = dx;
|
||||
event->y = dy;
|
||||
|
||||
meta_seat_native_notify_relative_motion (virtual_evdev->seat,
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_relative_motion);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_absolute_motion (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventMotion *event = g_task_get_task_data (task);
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
meta_seat_impl_notify_absolute_motion (seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
dx, dy,
|
||||
dx, dy);
|
||||
event->time_us,
|
||||
event->x, event->y,
|
||||
NULL);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -178,19 +265,23 @@ meta_virtual_input_device_native_notify_absolute_motion (ClutterVirtualInputDevi
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
MetaVirtualEventMotion *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventMotion, 1);
|
||||
event->time_us = time_us;
|
||||
event->x = x;
|
||||
event->y = y;
|
||||
|
||||
meta_seat_native_notify_absolute_motion (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
x, y,
|
||||
NULL);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_absolute_motion);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -213,50 +304,123 @@ translate_to_evdev_button (int clutter_button)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_button (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventButton *event = g_task_get_task_data (task);
|
||||
int button_count;
|
||||
int evdev_button;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
evdev_button = translate_to_evdev_button (event->button);
|
||||
|
||||
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
||||
evdev_button);
|
||||
goto out;
|
||||
}
|
||||
|
||||
button_count = update_button_count (virtual_evdev, evdev_button,
|
||||
event->button_state);
|
||||
if (button_count < 0 || button_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
|
||||
event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
|
||||
"presses" : "releases");
|
||||
update_button_count (virtual_evdev, evdev_button, 1 - event->button_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_INPUT,
|
||||
"Emitting virtual button-%s of button 0x%x (device %p)\n",
|
||||
event->button_state == CLUTTER_BUTTON_STATE_PRESSED ?
|
||||
"press" : "release",
|
||||
evdev_button, virtual_evdev);
|
||||
|
||||
meta_seat_impl_notify_button (seat,
|
||||
virtual_evdev->device,
|
||||
event->time_us,
|
||||
evdev_button,
|
||||
event->button_state);
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_virtual_input_device_native_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state)
|
||||
{
|
||||
MetaVirtualEventButton *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
int button_count;
|
||||
int evdev_button;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventButton, 1);
|
||||
event->time_us = time_us;
|
||||
event->button = button;
|
||||
event->button_state = button_state;
|
||||
|
||||
evdev_button = translate_to_evdev_button (button);
|
||||
|
||||
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
||||
evdev_button);
|
||||
return;
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_button);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
button_count = update_button_count (virtual_evdev, evdev_button, button_state);
|
||||
if (button_count < 0 || button_count > 1)
|
||||
static gboolean
|
||||
notify_key (GTask *task)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
|
||||
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
|
||||
update_button_count (virtual_evdev, evdev_button, 1 - button_state);
|
||||
return;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventKey *event = g_task_get_task_data (task);
|
||||
int key_count;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
if (get_button_type (event->key) != EVDEV_BUTTON_TYPE_KEY)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", event->key);
|
||||
goto out;
|
||||
}
|
||||
|
||||
key_count = update_button_count (virtual_evdev, event->key, event->key_state);
|
||||
if (key_count < 0 || key_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", event->key,
|
||||
event->key_state == CLUTTER_KEY_STATE_PRESSED ?
|
||||
"presses" : "releases");
|
||||
update_button_count (virtual_evdev, event->key, 1 - event->key_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_INPUT,
|
||||
"Emitting virtual button-%s of button 0x%x (device %p)\n",
|
||||
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "press" : "release",
|
||||
evdev_button, virtual_device);
|
||||
"Emitting virtual key-%s of key 0x%x (device %p)\n",
|
||||
event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
||||
event->key, virtual_evdev);
|
||||
|
||||
meta_seat_native_notify_button (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_key (seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
evdev_button,
|
||||
button_state);
|
||||
event->time_us,
|
||||
event->key,
|
||||
event->key_state,
|
||||
TRUE);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -265,41 +429,23 @@ meta_virtual_input_device_native_notify_key (ClutterVirtualInputDevice *virtual_
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
MetaVirtualEventKey *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
int key_count;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventKey, 1);
|
||||
event->time_us = time_us;
|
||||
event->key = key;
|
||||
event->key_state = key_state;
|
||||
|
||||
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 < 0 || key_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", key,
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
|
||||
update_button_count (virtual_evdev, key, 1 - key_state);
|
||||
return;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_INPUT,
|
||||
"Emitting virtual key-%s of key 0x%x (device %p)\n",
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
||||
key, virtual_device);
|
||||
|
||||
meta_seat_native_notify_key (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
key,
|
||||
key_state,
|
||||
TRUE);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_key);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -320,7 +466,7 @@ pick_keycode_for_keyval_in_current_group (ClutterVirtualInputDevice *virtual_dev
|
||||
backend = clutter_get_default_backend ();
|
||||
keymap = clutter_seat_get_keymap (clutter_backend_get_default_seat (backend));
|
||||
xkb_keymap = meta_keymap_native_get_keyboard_map (META_KEYMAP_NATIVE (keymap));
|
||||
state = virtual_evdev->seat->xkb;
|
||||
state = meta_seat_impl_get_xkb_state (virtual_evdev->seat->impl);
|
||||
|
||||
layout = xkb_state_serialize_layout (state, XKB_STATE_LAYOUT_EFFECTIVE);
|
||||
min_keycode = xkb_keymap_min_keycode (xkb_keymap);
|
||||
@ -389,7 +535,7 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
||||
evcode, virtual_device);
|
||||
|
||||
meta_seat_native_notify_key (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_key (virtual_evdev->seat->impl,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
evcode,
|
||||
@ -397,27 +543,26 @@ apply_level_modifiers (ClutterVirtualInputDevice *virtual_device,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
static gboolean
|
||||
notify_keyval (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
g_task_get_source_object (task);
|
||||
ClutterVirtualInputDevice *virtual_device =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE (virtual_evdev);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventKey *event = g_task_get_task_data (task);
|
||||
int key_count;
|
||||
guint keycode = 0, level = 0, evcode = 0;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
if (!pick_keycode_for_keyval_in_current_group (virtual_device,
|
||||
keyval, &keycode, &level))
|
||||
event->key, &keycode, &level))
|
||||
{
|
||||
g_warning ("No keycode found for keyval %x in current group", keyval);
|
||||
return;
|
||||
g_warning ("No keycode found for keyval %x in current group", event->key);
|
||||
goto out;
|
||||
}
|
||||
|
||||
clutter_input_device_keycode_to_evdev (virtual_evdev->device,
|
||||
@ -426,36 +571,66 @@ meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtu
|
||||
if (get_button_type (evcode) != EVDEV_BUTTON_TYPE_KEY)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device key 0x%x pressed\n", evcode);
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
|
||||
key_count = update_button_count (virtual_evdev, evcode, key_state);
|
||||
key_count = update_button_count (virtual_evdev, evcode, event->key_state);
|
||||
if (key_count < 0 || key_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x key %s (ignoring)", evcode,
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED ? "presses" : "releases");
|
||||
update_button_count (virtual_evdev, evcode, 1 - key_state);
|
||||
return;
|
||||
event->key_state == CLUTTER_KEY_STATE_PRESSED ?
|
||||
"presses" : "releases");
|
||||
update_button_count (virtual_evdev, evcode, 1 - event->key_state);
|
||||
goto out;
|
||||
}
|
||||
|
||||
meta_topic (META_DEBUG_INPUT,
|
||||
"Emitting virtual key-%s of key 0x%x with modifier level %d, "
|
||||
"press count %d (device %p)\n",
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
||||
evcode, level, key_count, virtual_device);
|
||||
event->key_state == CLUTTER_KEY_STATE_PRESSED ? "press" : "release",
|
||||
evcode, level, key_count, virtual_evdev);
|
||||
|
||||
if (key_state)
|
||||
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
||||
if (event->key_state)
|
||||
apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
|
||||
|
||||
meta_seat_native_notify_key (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_key (seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
event->time_us,
|
||||
evcode,
|
||||
key_state,
|
||||
event->key_state,
|
||||
TRUE);
|
||||
|
||||
if (!key_state)
|
||||
apply_level_modifiers (virtual_device, time_us, level, key_state);
|
||||
if (!event->key_state)
|
||||
apply_level_modifiers (virtual_device, event->time_us, level, event->key_state);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_virtual_input_device_native_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
MetaVirtualEventKey *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
event = g_new0 (MetaVirtualEventKey, 1);
|
||||
event->time_us = time_us;
|
||||
event->key = keyval;
|
||||
event->key_state = key_state;
|
||||
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_keyval);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -487,28 +662,74 @@ direction_to_discrete (ClutterScrollDirection direction,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_discrete_scroll (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventScroll *event = g_task_get_task_data (task);
|
||||
double discrete_dx = 0.0, discrete_dy = 0.0;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
direction_to_discrete (event->direction, &discrete_dx, &discrete_dy);
|
||||
|
||||
meta_seat_impl_notify_discrete_scroll (seat,
|
||||
virtual_evdev->device,
|
||||
event->time_us,
|
||||
discrete_dx, discrete_dy,
|
||||
event->scroll_source);
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_virtual_input_device_native_notify_discrete_scroll (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
ClutterScrollDirection direction,
|
||||
ClutterScrollSource scroll_source)
|
||||
{
|
||||
MetaVirtualEventScroll *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
double discrete_dx = 0.0, discrete_dy = 0.0;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventScroll, 1);
|
||||
event->time_us = time_us;
|
||||
event->direction = direction;
|
||||
event->scroll_source = scroll_source;
|
||||
|
||||
direction_to_discrete (direction, &discrete_dx, &discrete_dy);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_discrete_scroll);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
meta_seat_native_notify_discrete_scroll (virtual_evdev->seat,
|
||||
static gboolean
|
||||
notify_scroll_continuous (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventScroll *event = g_task_get_task_data (task);
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
meta_seat_impl_notify_scroll_continuous (seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
discrete_dx, discrete_dy,
|
||||
scroll_source);
|
||||
event->time_us,
|
||||
event->dx, event->dy,
|
||||
event->scroll_source,
|
||||
CLUTTER_SCROLL_FINISHED_NONE);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -519,20 +740,58 @@ meta_virtual_input_device_native_notify_scroll_continuous (ClutterVirtualInputDe
|
||||
ClutterScrollSource scroll_source,
|
||||
ClutterScrollFinishFlags finish_flags)
|
||||
{
|
||||
MetaVirtualEventScroll *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventScroll, 1);
|
||||
event->time_us = time_us;
|
||||
event->dx = dx;
|
||||
event->dy = dy;
|
||||
event->scroll_source = scroll_source;
|
||||
event->finish_flags = finish_flags;
|
||||
|
||||
meta_seat_native_notify_scroll_continuous (virtual_evdev->seat,
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_scroll_continuous);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_touch_down (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventTouch *event = g_task_get_task_data (task);
|
||||
MetaTouchState *touch_state;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
touch_state = meta_seat_impl_acquire_touch_state (seat,
|
||||
event->device_slot);
|
||||
if (!touch_state)
|
||||
goto out;
|
||||
|
||||
touch_state->coords.x = event->x;
|
||||
touch_state->coords.y = event->y;
|
||||
|
||||
meta_seat_impl_notify_touch_event (seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
dx, dy,
|
||||
scroll_source,
|
||||
CLUTTER_SCROLL_FINISHED_NONE);
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
event->time_us,
|
||||
touch_state->seat_slot,
|
||||
touch_state->coords.x,
|
||||
touch_state->coords.y);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -542,32 +801,57 @@ meta_virtual_input_device_native_notify_touch_down (ClutterVirtualInputDevice *v
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
MetaVirtualEventTouch *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
MetaInputDeviceNative *device_evdev =
|
||||
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
||||
MetaTouchState *touch_state;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventTouch, 1);
|
||||
event->time_us = time_us;
|
||||
event->device_slot = device_slot;
|
||||
event->x = x;
|
||||
event->y = y;
|
||||
|
||||
touch_state = meta_input_device_native_acquire_touch_state (device_evdev,
|
||||
device_slot);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_touch_down);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_touch_motion (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventTouch *event = g_task_get_task_data (task);
|
||||
MetaTouchState *touch_state;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
touch_state = meta_seat_impl_lookup_touch_state (seat,
|
||||
event->device_slot);
|
||||
if (!touch_state)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
touch_state->coords.x = x;
|
||||
touch_state->coords.y = y;
|
||||
touch_state->coords.x = event->x;
|
||||
touch_state->coords.y = event->y;
|
||||
|
||||
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_touch_event (seat,
|
||||
virtual_evdev->device,
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
time_us,
|
||||
CLUTTER_TOUCH_UPDATE,
|
||||
event->time_us,
|
||||
touch_state->seat_slot,
|
||||
touch_state->coords.x,
|
||||
touch_state->coords.y);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -577,32 +861,57 @@ meta_virtual_input_device_native_notify_touch_motion (ClutterVirtualInputDevice
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
MetaVirtualEventTouch *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
MetaInputDeviceNative *device_evdev =
|
||||
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
||||
MetaTouchState *touch_state;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventTouch, 1);
|
||||
event->time_us = time_us;
|
||||
event->device_slot = device_slot;
|
||||
event->x = x;
|
||||
event->y = y;
|
||||
|
||||
touch_state = meta_input_device_native_lookup_touch_state (device_evdev,
|
||||
device_slot);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_touch_motion);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
notify_touch_up (GTask *task)
|
||||
{
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
g_task_get_source_object (task);
|
||||
MetaSeatImpl *seat = virtual_evdev->seat->impl;
|
||||
MetaVirtualEventTouch *event = g_task_get_task_data (task);
|
||||
MetaTouchState *touch_state;
|
||||
|
||||
if (event->time_us == CLUTTER_CURRENT_TIME)
|
||||
event->time_us = g_get_monotonic_time ();
|
||||
|
||||
touch_state = meta_seat_impl_lookup_touch_state (seat,
|
||||
event->device_slot);
|
||||
if (!touch_state)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
touch_state->coords.x = x;
|
||||
touch_state->coords.y = y;
|
||||
|
||||
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
||||
meta_seat_impl_notify_touch_event (seat,
|
||||
virtual_evdev->device,
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
time_us,
|
||||
CLUTTER_TOUCH_END,
|
||||
event->time_us,
|
||||
touch_state->seat_slot,
|
||||
touch_state->coords.x,
|
||||
touch_state->coords.y);
|
||||
|
||||
meta_seat_impl_release_touch_state (virtual_evdev->seat->impl,
|
||||
touch_state->seat_slot);
|
||||
|
||||
out:
|
||||
g_task_return_boolean (task, TRUE);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -610,31 +919,22 @@ meta_virtual_input_device_native_notify_touch_up (ClutterVirtualInputDevice *vir
|
||||
uint64_t time_us,
|
||||
int device_slot)
|
||||
{
|
||||
MetaVirtualEventTouch *event;
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (virtual_device);
|
||||
MetaInputDeviceNative *device_evdev =
|
||||
META_INPUT_DEVICE_NATIVE (virtual_evdev->device);
|
||||
MetaTouchState *touch_state;
|
||||
GTask *task;
|
||||
|
||||
g_return_if_fail (virtual_evdev->device != NULL);
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
event = g_new0 (MetaVirtualEventTouch, 1);
|
||||
event->time_us = time_us;
|
||||
event->device_slot = device_slot;
|
||||
|
||||
touch_state = meta_input_device_native_lookup_touch_state (device_evdev,
|
||||
device_slot);
|
||||
if (!touch_state)
|
||||
return;
|
||||
|
||||
meta_seat_native_notify_touch_event (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
CLUTTER_TOUCH_BEGIN,
|
||||
time_us,
|
||||
touch_state->seat_slot,
|
||||
touch_state->coords.x,
|
||||
touch_state->coords.y);
|
||||
|
||||
meta_input_device_native_release_touch_state (device_evdev, touch_state);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, event, g_free);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) notify_touch_up);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -685,7 +985,6 @@ meta_virtual_input_device_native_constructed (GObject *object)
|
||||
MetaVirtualInputDeviceNative *virtual_evdev =
|
||||
META_VIRTUAL_INPUT_DEVICE_NATIVE (object);
|
||||
ClutterInputDeviceType device_type;
|
||||
ClutterStage *stage;
|
||||
|
||||
device_type = clutter_virtual_input_device_get_device_type (virtual_device);
|
||||
|
||||
@ -694,16 +993,9 @@ meta_virtual_input_device_native_constructed (GObject *object)
|
||||
device_type, virtual_device);
|
||||
|
||||
virtual_evdev->device =
|
||||
meta_input_device_native_new_virtual (virtual_evdev->seat,
|
||||
meta_input_device_native_new_virtual (virtual_evdev->seat->impl,
|
||||
device_type,
|
||||
CLUTTER_INPUT_MODE_SLAVE);
|
||||
|
||||
stage = meta_seat_native_get_stage (virtual_evdev->seat);
|
||||
_clutter_input_device_set_stage (virtual_evdev->device, stage);
|
||||
|
||||
g_signal_emit_by_name (virtual_evdev->seat,
|
||||
"device-added",
|
||||
virtual_evdev->device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -718,12 +1010,13 @@ meta_virtual_input_device_native_dispose (GObject *object)
|
||||
|
||||
if (virtual_evdev->device)
|
||||
{
|
||||
release_pressed_buttons (virtual_device);
|
||||
g_signal_emit_by_name (virtual_evdev->seat,
|
||||
"device-removed",
|
||||
virtual_evdev->device);
|
||||
GTask *task;
|
||||
|
||||
g_clear_object (&virtual_evdev->device);
|
||||
task = g_task_new (virtual_device, NULL, NULL, NULL);
|
||||
g_task_set_task_data (task, g_object_ref (virtual_device), g_object_unref);
|
||||
meta_seat_impl_run_input_task (virtual_evdev->seat->impl, task,
|
||||
(GSourceFunc) release_device);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
object_class->dispose (object);
|
||||
|
@ -28,7 +28,6 @@
|
||||
/*
|
||||
* _clutter_event_new_from_evdev: Create a new Clutter ClutterKeyEvent
|
||||
* @device: a ClutterInputDevice
|
||||
* @stage: the stage the event should be delivered to
|
||||
* @xkb: XKB rules to translate the event
|
||||
* @_time: timestamp of the event
|
||||
* @key: a key code coming from a Linux input device
|
||||
@ -42,7 +41,6 @@
|
||||
ClutterEvent *
|
||||
meta_key_event_new_from_evdev (ClutterInputDevice *device,
|
||||
ClutterInputDevice *core_device,
|
||||
ClutterStage *stage,
|
||||
struct xkb_state *xkb_state,
|
||||
uint32_t button_state,
|
||||
uint32_t _time,
|
||||
@ -72,7 +70,6 @@ meta_key_event_new_from_evdev (ClutterInputDevice *device,
|
||||
else
|
||||
sym = XKB_KEY_NoSymbol;
|
||||
|
||||
event->key.stage = stage;
|
||||
event->key.time = _time;
|
||||
meta_xkb_translate_state (event, xkb_state, button_state);
|
||||
event->key.hardware_keycode = key;
|
||||
@ -109,3 +106,10 @@ meta_xkb_translate_state (ClutterEvent *event,
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_LOCKED),
|
||||
xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
meta_xkb_translate_modifiers (struct xkb_state *state,
|
||||
uint32_t button_state)
|
||||
{
|
||||
return xkb_state_serialize_mods (state, XKB_STATE_MODS_EFFECTIVE) | button_state;
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
|
||||
ClutterEvent * meta_key_event_new_from_evdev (ClutterInputDevice *device,
|
||||
ClutterInputDevice *core_keyboard,
|
||||
ClutterStage *stage,
|
||||
struct xkb_state *xkb_state,
|
||||
uint32_t button_state,
|
||||
uint32_t _time,
|
||||
@ -36,5 +35,7 @@ ClutterEvent * meta_key_event_new_from_evdev (ClutterInputDevice *device,
|
||||
void meta_xkb_translate_state (ClutterEvent *event,
|
||||
struct xkb_state *xkb_state,
|
||||
uint32_t button_state);
|
||||
uint32_t meta_xkb_translate_modifiers (struct xkb_state *state,
|
||||
uint32_t button_state);
|
||||
|
||||
#endif /* META_XKB_UTILS_H */
|
||||
|
@ -41,6 +41,7 @@ struct _MetaBackendX11Cm
|
||||
{
|
||||
MetaBackendX11 parent;
|
||||
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
char *keymap_layouts;
|
||||
char *keymap_variants;
|
||||
char *keymap_options;
|
||||
@ -116,13 +117,23 @@ meta_backend_x11_cm_create_monitor_manager (MetaBackend *backend,
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_x11_cm_create_cursor_renderer (MetaBackend *backend)
|
||||
meta_backend_x11_cm_get_cursor_renderer (MetaBackend *backend,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_X11,
|
||||
MetaBackendX11Cm *x11_cm = META_BACKEND_X11_CM (backend);
|
||||
|
||||
if (!x11_cm->cursor_renderer)
|
||||
{
|
||||
x11_cm->cursor_renderer =
|
||||
g_object_new (META_TYPE_CURSOR_RENDERER_X11,
|
||||
"backend", backend,
|
||||
"device", device,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return x11_cm->cursor_renderer;
|
||||
}
|
||||
|
||||
static MetaCursorTracker *
|
||||
meta_backend_x11_cm_create_cursor_tracker (MetaBackend *backend)
|
||||
{
|
||||
@ -444,7 +455,7 @@ meta_backend_x11_cm_class_init (MetaBackendX11CmClass *klass)
|
||||
backend_class->post_init = meta_backend_x11_cm_post_init;
|
||||
backend_class->create_renderer = meta_backend_x11_cm_create_renderer;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_cm_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_x11_cm_create_cursor_renderer;
|
||||
backend_class->get_cursor_renderer = meta_backend_x11_cm_get_cursor_renderer;
|
||||
backend_class->create_cursor_tracker = meta_backend_x11_cm_create_cursor_tracker;
|
||||
backend_class->create_input_settings = meta_backend_x11_cm_create_input_settings;
|
||||
backend_class->update_screen_size = meta_backend_x11_cm_update_screen_size;
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "backends/x11/meta-seat-x11.h"
|
||||
#include "backends/x11/meta-stage-x11.h"
|
||||
#include "backends/x11/meta-renderer-x11.h"
|
||||
#include "backends/x11/meta-xkb-a11y-x11.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "clutter/x11/clutter-x11.h"
|
||||
#include "compositor/compositor-private.h"
|
||||
@ -519,12 +520,24 @@ on_monitors_changed (MetaMonitorManager *manager,
|
||||
priv->cached_current_logical_monitor = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_kbd_a11y_changed (MetaInputSettings *input_settings,
|
||||
MetaKbdA11ySettings *a11y_settings,
|
||||
MetaBackend *backend)
|
||||
{
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
|
||||
meta_seat_x11_apply_kbd_a11y_settings (seat, a11y_settings);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_post_init (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaInputSettings *input_settings;
|
||||
int major, minor;
|
||||
gboolean has_xi = FALSE;
|
||||
|
||||
@ -577,6 +590,15 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
|
||||
"_MUTTER_TOUCH_SEQUENCE_SYNC",
|
||||
False);
|
||||
|
||||
input_settings = meta_backend_get_input_settings (backend);
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
g_signal_connect_object (meta_backend_get_input_settings (backend),
|
||||
"kbd-a11y-changed",
|
||||
G_CALLBACK (on_kbd_a11y_changed), backend, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterBackend *
|
||||
@ -677,7 +699,7 @@ meta_backend_x11_get_current_logical_monitor (MetaBackend *backend)
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
MetaCursorTracker *cursor_tracker;
|
||||
int x, y;
|
||||
graphene_point_t point;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
|
||||
@ -685,10 +707,11 @@ meta_backend_x11_get_current_logical_monitor (MetaBackend *backend)
|
||||
return priv->cached_current_logical_monitor;
|
||||
|
||||
cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
|
||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
logical_monitor =
|
||||
meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
|
||||
meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
point.x, point.y);
|
||||
|
||||
if (!logical_monitor && monitor_manager->logical_monitors)
|
||||
logical_monitor = monitor_manager->logical_monitors->data;
|
||||
|
@ -69,10 +69,8 @@ static void
|
||||
update_position (MetaCursorTrackerX11 *tracker_x11)
|
||||
{
|
||||
MetaCursorTracker *tracker = META_CURSOR_TRACKER (tracker_x11);
|
||||
int x, y;
|
||||
|
||||
meta_cursor_tracker_get_pointer (tracker, &x, &y, NULL);
|
||||
meta_cursor_tracker_update_position (tracker, x, y);
|
||||
meta_cursor_tracker_update_position (tracker);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include <gudev/gudev.h>
|
||||
#endif
|
||||
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "core/display-private.h"
|
||||
#include "meta/meta-x11-errors.h"
|
||||
@ -665,15 +664,6 @@ meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings,
|
||||
g_warning ("Could not set tablet mapping for %s",
|
||||
clutter_input_device_get_device_name (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterInputDeviceMapping dev_mapping;
|
||||
|
||||
dev_mapping = (mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE) ?
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE :
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE;
|
||||
clutter_input_device_set_mapping_mode (device, dev_mapping);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -750,37 +740,19 @@ meta_input_settings_x11_set_tablet_area (MetaInputSettings *settings,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
meta_input_settings_x11_set_tablet_aspect_ratio (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaLogicalMonitor *logical_monitor,
|
||||
gboolean keep_aspect)
|
||||
gdouble aspect_ratio)
|
||||
{
|
||||
gint32 width, height, dev_x, dev_y, dev_width, dev_height, area[4] = { 0 };
|
||||
gint32 dev_x, dev_y, dev_width, dev_height, area[4] = { 0 };
|
||||
|
||||
if (!device_query_area (device, &dev_x, &dev_y, &dev_width, &dev_height))
|
||||
return;
|
||||
|
||||
if (keep_aspect)
|
||||
if (aspect_ratio > 0)
|
||||
{
|
||||
double aspect_ratio, dev_aspect;
|
||||
double dev_aspect;
|
||||
|
||||
if (logical_monitor)
|
||||
{
|
||||
width = logical_monitor->rect.width;
|
||||
height = logical_monitor->rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaBackend *backend;
|
||||
|
||||
backend = meta_get_backend ();
|
||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
meta_monitor_manager_get_screen_size (monitor_manager,
|
||||
&width, &height);
|
||||
}
|
||||
|
||||
aspect_ratio = (double) width / height;
|
||||
dev_aspect = (double) dev_width / dev_height;
|
||||
|
||||
if (dev_aspect > aspect_ratio)
|
||||
@ -952,7 +924,7 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
|
||||
input_settings_class->set_keyboard_repeat = meta_input_settings_x11_set_keyboard_repeat;
|
||||
|
||||
input_settings_class->set_tablet_mapping = meta_input_settings_x11_set_tablet_mapping;
|
||||
input_settings_class->set_tablet_keep_aspect = meta_input_settings_x11_set_tablet_keep_aspect;
|
||||
input_settings_class->set_tablet_aspect_ratio = meta_input_settings_x11_set_tablet_aspect_ratio;
|
||||
input_settings_class->set_tablet_area = meta_input_settings_x11_set_tablet_area;
|
||||
|
||||
input_settings_class->set_mouse_accel_profile = meta_input_settings_x11_set_mouse_accel_profile;
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/x11/meta-event-x11.h"
|
||||
#include "backends/x11/meta-input-device-tool-x11.h"
|
||||
#include "backends/x11/meta-input-device-x11.h"
|
||||
@ -44,6 +46,15 @@ enum
|
||||
PROP_TOUCH_MODE,
|
||||
};
|
||||
|
||||
typedef struct _MetaTouchInfo MetaTouchInfo;
|
||||
|
||||
struct _MetaTouchInfo
|
||||
{
|
||||
ClutterEventSequence *sequence;
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
struct _MetaSeatX11
|
||||
{
|
||||
ClutterSeat parent_instance;
|
||||
@ -52,6 +63,7 @@ struct _MetaSeatX11
|
||||
GList *devices;
|
||||
GHashTable *devices_by_id;
|
||||
GHashTable *tools_by_serial;
|
||||
GHashTable *touch_coords;
|
||||
MetaKeymapX11 *keymap;
|
||||
|
||||
int pointer_id;
|
||||
@ -462,7 +474,6 @@ create_device (MetaSeatX11 *seat_x11,
|
||||
ClutterInputDeviceType source, touch_source;
|
||||
ClutterInputDevice *retval;
|
||||
ClutterInputMode mode;
|
||||
gboolean is_enabled;
|
||||
uint32_t num_touches = 0, num_rings = 0, num_strips = 0;
|
||||
char *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
|
||||
|
||||
@ -508,19 +519,16 @@ create_device (MetaSeatX11 *seat_x11,
|
||||
case XIMasterKeyboard:
|
||||
case XIMasterPointer:
|
||||
mode = CLUTTER_INPUT_MODE_MASTER;
|
||||
is_enabled = TRUE;
|
||||
break;
|
||||
|
||||
case XISlaveKeyboard:
|
||||
case XISlavePointer:
|
||||
mode = CLUTTER_INPUT_MODE_SLAVE;
|
||||
is_enabled = FALSE;
|
||||
break;
|
||||
|
||||
case XIFloatingSlave:
|
||||
default:
|
||||
mode = CLUTTER_INPUT_MODE_FLOATING;
|
||||
is_enabled = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -532,10 +540,7 @@ create_device (MetaSeatX11 *seat_x11,
|
||||
}
|
||||
|
||||
if (source == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
is_enabled = TRUE;
|
||||
get_pad_features (info, &num_rings, &num_strips);
|
||||
}
|
||||
|
||||
retval = g_object_new (META_TYPE_INPUT_DEVICE_X11,
|
||||
"name", info->name,
|
||||
@ -544,7 +549,6 @@ create_device (MetaSeatX11 *seat_x11,
|
||||
"device-type", source,
|
||||
"device-mode", mode,
|
||||
"backend", backend,
|
||||
"enabled", is_enabled,
|
||||
"vendor-id", vendor_id,
|
||||
"product-id", product_id,
|
||||
"device-node", node_path,
|
||||
@ -654,8 +658,6 @@ add_device (MetaSeatX11 *seat_x11,
|
||||
info->attachment == seat_x11->keyboard_id))
|
||||
{
|
||||
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
|
||||
seat_x11->has_touchscreens |=
|
||||
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -679,13 +681,9 @@ add_device (MetaSeatX11 *seat_x11,
|
||||
GINT_TO_POINTER (info->attachment));
|
||||
_clutter_input_device_set_associated_device (device, master);
|
||||
_clutter_input_device_add_slave (master, device);
|
||||
|
||||
g_signal_emit_by_name (seat_x11, "device-added", device);
|
||||
}
|
||||
}
|
||||
|
||||
update_touch_mode (seat_x11);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
@ -705,18 +703,7 @@ has_touchscreens (MetaSeatX11 *seat_x11)
|
||||
|
||||
static void
|
||||
remove_device (MetaSeatX11 *seat_x11,
|
||||
int device_id)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
gboolean check_touchscreens = FALSE;
|
||||
|
||||
device = g_hash_table_lookup (seat_x11->devices_by_id,
|
||||
GINT_TO_POINTER (device_id));
|
||||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||
check_touchscreens = TRUE;
|
||||
|
||||
if (device != NULL)
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
if (seat_x11->core_pointer == device)
|
||||
{
|
||||
@ -729,19 +716,41 @@ remove_device (MetaSeatX11 *seat_x11,
|
||||
else
|
||||
{
|
||||
seat_x11->devices = g_list_remove (seat_x11->devices, device);
|
||||
g_signal_emit_by_name (seat_x11, "device-removed", device);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_run_dispose (G_OBJECT (device));
|
||||
g_hash_table_remove (seat_x11->devices_by_id,
|
||||
GINT_TO_POINTER (device_id));
|
||||
}
|
||||
|
||||
if (check_touchscreens)
|
||||
static gboolean
|
||||
meta_seat_x11_handle_event_post (ClutterSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
|
||||
ClutterInputDevice *device = event->device.device;
|
||||
MetaInputSettings *input_settings;
|
||||
gboolean is_touch;
|
||||
|
||||
is_touch =
|
||||
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_DEVICE_ADDED:
|
||||
meta_input_settings_add_device (input_settings, device);
|
||||
seat_x11->has_touchscreens |= is_touch;
|
||||
break;
|
||||
case CLUTTER_DEVICE_REMOVED:
|
||||
if (is_touch)
|
||||
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
|
||||
update_touch_mode (seat_x11);
|
||||
meta_input_settings_remove_device (input_settings, device);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_touch)
|
||||
update_touch_mode (seat_x11);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -803,12 +812,14 @@ device_get_tool_serial (ClutterInputDevice *device)
|
||||
return serial_id;
|
||||
}
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
translate_hierarchy_event (ClutterBackend *backend,
|
||||
MetaSeatX11 *seat_x11,
|
||||
XIHierarchyEvent *ev)
|
||||
XIHierarchyEvent *ev,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
int i;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
for (i = 0; i < ev->num_info; i++)
|
||||
{
|
||||
@ -828,15 +839,38 @@ translate_hierarchy_event (ClutterBackend *backend,
|
||||
clutter_x11_untrap_x_errors ();
|
||||
if (info != NULL)
|
||||
{
|
||||
add_device (seat_x11, backend, &info[0], FALSE);
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = add_device (seat_x11, backend, &info[0], FALSE);
|
||||
|
||||
event->any.type = CLUTTER_DEVICE_ADDED;
|
||||
event->any.time = ev->time;
|
||||
clutter_event_set_device (event, device);
|
||||
|
||||
retval = TRUE;
|
||||
XIFreeDeviceInfo (info);
|
||||
}
|
||||
}
|
||||
else if (ev->info[i].flags & XIDeviceDisabled)
|
||||
{
|
||||
g_autoptr (ClutterInputDevice) device = NULL;
|
||||
g_debug ("Hierarchy event: device disabled");
|
||||
|
||||
remove_device (seat_x11, ev->info[i].deviceid);
|
||||
g_hash_table_steal_extended (seat_x11->devices_by_id,
|
||||
GINT_TO_POINTER (ev->info[i].deviceid),
|
||||
NULL,
|
||||
(gpointer) &device);
|
||||
|
||||
if (device != NULL)
|
||||
{
|
||||
remove_device (seat_x11, device);
|
||||
|
||||
event->any.type = CLUTTER_DEVICE_REMOVED;
|
||||
event->any.time = ev->time;
|
||||
clutter_event_set_device (event, device);
|
||||
|
||||
retval = TRUE;
|
||||
}
|
||||
}
|
||||
else if ((ev->info[i].flags & XISlaveAttached) ||
|
||||
(ev->info[i].flags & XISlaveDetached))
|
||||
@ -883,6 +917,8 @@ translate_hierarchy_event (ClutterBackend *backend,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -902,6 +938,7 @@ translate_property_event (MetaSeatX11 *seat_x11,
|
||||
{
|
||||
ClutterInputDeviceTool *tool = NULL;
|
||||
ClutterInputDeviceToolType type;
|
||||
MetaInputSettings *input_settings;
|
||||
int serial_id;
|
||||
|
||||
serial_id = device_get_tool_serial (device);
|
||||
@ -922,7 +959,8 @@ translate_property_event (MetaSeatX11 *seat_x11,
|
||||
}
|
||||
|
||||
meta_input_device_x11_update_tool (device, tool);
|
||||
g_signal_emit_by_name (seat_x11, "tool-changed", device, tool);
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
meta_input_settings_notify_tool_change (input_settings, device, tool);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1115,6 +1153,9 @@ get_event_stage (MetaSeatX11 *seat_x11,
|
||||
}
|
||||
break;
|
||||
|
||||
case XI_HierarchyChanged:
|
||||
return CLUTTER_STAGE (meta_backend_get_stage (meta_get_backend ()));
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -1290,13 +1331,15 @@ static void
|
||||
on_keymap_state_change (MetaKeymapX11 *keymap_x11,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterSeat *seat = CLUTTER_SEAT (data);
|
||||
ClutterKbdA11ySettings kbd_a11y_settings;
|
||||
ClutterSeat *seat = data;
|
||||
MetaInputSettings *input_settings;
|
||||
MetaKbdA11ySettings kbd_a11y_settings;
|
||||
|
||||
/* On keymaps state change, just reapply the current settings, it'll
|
||||
* take care of enabling/disabling mousekeys based on NumLock state.
|
||||
*/
|
||||
clutter_seat_get_kbd_a11y_settings (seat, &kbd_a11y_settings);
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
meta_input_settings_get_kbd_a11y_settings (input_settings, &kbd_a11y_settings);
|
||||
meta_seat_x11_apply_kbd_a11y_settings (seat, &kbd_a11y_settings);
|
||||
}
|
||||
|
||||
@ -1450,6 +1493,7 @@ meta_seat_x11_finalize (GObject *object)
|
||||
|
||||
g_hash_table_unref (seat_x11->devices_by_id);
|
||||
g_hash_table_unref (seat_x11->tools_by_serial);
|
||||
g_hash_table_unref (seat_x11->touch_coords);
|
||||
g_list_free (seat_x11->devices);
|
||||
|
||||
G_OBJECT_CLASS (meta_seat_x11_parent_class)->finalize (object);
|
||||
@ -1548,6 +1592,140 @@ meta_seat_x11_warp_pointer (ClutterSeat *seat,
|
||||
x, y);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
translate_state (XIButtonState *button_state,
|
||||
XIModifierState *modifier_state,
|
||||
XIGroupState *group_state)
|
||||
{
|
||||
uint32_t state = 0;
|
||||
int i;
|
||||
|
||||
if (modifier_state)
|
||||
state |= modifier_state->effective;
|
||||
|
||||
if (button_state)
|
||||
{
|
||||
for (i = 1; i < XIMaskLen (button_state->mask_len); i++)
|
||||
{
|
||||
if (!XIMaskIsSet (button_state->mask, i))
|
||||
continue;
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case 1:
|
||||
state |= CLUTTER_BUTTON1_MASK;
|
||||
break;
|
||||
case 2:
|
||||
state |= CLUTTER_BUTTON2_MASK;
|
||||
break;
|
||||
case 3:
|
||||
state |= CLUTTER_BUTTON3_MASK;
|
||||
break;
|
||||
case 8:
|
||||
state |= CLUTTER_BUTTON4_MASK;
|
||||
break;
|
||||
case 9:
|
||||
state |= CLUTTER_BUTTON5_MASK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (group_state)
|
||||
state |= (group_state->effective) << 13;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_seat_x11_query_state (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
ClutterEventSequence *sequence,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *modifiers)
|
||||
{
|
||||
MetaBackendX11 *backend_x11 = META_BACKEND_X11 (meta_get_backend ());
|
||||
MetaSeatX11 *seat_x11 = META_SEAT_X11 (seat);
|
||||
Window root_ret, child_ret;
|
||||
double root_x, root_y, win_x, win_y;
|
||||
XIButtonState button_state;
|
||||
XIModifierState modifier_state;
|
||||
XIGroupState group_state;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
XIQueryPointer (clutter_x11_get_default_display (),
|
||||
seat_x11->pointer_id,
|
||||
meta_backend_x11_get_xwindow (backend_x11),
|
||||
&root_ret, &child_ret,
|
||||
&root_x, &root_y, &win_x, &win_y,
|
||||
&button_state, &modifier_state, &group_state);
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
return FALSE;
|
||||
|
||||
if (sequence)
|
||||
{
|
||||
MetaTouchInfo *touch_info;
|
||||
|
||||
touch_info = g_hash_table_lookup (seat_x11->touch_coords, sequence);
|
||||
if (!touch_info)
|
||||
return FALSE;
|
||||
|
||||
if (coords)
|
||||
{
|
||||
coords->x = touch_info->x;
|
||||
coords->y = touch_info->y;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (coords)
|
||||
{
|
||||
coords->x = win_x;
|
||||
coords->y = win_y;
|
||||
}
|
||||
}
|
||||
|
||||
if (modifiers)
|
||||
*modifiers = translate_state (&button_state, &modifier_state, &group_state);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_seat_x11_update_touchpoint (MetaSeatX11 *seat,
|
||||
ClutterEventSequence *sequence,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
MetaTouchInfo *touch_info;
|
||||
|
||||
touch_info = g_hash_table_lookup (seat->touch_coords, sequence);
|
||||
if (!touch_info)
|
||||
{
|
||||
touch_info = g_slice_new (MetaTouchInfo);
|
||||
touch_info->sequence = sequence;
|
||||
g_hash_table_insert (seat->touch_coords, sequence, touch_info);
|
||||
}
|
||||
|
||||
touch_info->x = x;
|
||||
touch_info->y = y;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_seat_x11_remove_touchpoint (MetaSeatX11 *seat,
|
||||
ClutterEventSequence *sequence)
|
||||
{
|
||||
g_hash_table_remove (seat->touch_coords, sequence);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_touch_info_free (MetaTouchInfo *touch_info)
|
||||
{
|
||||
g_slice_free (MetaTouchInfo, touch_info);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_seat_x11_class_init (MetaSeatX11Class *klass)
|
||||
{
|
||||
@ -1566,10 +1744,11 @@ meta_seat_x11_class_init (MetaSeatX11Class *klass)
|
||||
seat_class->get_keymap = meta_seat_x11_get_keymap;
|
||||
seat_class->copy_event_data = meta_seat_x11_copy_event_data;
|
||||
seat_class->free_event_data = meta_seat_x11_free_event_data;
|
||||
seat_class->apply_kbd_a11y_settings = meta_seat_x11_apply_kbd_a11y_settings;
|
||||
seat_class->create_virtual_device = meta_seat_x11_create_virtual_device;
|
||||
seat_class->get_supported_virtual_device_types = meta_seat_x11_get_supported_virtual_device_types;
|
||||
seat_class->warp_pointer = meta_seat_x11_warp_pointer;
|
||||
seat_class->handle_event_post = meta_seat_x11_handle_event_post;
|
||||
seat_class->query_state = meta_seat_x11_query_state;
|
||||
|
||||
props[PROP_OPCODE] =
|
||||
g_param_spec_int ("opcode",
|
||||
@ -1607,6 +1786,8 @@ meta_seat_x11_init (MetaSeatX11 *seat)
|
||||
(GDestroyNotify) g_object_unref);
|
||||
seat->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
seat->touch_coords = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) meta_touch_info_free);
|
||||
}
|
||||
|
||||
MetaSeatX11 *
|
||||
@ -1672,8 +1853,7 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(xi_event->evtype == XI_HierarchyChanged ||
|
||||
xi_event->evtype == XI_DeviceChanged ||
|
||||
if (!(xi_event->evtype == XI_DeviceChanged ||
|
||||
xi_event->evtype == XI_PropertyEvent))
|
||||
{
|
||||
stage = get_event_stage (seat, xi_event);
|
||||
@ -1691,9 +1871,8 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
{
|
||||
XIHierarchyEvent *xev = (XIHierarchyEvent *) xi_event;
|
||||
|
||||
translate_hierarchy_event (backend, seat, xev);
|
||||
retval = translate_hierarchy_event (backend, seat, xev, event);
|
||||
}
|
||||
retval = FALSE;
|
||||
break;
|
||||
|
||||
case XI_DeviceChanged:
|
||||
@ -1815,12 +1994,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
device = g_hash_table_lookup (seat->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
|
||||
/* Set the stage for core events coming out of nowhere (see bug #684509) */
|
||||
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER &&
|
||||
clutter_input_device_get_pointer_stage (device) == NULL &&
|
||||
stage != NULL)
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
|
||||
if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
/* We got these events because of the passive button grab */
|
||||
@ -1978,9 +2151,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
break;
|
||||
}
|
||||
|
||||
if (device->stage != NULL)
|
||||
_clutter_input_device_set_stage (source_device, device->stage);
|
||||
|
||||
if (xev->flags & XIPointerEmulated)
|
||||
_clutter_event_set_pointer_emulated (event, TRUE);
|
||||
|
||||
@ -2012,12 +2182,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the stage for core events coming out of nowhere (see bug #684509) */
|
||||
if (clutter_input_device_get_device_mode (device) == CLUTTER_INPUT_MODE_MASTER &&
|
||||
clutter_input_device_get_pointer_stage (device) == NULL &&
|
||||
stage != NULL)
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
|
||||
if (scroll_valuators_changed (source_device,
|
||||
&xev->valuators,
|
||||
&delta_x, &delta_y))
|
||||
@ -2070,9 +2234,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
event->motion.y,
|
||||
&xev->valuators);
|
||||
|
||||
if (device->stage != NULL)
|
||||
_clutter_input_device_set_stage (source_device, device->stage);
|
||||
|
||||
if (xev->flags & XIPointerEmulated)
|
||||
_clutter_event_set_pointer_emulated (event, TRUE);
|
||||
|
||||
@ -2093,8 +2254,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
|
||||
device = g_hash_table_lookup (seat->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
if (!_clutter_input_device_get_stage (device))
|
||||
_clutter_input_device_set_stage (device, stage);
|
||||
}
|
||||
/* Fall through */
|
||||
case XI_TouchEnd:
|
||||
@ -2133,6 +2292,15 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
event->touch.modifier_state |= CLUTTER_BUTTON1_MASK;
|
||||
|
||||
meta_stage_x11_set_user_time (stage_x11, event->touch.time);
|
||||
meta_seat_x11_update_touchpoint (seat,
|
||||
GUINT_TO_POINTER (xev->detail),
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
}
|
||||
else if (xi_event->evtype == XI_TouchEnd)
|
||||
{
|
||||
meta_seat_x11_remove_touchpoint (seat,
|
||||
GUINT_TO_POINTER (xev->detail));
|
||||
}
|
||||
|
||||
event->touch.sequence = GUINT_TO_POINTER (xev->detail);
|
||||
@ -2187,6 +2355,11 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
if (xev->flags & XITouchEmulatingPointer)
|
||||
_clutter_event_set_pointer_emulated (event, TRUE);
|
||||
|
||||
meta_seat_x11_update_touchpoint (seat,
|
||||
event->touch.sequence,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
|
||||
g_debug ("touch update: win:0x%x device:%d '%s' (seq:%d, x:%.2f, y:%.2f, axes:%s)",
|
||||
(unsigned int) stage_x11->xwin,
|
||||
event->touch.device->id,
|
||||
@ -2224,14 +2397,6 @@ meta_seat_x11_translate_event (MetaSeatX11 *seat,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (device->stage == NULL)
|
||||
{
|
||||
g_debug ("Discarding Leave for ButtonRelease "
|
||||
"event off-stage");
|
||||
retval = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
event->crossing.type = event->type = CLUTTER_LEAVE;
|
||||
|
||||
event->crossing.stage = stage;
|
||||
|
@ -78,47 +78,55 @@ static void
|
||||
check_settings_changed (ClutterSeat *seat)
|
||||
{
|
||||
Display *xdisplay = clutter_x11_get_default_display ();
|
||||
ClutterKbdA11ySettings kbd_a11y_settings;
|
||||
ClutterKeyboardA11yFlags what_changed = 0;
|
||||
MetaKbdA11ySettings kbd_a11y_settings;
|
||||
MetaKeyboardA11yFlags what_changed = 0;
|
||||
MetaInputSettings *input_settings;
|
||||
XkbDescRec *desc;
|
||||
|
||||
desc = get_xkb_desc_rec (xdisplay);
|
||||
if (!desc)
|
||||
return;
|
||||
|
||||
clutter_seat_get_kbd_a11y_settings (seat, &kbd_a11y_settings);
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
meta_input_settings_get_kbd_a11y_settings (input_settings,
|
||||
&kbd_a11y_settings);
|
||||
|
||||
if (desc->ctrls->enabled_ctrls & XkbSlowKeysMask &&
|
||||
!(kbd_a11y_settings.controls & CLUTTER_A11Y_SLOW_KEYS_ENABLED))
|
||||
!(kbd_a11y_settings.controls & META_A11Y_SLOW_KEYS_ENABLED))
|
||||
{
|
||||
what_changed |= CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls |= CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
what_changed |= META_A11Y_SLOW_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls |= META_A11Y_SLOW_KEYS_ENABLED;
|
||||
}
|
||||
else if (!(desc->ctrls->enabled_ctrls & XkbSlowKeysMask) &&
|
||||
kbd_a11y_settings.controls & CLUTTER_A11Y_SLOW_KEYS_ENABLED)
|
||||
kbd_a11y_settings.controls & META_A11Y_SLOW_KEYS_ENABLED)
|
||||
{
|
||||
what_changed |= CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls &= ~CLUTTER_A11Y_SLOW_KEYS_ENABLED;
|
||||
what_changed |= META_A11Y_SLOW_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls &= ~META_A11Y_SLOW_KEYS_ENABLED;
|
||||
}
|
||||
|
||||
if (desc->ctrls->enabled_ctrls & XkbStickyKeysMask &&
|
||||
!(kbd_a11y_settings.controls & CLUTTER_A11Y_STICKY_KEYS_ENABLED))
|
||||
!(kbd_a11y_settings.controls & META_A11Y_STICKY_KEYS_ENABLED))
|
||||
{
|
||||
what_changed |= CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls |= CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
what_changed |= META_A11Y_STICKY_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls |= META_A11Y_STICKY_KEYS_ENABLED;
|
||||
}
|
||||
else if (!(desc->ctrls->enabled_ctrls & XkbStickyKeysMask) &&
|
||||
kbd_a11y_settings.controls & CLUTTER_A11Y_STICKY_KEYS_ENABLED)
|
||||
kbd_a11y_settings.controls & META_A11Y_STICKY_KEYS_ENABLED)
|
||||
{
|
||||
what_changed |= CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls &= ~CLUTTER_A11Y_STICKY_KEYS_ENABLED;
|
||||
what_changed |= META_A11Y_STICKY_KEYS_ENABLED;
|
||||
kbd_a11y_settings.controls &= ~META_A11Y_STICKY_KEYS_ENABLED;
|
||||
}
|
||||
|
||||
if (what_changed)
|
||||
{
|
||||
meta_input_settings_notify_kbd_a11y_change (input_settings,
|
||||
kbd_a11y_settings.controls,
|
||||
what_changed);
|
||||
g_signal_emit_by_name (seat,
|
||||
"kbd-a11y-flags-changed",
|
||||
kbd_a11y_settings.controls,
|
||||
what_changed);
|
||||
}
|
||||
|
||||
XkbFreeKeyboard (desc, XkbAllComponentsMask, TRUE);
|
||||
}
|
||||
@ -183,8 +191,8 @@ set_value_mask (gboolean flag,
|
||||
|
||||
static gboolean
|
||||
set_xkb_ctrl (XkbDescRec *desc,
|
||||
ClutterKeyboardA11yFlags settings,
|
||||
ClutterKeyboardA11yFlags flag,
|
||||
MetaKeyboardA11yFlags settings,
|
||||
MetaKeyboardA11yFlags flag,
|
||||
unsigned long mask)
|
||||
{
|
||||
gboolean result = (settings & flag) == flag;
|
||||
@ -195,7 +203,7 @@ set_xkb_ctrl (XkbDescRec *desc,
|
||||
|
||||
void
|
||||
meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *kbd_a11y_settings)
|
||||
MetaKbdA11ySettings *kbd_a11y_settings)
|
||||
{
|
||||
Display *xdisplay = clutter_x11_get_default_display ();
|
||||
XkbDescRec *desc;
|
||||
@ -206,13 +214,13 @@ meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
return;
|
||||
|
||||
/* general */
|
||||
enable_accessX = kbd_a11y_settings->controls & CLUTTER_A11Y_KEYBOARD_ENABLED;
|
||||
enable_accessX = kbd_a11y_settings->controls & META_A11Y_KEYBOARD_ENABLED;
|
||||
|
||||
desc->ctrls->enabled_ctrls = set_value_mask (enable_accessX,
|
||||
desc->ctrls->enabled_ctrls,
|
||||
XkbAccessXKeysMask);
|
||||
|
||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, CLUTTER_A11Y_TIMEOUT_ENABLED,
|
||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls, META_A11Y_TIMEOUT_ENABLED,
|
||||
XkbAccessXTimeoutMask))
|
||||
{
|
||||
desc->ctrls->ax_timeout = kbd_a11y_settings->timeout_delay;
|
||||
@ -226,17 +234,17 @@ meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
}
|
||||
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_FEATURE_STATE_CHANGE_BEEP,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_FEATURE_STATE_CHANGE_BEEP,
|
||||
desc->ctrls->ax_options,
|
||||
XkbAccessXFeedbackMask | XkbAX_FeatureFBMask | XkbAX_SlowWarnFBMask);
|
||||
|
||||
/* bounce keys */
|
||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
||||
CLUTTER_A11Y_BOUNCE_KEYS_ENABLED, XkbBounceKeysMask))
|
||||
META_A11Y_BOUNCE_KEYS_ENABLED, XkbBounceKeysMask))
|
||||
{
|
||||
desc->ctrls->debounce_delay = kbd_a11y_settings->debounce_delay;
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_BOUNCE_KEYS_BEEP_REJECT,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_BOUNCE_KEYS_BEEP_REJECT,
|
||||
desc->ctrls->ax_options,
|
||||
XkbAccessXFeedbackMask | XkbAX_BKRejectFBMask);
|
||||
}
|
||||
@ -248,7 +256,7 @@ meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
desc->ctrls->enabled_ctrls &= ~(XkbMouseKeysMask | XkbMouseKeysAccelMask);
|
||||
}
|
||||
else if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
||||
CLUTTER_A11Y_MOUSE_KEYS_ENABLED, XkbMouseKeysMask | XkbMouseKeysAccelMask))
|
||||
META_A11Y_MOUSE_KEYS_ENABLED, XkbMouseKeysMask | XkbMouseKeysAccelMask))
|
||||
{
|
||||
int mk_max_speed;
|
||||
int mk_accel_time;
|
||||
@ -273,16 +281,16 @@ meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
|
||||
/* slow keys */
|
||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
||||
CLUTTER_A11Y_SLOW_KEYS_ENABLED, XkbSlowKeysMask))
|
||||
META_A11Y_SLOW_KEYS_ENABLED, XkbSlowKeysMask))
|
||||
{
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_SLOW_KEYS_BEEP_PRESS,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_PRESS,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKPressFBMask);
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_SLOW_KEYS_BEEP_ACCEPT,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_ACCEPT,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKAcceptFBMask);
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_SLOW_KEYS_BEEP_REJECT,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_SLOW_KEYS_BEEP_REJECT,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_SKRejectFBMask);
|
||||
desc->ctrls->slow_keys_delay = kbd_a11y_settings->slowkeys_delay;
|
||||
/* anything larger than 500 seems to loose all keyboard input */
|
||||
@ -292,20 +300,20 @@ meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
|
||||
/* sticky keys */
|
||||
if (set_xkb_ctrl (desc, kbd_a11y_settings->controls,
|
||||
CLUTTER_A11Y_STICKY_KEYS_ENABLED, XkbStickyKeysMask))
|
||||
META_A11Y_STICKY_KEYS_ENABLED, XkbStickyKeysMask))
|
||||
{
|
||||
desc->ctrls->ax_options |= XkbAX_LatchToLockMask;
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_STICKY_KEYS_TWO_KEY_OFF,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_STICKY_KEYS_TWO_KEY_OFF,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_TwoKeysMask);
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_STICKY_KEYS_BEEP,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_STICKY_KEYS_BEEP,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_StickyKeysFBMask);
|
||||
}
|
||||
|
||||
/* toggle keys */
|
||||
desc->ctrls->ax_options =
|
||||
set_value_mask (kbd_a11y_settings->controls & CLUTTER_A11Y_TOGGLE_KEYS_ENABLED,
|
||||
set_value_mask (kbd_a11y_settings->controls & META_A11Y_TOGGLE_KEYS_ENABLED,
|
||||
desc->ctrls->ax_options, XkbAccessXFeedbackMask | XkbAX_IndicatorFBMask);
|
||||
|
||||
set_xkb_desc_rec (xdisplay, desc);
|
||||
|
@ -26,11 +26,12 @@
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "clutter/clutter.h"
|
||||
|
||||
void
|
||||
meta_seat_x11_apply_kbd_a11y_settings (ClutterSeat *seat,
|
||||
ClutterKbdA11ySettings *kbd_a11y_settings);
|
||||
MetaKbdA11ySettings *kbd_a11y_settings);
|
||||
|
||||
gboolean
|
||||
meta_seat_x11_a11y_init (ClutterSeat *seat);
|
||||
|
@ -31,6 +31,7 @@
|
||||
typedef struct _MetaBackendX11NestedPrivate
|
||||
{
|
||||
MetaGpu *gpu;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
} MetaBackendX11NestedPrivate;
|
||||
|
||||
static GInitableIface *initable_parent_iface;
|
||||
@ -63,13 +64,25 @@ meta_backend_x11_nested_create_monitor_manager (MetaBackend *backend,
|
||||
}
|
||||
|
||||
static MetaCursorRenderer *
|
||||
meta_backend_x11_nested_create_cursor_renderer (MetaBackend *backend)
|
||||
meta_backend_x11_nested_get_cursor_renderer (MetaBackend *backend,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
return g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED,
|
||||
MetaBackendX11Nested *backend_x11_nested = META_BACKEND_X11_NESTED (backend);
|
||||
MetaBackendX11NestedPrivate *priv =
|
||||
meta_backend_x11_nested_get_instance_private (backend_x11_nested);
|
||||
|
||||
if (!priv->cursor_renderer)
|
||||
{
|
||||
priv->cursor_renderer =
|
||||
g_object_new (META_TYPE_CURSOR_RENDERER_X11_NESTED,
|
||||
"backend", backend,
|
||||
"device", device,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return priv->cursor_renderer;
|
||||
}
|
||||
|
||||
static MetaInputSettings *
|
||||
meta_backend_x11_nested_create_input_settings (MetaBackend *backend)
|
||||
{
|
||||
@ -275,7 +288,7 @@ meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass)
|
||||
backend_class->post_init = meta_backend_x11_nested_post_init;
|
||||
backend_class->create_renderer = meta_backend_x11_nested_create_renderer;
|
||||
backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager;
|
||||
backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer;
|
||||
backend_class->get_cursor_renderer = meta_backend_x11_nested_get_cursor_renderer;
|
||||
backend_class->create_input_settings = meta_backend_x11_nested_create_input_settings;
|
||||
backend_class->update_screen_size = meta_backend_x11_nested_update_screen_size;
|
||||
backend_class->select_stage_events = meta_backend_x11_nested_select_stage_events;
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "clutter/clutter.h"
|
||||
#include "core/keybindings-private.h"
|
||||
#include "core/meta-gesture-tracker-private.h"
|
||||
#include "core/meta-pad-action-mapper.h"
|
||||
#include "core/stack-tracker.h"
|
||||
#include "core/startup-notification-private.h"
|
||||
#include "meta/barrier.h"
|
||||
@ -199,9 +200,6 @@ struct _MetaDisplay
|
||||
|
||||
MetaKeyBindingManager key_binding_manager;
|
||||
|
||||
/* Monitor cache */
|
||||
unsigned int monitor_cache_invalidated : 1;
|
||||
|
||||
/* Opening the display */
|
||||
unsigned int display_opening : 1;
|
||||
|
||||
@ -215,6 +213,7 @@ struct _MetaDisplay
|
||||
ClutterEventSequence *pointer_emulating_sequence;
|
||||
|
||||
ClutterActor *current_pad_osd;
|
||||
MetaPadActionMapper *pad_action_mapper;
|
||||
|
||||
MetaStartupNotification *startup_notification;
|
||||
|
||||
|
@ -45,8 +45,7 @@
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
#include "backends/meta-idle-monitor-dbus.h"
|
||||
#include "backends/meta-input-device-private.h"
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/meta-input-mapper-private.h"
|
||||
#include "backends/meta-stage-private.h"
|
||||
#include "backends/x11/meta-backend-x11.h"
|
||||
#include "backends/x11/meta-event-x11.h"
|
||||
@ -844,6 +843,8 @@ meta_display_open (void)
|
||||
|
||||
meta_prefs_add_listener (prefs_changed_callback, display);
|
||||
|
||||
display->pad_action_mapper = meta_pad_action_mapper_new ();
|
||||
|
||||
/* Get events */
|
||||
meta_display_init_events (display);
|
||||
|
||||
@ -1120,6 +1121,7 @@ meta_display_close (MetaDisplay *display,
|
||||
|
||||
meta_clipboard_manager_shutdown (display);
|
||||
g_clear_object (&display->selection);
|
||||
g_clear_object (&display->pad_action_mapper);
|
||||
|
||||
g_object_unref (display);
|
||||
the_display = NULL;
|
||||
@ -1629,43 +1631,9 @@ meta_cursor_for_grab_op (MetaGrabOp op)
|
||||
return META_CURSOR_DEFAULT;
|
||||
}
|
||||
|
||||
static float
|
||||
find_highest_logical_monitor_scale (MetaBackend *backend,
|
||||
MetaCursorSprite *cursor_sprite)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
graphene_rect_t cursor_rect;
|
||||
GList *logical_monitors;
|
||||
GList *l;
|
||||
float highest_scale = 0.0;
|
||||
|
||||
cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
|
||||
cursor_sprite);
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
graphene_rect_t logical_monitor_rect =
|
||||
meta_rectangle_to_graphene_rect (&logical_monitor->rect);
|
||||
|
||||
if (!graphene_rect_intersection (&cursor_rect,
|
||||
&logical_monitor_rect,
|
||||
NULL))
|
||||
continue;
|
||||
|
||||
highest_scale = MAX (highest_scale, logical_monitor->scale);
|
||||
}
|
||||
|
||||
return highest_scale;
|
||||
}
|
||||
|
||||
static void
|
||||
root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
|
||||
float best_scale,
|
||||
int x,
|
||||
int y,
|
||||
MetaDisplay *display)
|
||||
@ -1675,14 +1643,11 @@ root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
|
||||
|
||||
if (meta_is_stage_views_scaled ())
|
||||
{
|
||||
float scale;
|
||||
|
||||
scale = find_highest_logical_monitor_scale (backend, cursor_sprite);
|
||||
if (scale != 0.0)
|
||||
if (best_scale != 0.0)
|
||||
{
|
||||
float ceiled_scale;
|
||||
|
||||
ceiled_scale = ceilf (scale);
|
||||
ceiled_scale = ceilf (best_scale);
|
||||
meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
|
||||
(int) ceiled_scale);
|
||||
meta_cursor_sprite_set_texture_scale (cursor_sprite,
|
||||
@ -2944,7 +2909,7 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
gboolean edition_mode)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaInputSettings *input_settings;
|
||||
MetaInputMapper *input_mapper;
|
||||
const gchar *layout_path = NULL;
|
||||
ClutterActor *osd;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
@ -2960,13 +2925,13 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
if (display->current_pad_osd)
|
||||
return;
|
||||
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
|
||||
|
||||
if (input_settings)
|
||||
if (input_mapper)
|
||||
{
|
||||
settings = meta_input_settings_get_tablet_settings (input_settings, pad);
|
||||
settings = meta_input_mapper_get_tablet_settings (input_mapper, pad);
|
||||
logical_monitor =
|
||||
meta_input_settings_get_tablet_logical_monitor (input_settings, pad);
|
||||
meta_input_mapper_get_device_logical_monitor (input_mapper, pad);
|
||||
#ifdef HAVE_LIBWACOM
|
||||
wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
|
||||
layout_path = libwacom_get_layout_filename (wacom_device);
|
||||
@ -2999,12 +2964,12 @@ meta_display_get_pad_action_label (MetaDisplay *display,
|
||||
MetaPadActionType action_type,
|
||||
guint action_number)
|
||||
{
|
||||
MetaInputSettings *settings;
|
||||
gchar *label;
|
||||
|
||||
/* First, lookup the action, as imposed by settings */
|
||||
settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
label = meta_input_settings_get_pad_action_label (settings, pad, action_type, action_number);
|
||||
label = meta_pad_action_mapper_get_action_label (display->pad_action_mapper,
|
||||
pad, action_type,
|
||||
action_number);
|
||||
if (label)
|
||||
return label;
|
||||
|
||||
@ -3050,15 +3015,15 @@ static gint
|
||||
lookup_tablet_monitor (MetaDisplay *display,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
MetaInputMapper *input_mapper;
|
||||
MetaLogicalMonitor *monitor;
|
||||
gint monitor_idx = -1;
|
||||
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
if (!input_settings)
|
||||
input_mapper = meta_backend_get_input_mapper (meta_get_backend ());
|
||||
if (!input_mapper)
|
||||
return -1;
|
||||
|
||||
monitor = meta_input_settings_get_tablet_logical_monitor (input_settings, device);
|
||||
monitor = meta_input_mapper_get_device_logical_monitor (input_mapper, device);
|
||||
|
||||
if (monitor)
|
||||
{
|
||||
@ -3144,9 +3109,6 @@ static void
|
||||
on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
|
||||
MetaDisplay *display)
|
||||
{
|
||||
MetaBackend *backend;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
|
||||
meta_workspace_manager_reload_work_areas (display->workspace_manager);
|
||||
|
||||
/* Fix up monitor for all windows on this display */
|
||||
@ -3159,10 +3121,6 @@ on_monitors_changed_internal (MetaMonitorManager *monitor_manager,
|
||||
meta_display_resize_func, 0);
|
||||
|
||||
meta_display_queue_check_fullscreen (display);
|
||||
|
||||
backend = meta_get_backend ();
|
||||
cursor_renderer = meta_backend_get_cursor_renderer (backend);
|
||||
meta_cursor_renderer_force_update (cursor_renderer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -3750,18 +3708,18 @@ meta_display_get_pointer_window (MetaDisplay *display,
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
MetaWindow *window;
|
||||
int x, y;
|
||||
graphene_point_t point;
|
||||
|
||||
if (not_this_one)
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing mouse window excluding %s\n", not_this_one->desc);
|
||||
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &x, &y, NULL);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
|
||||
|
||||
window = meta_stack_get_default_focus_window_at_point (display->stack,
|
||||
workspace_manager->active_workspace,
|
||||
not_this_one,
|
||||
x, y);
|
||||
point.x, point.y);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
@ -263,8 +263,7 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
handle_pad_event = !display->current_pad_osd || is_mode_switch;
|
||||
|
||||
if (handle_pad_event &&
|
||||
meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend),
|
||||
event))
|
||||
meta_pad_action_mapper_handle_event (display->pad_action_mapper, event))
|
||||
{
|
||||
bypass_wayland = bypass_clutter = TRUE;
|
||||
goto out;
|
||||
@ -279,25 +278,22 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (meta_is_wayland_compositor () && event->type == CLUTTER_MOTION)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
device = clutter_event_get_device (event);
|
||||
cursor_renderer = meta_backend_get_cursor_renderer_for_device (backend,
|
||||
device);
|
||||
if (cursor_renderer)
|
||||
meta_cursor_renderer_update_position (cursor_renderer);
|
||||
|
||||
if (meta_wayland_tablet_manager_consumes_event (compositor->tablet_manager, event))
|
||||
{
|
||||
meta_wayland_tablet_manager_update_cursor_position (compositor->tablet_manager, event);
|
||||
}
|
||||
else
|
||||
if (device == clutter_seat_get_pointer (clutter_input_device_get_seat (device)))
|
||||
{
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
|
||||
meta_cursor_tracker_update_position (cursor_tracker,
|
||||
event->motion.x,
|
||||
event->motion.y);
|
||||
meta_cursor_tracker_update_position (cursor_tracker);
|
||||
}
|
||||
|
||||
display->monitor_cache_invalidated = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
852
src/core/meta-pad-action-mapper.c
Normal file
852
src/core/meta-pad-action-mapper.c
Normal file
@ -0,0 +1,852 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <gsettings-desktop-schemas/gdesktop-enums.h>
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
#include <libwacom/libwacom.h>
|
||||
#endif
|
||||
|
||||
#include "meta-pad-action-mapper.h"
|
||||
#include "backends/meta-input-device-private.h"
|
||||
#include "backends/meta-logical-monitor.h"
|
||||
#include "backends/meta-monitor.h"
|
||||
#include "core/display-private.h"
|
||||
|
||||
typedef struct _PadMappingInfo PadMappingInfo;
|
||||
|
||||
struct _PadMappingInfo
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
guint *group_modes;
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_PAD_DIRECTION_NONE = -1,
|
||||
META_PAD_DIRECTION_UP = 0,
|
||||
META_PAD_DIRECTION_DOWN,
|
||||
META_PAD_DIRECTION_CW,
|
||||
META_PAD_DIRECTION_CCW,
|
||||
} MetaPadDirection;
|
||||
|
||||
struct _MetaPadActionMapper
|
||||
{
|
||||
GObject parent_class;
|
||||
|
||||
GHashTable *pads;
|
||||
ClutterSeat *seat;
|
||||
ClutterVirtualInputDevice *virtual_pad_keyboard;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
gulong monitors_changed_id;
|
||||
|
||||
/* Pad ring/strip emission */
|
||||
struct {
|
||||
ClutterInputDevice *pad;
|
||||
MetaPadActionType action;
|
||||
guint number;
|
||||
gdouble value;
|
||||
} last_pad_action_info;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaPadActionMapper, meta_pad_action_mapper, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_finalize (GObject *object)
|
||||
{
|
||||
MetaPadActionMapper *mapper = META_PAD_ACTION_MAPPER (object);
|
||||
|
||||
g_hash_table_unref (mapper->pads);
|
||||
g_signal_handler_disconnect (mapper->monitor_manager,
|
||||
mapper->monitors_changed_id);
|
||||
g_object_unref (mapper->monitor_manager);
|
||||
g_clear_object (&mapper->virtual_pad_keyboard);
|
||||
|
||||
G_OBJECT_CLASS (meta_pad_action_mapper_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_class_init (MetaPadActionMapperClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_pad_action_mapper_finalize;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_device_settings (ClutterInputDevice *device)
|
||||
{
|
||||
const gchar *vendor, *product;
|
||||
GSettings *settings;
|
||||
gchar *path;
|
||||
|
||||
vendor = clutter_input_device_get_vendor_id (device);
|
||||
product = clutter_input_device_get_product_id (device);
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/tablets/%s:%s/",
|
||||
vendor, product);
|
||||
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet",
|
||||
path);
|
||||
g_free (path);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static PadMappingInfo *
|
||||
pad_mapping_info_new (ClutterInputDevice *pad)
|
||||
{
|
||||
PadMappingInfo *info;
|
||||
|
||||
info = g_new0 (PadMappingInfo, 1);
|
||||
info->device = pad;
|
||||
info->settings = lookup_device_settings (pad);
|
||||
info->group_modes =
|
||||
g_new0 (guint, clutter_input_device_get_n_mode_groups (pad));
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_mapping_info_free (PadMappingInfo *info)
|
||||
{
|
||||
g_object_unref (info->settings);
|
||||
g_free (info->group_modes);
|
||||
g_free (info);
|
||||
}
|
||||
|
||||
static void
|
||||
device_added (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
MetaPadActionMapper *mapper)
|
||||
{
|
||||
PadMappingInfo *info;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
info = pad_mapping_info_new (device);
|
||||
g_hash_table_insert (mapper->pads, device, info);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
device_removed (ClutterSeat *seat,
|
||||
ClutterInputDevice *device,
|
||||
MetaPadActionMapper *mapper)
|
||||
{
|
||||
g_hash_table_remove (mapper->pads, device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_init (MetaPadActionMapper *mapper)
|
||||
{
|
||||
mapper->pads = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) pad_mapping_info_free);
|
||||
|
||||
mapper->seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
g_signal_connect (mapper->seat, "device-added",
|
||||
G_CALLBACK (device_added), mapper);
|
||||
g_signal_connect (mapper->seat, "device-removed",
|
||||
G_CALLBACK (device_removed), mapper);
|
||||
}
|
||||
|
||||
MetaPadActionMapper *
|
||||
meta_pad_action_mapper_new (void)
|
||||
{
|
||||
return g_object_new (META_TYPE_PAD_ACTION_MAPPER, NULL);
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_pad_action_settings (ClutterInputDevice *device,
|
||||
MetaPadActionType action,
|
||||
guint number,
|
||||
MetaPadDirection direction,
|
||||
gint mode)
|
||||
{
|
||||
const gchar *vendor, *product, *action_type, *detail_type = NULL;
|
||||
GSettings *settings;
|
||||
GString *path;
|
||||
gchar action_label;
|
||||
|
||||
vendor = clutter_input_device_get_vendor_id (device);
|
||||
product = clutter_input_device_get_product_id (device);
|
||||
|
||||
action_label = 'A' + number;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case META_PAD_ACTION_BUTTON:
|
||||
action_type = "button";
|
||||
break;
|
||||
case META_PAD_ACTION_RING:
|
||||
g_assert (direction == META_PAD_DIRECTION_CW ||
|
||||
direction == META_PAD_DIRECTION_CCW);
|
||||
action_type = "ring";
|
||||
detail_type = (direction == META_PAD_DIRECTION_CW) ? "cw" : "ccw";
|
||||
break;
|
||||
case META_PAD_ACTION_STRIP:
|
||||
g_assert (direction == META_PAD_DIRECTION_UP ||
|
||||
direction == META_PAD_DIRECTION_DOWN);
|
||||
action_type = "strip";
|
||||
detail_type = (direction == META_PAD_DIRECTION_UP) ? "up" : "down";
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = g_string_new (NULL);
|
||||
g_string_append_printf (path, "/org/gnome/desktop/peripherals/tablets/%s:%s/%s%c",
|
||||
vendor, product, action_type, action_label);
|
||||
|
||||
if (detail_type)
|
||||
g_string_append_printf (path, "-%s", detail_type);
|
||||
|
||||
if (mode >= 0)
|
||||
g_string_append_printf (path, "-mode-%d", mode);
|
||||
|
||||
g_string_append_c (path, '/');
|
||||
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
|
||||
path->str);
|
||||
g_string_free (path, TRUE);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static GDesktopPadButtonAction
|
||||
meta_pad_action_mapper_get_button_action (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
GSettings *settings;
|
||||
|
||||
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
|
||||
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
||||
button, META_PAD_DIRECTION_NONE, -1);
|
||||
action = g_settings_get_enum (settings, "action");
|
||||
g_object_unref (settings);
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cycle_logical_monitors (MetaPadActionMapper *mapper,
|
||||
MetaLogicalMonitor *current_logical_monitor,
|
||||
MetaLogicalMonitor **next_logical_monitor)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager = mapper->monitor_manager;
|
||||
GList *logical_monitors;
|
||||
|
||||
/* We cycle between:
|
||||
* - the span of all monitors (current_output = NULL)
|
||||
* - each monitor individually.
|
||||
*/
|
||||
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
|
||||
if (!current_logical_monitor)
|
||||
{
|
||||
*next_logical_monitor = logical_monitors->data;
|
||||
}
|
||||
else
|
||||
{
|
||||
GList *l;
|
||||
|
||||
l = g_list_find (logical_monitors, current_logical_monitor);
|
||||
if (l->next)
|
||||
*next_logical_monitor = l->next->data;
|
||||
else
|
||||
*next_logical_monitor = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static MetaMonitor *
|
||||
logical_monitor_find_monitor (MetaLogicalMonitor *logical_monitor,
|
||||
const char *vendor,
|
||||
const char *product,
|
||||
const char *serial)
|
||||
{
|
||||
GList *monitors;
|
||||
GList *l;
|
||||
|
||||
monitors = meta_logical_monitor_get_monitors (logical_monitor);
|
||||
for (l = monitors; l; l = l->next)
|
||||
{
|
||||
MetaMonitor *monitor = l->data;
|
||||
|
||||
if (g_strcmp0 (meta_monitor_get_vendor (monitor), vendor) == 0 &&
|
||||
g_strcmp0 (meta_monitor_get_product (monitor), product) == 0 &&
|
||||
g_strcmp0 (meta_monitor_get_serial (monitor), serial) == 0)
|
||||
return monitor;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_find_monitor (MetaPadActionMapper *mapper,
|
||||
GSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaMonitor **out_monitor,
|
||||
MetaLogicalMonitor **out_logical_monitor)
|
||||
{
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaMonitor *monitor;
|
||||
guint n_values;
|
||||
GList *logical_monitors;
|
||||
GList *l;
|
||||
gchar **edid;
|
||||
|
||||
edid = g_settings_get_strv (settings, "output");
|
||||
n_values = g_strv_length (edid);
|
||||
|
||||
if (n_values != 3)
|
||||
{
|
||||
g_warning ("EDID configuration for device '%s' "
|
||||
"is incorrect, must have 3 values",
|
||||
clutter_input_device_get_device_name (device));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!*edid[0] && !*edid[1] && !*edid[2])
|
||||
goto out;
|
||||
|
||||
monitor_manager = mapper->monitor_manager;
|
||||
logical_monitors =
|
||||
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||
for (l = logical_monitors; l; l = l->next)
|
||||
{
|
||||
MetaLogicalMonitor *logical_monitor = l->data;
|
||||
|
||||
monitor = logical_monitor_find_monitor (logical_monitor,
|
||||
edid[0], edid[1], edid[2]);
|
||||
if (monitor)
|
||||
{
|
||||
if (out_monitor)
|
||||
*out_monitor = monitor;
|
||||
if (out_logical_monitor)
|
||||
*out_logical_monitor = logical_monitor;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
g_strfreev (edid);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_cycle_tablet_output (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
PadMappingInfo *info;
|
||||
MetaLogicalMonitor *logical_monitor = NULL;
|
||||
const gchar *edid[4] = { 0 }, *pretty_name = NULL;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
|
||||
g_return_if_fail (META_IS_PAD_ACTION_MAPPER (mapper));
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE);
|
||||
|
||||
info = g_hash_table_lookup (mapper->pads, device);
|
||||
g_return_if_fail (info != NULL);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
|
||||
|
||||
if (wacom_device)
|
||||
{
|
||||
/* Output rotation only makes sense on external tablets */
|
||||
if (libwacom_get_integration_flags (wacom_device) != WACOM_DEVICE_INTEGRATED_NONE)
|
||||
return;
|
||||
|
||||
pretty_name = libwacom_get_name (wacom_device);
|
||||
}
|
||||
#endif
|
||||
|
||||
meta_pad_action_mapper_find_monitor (mapper, info->settings, device,
|
||||
NULL, &logical_monitor);
|
||||
|
||||
if (!cycle_logical_monitors (mapper,
|
||||
logical_monitor,
|
||||
&logical_monitor))
|
||||
return;
|
||||
|
||||
if (logical_monitor)
|
||||
{
|
||||
MetaMonitor *monitor;
|
||||
|
||||
/* Pick an arbitrary monitor in the logical monitor to represent it. */
|
||||
monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
||||
edid[0] = meta_monitor_get_vendor (monitor);
|
||||
edid[1] = meta_monitor_get_product (monitor);
|
||||
edid[2] = meta_monitor_get_serial (monitor);
|
||||
}
|
||||
else
|
||||
{
|
||||
edid[0] = "";
|
||||
edid[1] = "";
|
||||
edid[2] = "";
|
||||
}
|
||||
|
||||
g_settings_set_strv (info->settings, "output", edid);
|
||||
meta_display_show_tablet_mapping_notification (meta_get_display (),
|
||||
device, pretty_name);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), FALSE);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
||||
CLUTTER_PAD_DEVICE, FALSE);
|
||||
|
||||
return (meta_pad_action_mapper_get_button_action (mapper, pad, button) !=
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
}
|
||||
|
||||
static void
|
||||
emulate_modifiers (ClutterVirtualInputDevice *device,
|
||||
ClutterModifierType mods,
|
||||
ClutterKeyState state)
|
||||
{
|
||||
guint i;
|
||||
struct {
|
||||
ClutterModifierType mod;
|
||||
guint keyval;
|
||||
} mod_map[] = {
|
||||
{ CLUTTER_SHIFT_MASK, CLUTTER_KEY_Shift_L },
|
||||
{ CLUTTER_CONTROL_MASK, CLUTTER_KEY_Control_L },
|
||||
{ CLUTTER_MOD1_MASK, CLUTTER_KEY_Meta_L }
|
||||
};
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (mod_map); i++)
|
||||
{
|
||||
if ((mods & mod_map[i].mod) == 0)
|
||||
continue;
|
||||
|
||||
clutter_virtual_input_device_notify_keyval (device,
|
||||
clutter_get_current_event_time (),
|
||||
mod_map[i].keyval, state);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pad_action_mapper_emulate_keybinding (MetaPadActionMapper *mapper,
|
||||
const gchar *accel,
|
||||
gboolean is_press)
|
||||
{
|
||||
ClutterKeyState state;
|
||||
guint key, mods;
|
||||
|
||||
if (!accel || !*accel)
|
||||
return;
|
||||
|
||||
/* FIXME: This is appalling */
|
||||
gtk_accelerator_parse (accel, &key, &mods);
|
||||
|
||||
if (!mapper->virtual_pad_keyboard)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
ClutterSeat *seat;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
seat = clutter_backend_get_default_seat (backend);
|
||||
|
||||
mapper->virtual_pad_keyboard =
|
||||
clutter_seat_create_virtual_device (seat,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
}
|
||||
|
||||
state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
|
||||
|
||||
if (is_press)
|
||||
emulate_modifiers (mapper->virtual_pad_keyboard, mods, state);
|
||||
|
||||
clutter_virtual_input_device_notify_keyval (mapper->virtual_pad_keyboard,
|
||||
clutter_get_current_event_time (),
|
||||
key, state);
|
||||
if (!is_press)
|
||||
emulate_modifiers (mapper->virtual_pad_keyboard, mods, state);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_pad_action_mapper_handle_button (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
const ClutterPadButtonEvent *event)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
gint button, group, mode;
|
||||
gboolean is_press;
|
||||
GSettings *settings;
|
||||
gchar *accel;
|
||||
|
||||
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), FALSE);
|
||||
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE, FALSE);
|
||||
|
||||
button = event->button;
|
||||
mode = event->mode;
|
||||
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
||||
is_press = event->type == CLUTTER_PAD_BUTTON_PRESS;
|
||||
|
||||
if (is_press && group >= 0)
|
||||
{
|
||||
guint n_modes = clutter_input_device_get_group_n_modes (pad, group);
|
||||
const gchar *pretty_name = NULL;
|
||||
PadMappingInfo *info;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
|
||||
info = g_hash_table_lookup (mapper->pads, pad);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
wacom_device = meta_input_device_get_wacom_device (META_INPUT_DEVICE (pad));
|
||||
|
||||
if (wacom_device)
|
||||
pretty_name = libwacom_get_name (wacom_device);
|
||||
#endif
|
||||
meta_display_notify_pad_group_switch (meta_get_display (), pad,
|
||||
pretty_name, group, mode, n_modes);
|
||||
info->group_modes[group] = mode;
|
||||
}
|
||||
|
||||
action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
||||
if (is_press)
|
||||
meta_pad_action_mapper_cycle_tablet_output (mapper, pad);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
||||
if (is_press)
|
||||
meta_display_request_pad_osd (meta_get_display (), pad, FALSE);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
||||
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
||||
button, META_PAD_DIRECTION_NONE, -1);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
meta_pad_action_mapper_emulate_keybinding (mapper, accel, is_press);
|
||||
g_object_unref (settings);
|
||||
g_free (accel);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_pad_action_mapper_handle_action (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action,
|
||||
guint number,
|
||||
MetaPadDirection direction,
|
||||
guint mode)
|
||||
{
|
||||
GSettings *settings;
|
||||
gboolean handled = FALSE;
|
||||
gchar *accel;
|
||||
|
||||
settings = lookup_pad_action_settings (pad, action, number, direction, mode);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
|
||||
if (accel && *accel)
|
||||
{
|
||||
meta_pad_action_mapper_emulate_keybinding (mapper, accel, TRUE);
|
||||
meta_pad_action_mapper_emulate_keybinding (mapper, accel, FALSE);
|
||||
handled = TRUE;
|
||||
}
|
||||
|
||||
g_object_unref (settings);
|
||||
g_free (accel);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_pad_action_mapper_get_action_direction (MetaPadActionMapper *mapper,
|
||||
const ClutterEvent *event,
|
||||
MetaPadDirection *direction)
|
||||
{
|
||||
ClutterInputDevice *pad = clutter_event_get_device (event);
|
||||
MetaPadActionType pad_action;
|
||||
gboolean has_direction = FALSE;
|
||||
MetaPadDirection inc_dir, dec_dir;
|
||||
guint number;
|
||||
gdouble value;
|
||||
|
||||
*direction = META_PAD_DIRECTION_NONE;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_RING:
|
||||
pad_action = META_PAD_ACTION_RING;
|
||||
number = event->pad_ring.ring_number;
|
||||
value = event->pad_ring.angle;
|
||||
inc_dir = META_PAD_DIRECTION_CW;
|
||||
dec_dir = META_PAD_DIRECTION_CCW;
|
||||
break;
|
||||
case CLUTTER_PAD_STRIP:
|
||||
pad_action = META_PAD_ACTION_STRIP;
|
||||
number = event->pad_strip.strip_number;
|
||||
value = event->pad_strip.value;
|
||||
inc_dir = META_PAD_DIRECTION_DOWN;
|
||||
dec_dir = META_PAD_DIRECTION_UP;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (mapper->last_pad_action_info.pad == pad &&
|
||||
mapper->last_pad_action_info.action == pad_action &&
|
||||
mapper->last_pad_action_info.number == number &&
|
||||
value >= 0 && mapper->last_pad_action_info.value >= 0)
|
||||
{
|
||||
*direction = (value - mapper->last_pad_action_info.value) > 0 ?
|
||||
inc_dir : dec_dir;
|
||||
has_direction = TRUE;
|
||||
}
|
||||
|
||||
mapper->last_pad_action_info.pad = pad;
|
||||
mapper->last_pad_action_info.action = pad_action;
|
||||
mapper->last_pad_action_info.number = number;
|
||||
mapper->last_pad_action_info.value = value;
|
||||
return has_direction;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
ClutterInputDevice *pad;
|
||||
MetaPadDirection direction = META_PAD_DIRECTION_NONE;
|
||||
|
||||
pad = clutter_event_get_source_device ((ClutterEvent *) event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
return meta_pad_action_mapper_handle_button (mapper, pad,
|
||||
&event->pad_button);
|
||||
case CLUTTER_PAD_RING:
|
||||
if (!meta_pad_action_mapper_get_action_direction (mapper,
|
||||
event, &direction))
|
||||
return FALSE;
|
||||
return meta_pad_action_mapper_handle_action (mapper, pad,
|
||||
META_PAD_ACTION_RING,
|
||||
event->pad_ring.ring_number,
|
||||
direction,
|
||||
event->pad_ring.mode);
|
||||
case CLUTTER_PAD_STRIP:
|
||||
if (!meta_pad_action_mapper_get_action_direction (mapper,
|
||||
event, &direction))
|
||||
return FALSE;
|
||||
return meta_pad_action_mapper_handle_action (mapper, pad,
|
||||
META_PAD_ACTION_STRIP,
|
||||
event->pad_strip.strip_number,
|
||||
direction,
|
||||
event->pad_strip.mode);
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gchar *
|
||||
compose_directional_action_label (GSettings *direction1,
|
||||
GSettings *direction2)
|
||||
{
|
||||
gchar *accel1, *accel2, *str = NULL;
|
||||
|
||||
accel1 = g_settings_get_string (direction1, "keybinding");
|
||||
accel2 = g_settings_get_string (direction2, "keybinding");
|
||||
|
||||
if (accel1 && *accel1 && accel2 && *accel2)
|
||||
str = g_strdup_printf ("%s / %s", accel1, accel2);
|
||||
|
||||
g_free (accel1);
|
||||
g_free (accel2);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
meta_pad_action_mapper_get_ring_label (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint number,
|
||||
guint mode)
|
||||
{
|
||||
GSettings *settings1, *settings2;
|
||||
gchar *label;
|
||||
|
||||
/* We only allow keybinding actions with those */
|
||||
settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
|
||||
META_PAD_DIRECTION_CW, mode);
|
||||
settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_RING, number,
|
||||
META_PAD_DIRECTION_CCW, mode);
|
||||
label = compose_directional_action_label (settings1, settings2);
|
||||
g_object_unref (settings1);
|
||||
g_object_unref (settings2);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
meta_pad_action_mapper_get_strip_label (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint number,
|
||||
guint mode)
|
||||
{
|
||||
GSettings *settings1, *settings2;
|
||||
gchar *label;
|
||||
|
||||
/* We only allow keybinding actions with those */
|
||||
settings1 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
|
||||
META_PAD_DIRECTION_UP, mode);
|
||||
settings2 = lookup_pad_action_settings (pad, META_PAD_ACTION_STRIP, number,
|
||||
META_PAD_DIRECTION_DOWN, mode);
|
||||
label = compose_directional_action_label (settings1, settings2);
|
||||
g_object_unref (settings1);
|
||||
g_object_unref (settings2);
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
meta_pad_action_mapper_get_button_label (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
gint group;
|
||||
|
||||
g_return_val_if_fail (META_IS_PAD_ACTION_MAPPER (mapper), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad), NULL);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (pad) ==
|
||||
CLUTTER_PAD_DEVICE, NULL);
|
||||
|
||||
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
||||
|
||||
if (group >= 0)
|
||||
{
|
||||
/* TRANSLATORS: This string refers to a button that switches between
|
||||
* different modes.
|
||||
*/
|
||||
return g_strdup_printf (_("Mode Switch (Group %d)"), group);
|
||||
}
|
||||
|
||||
action = meta_pad_action_mapper_get_button_action (mapper, pad, button);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
||||
{
|
||||
GSettings *settings;
|
||||
gchar *accel;
|
||||
|
||||
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
||||
button, META_PAD_DIRECTION_NONE, -1);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
g_object_unref (settings);
|
||||
|
||||
return accel;
|
||||
}
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR:
|
||||
/* TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
* mapping through the available outputs.
|
||||
*/
|
||||
return g_strdup (_("Switch monitor"));
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_HELP:
|
||||
return g_strdup (_("Show on-screen help"));
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
get_current_pad_mode (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint number)
|
||||
{
|
||||
PadMappingInfo *info;
|
||||
guint group = 0, n_groups;
|
||||
|
||||
info = g_hash_table_lookup (mapper->pads, pad);
|
||||
n_groups = clutter_input_device_get_n_mode_groups (pad);
|
||||
|
||||
if (!info->group_modes || n_groups == 0)
|
||||
return 0;
|
||||
|
||||
if (action_type == META_PAD_ACTION_RING ||
|
||||
action_type == META_PAD_ACTION_STRIP)
|
||||
{
|
||||
/* Assume features are evenly distributed in groups */
|
||||
group = number % n_groups;
|
||||
}
|
||||
|
||||
return info->group_modes[group];
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint number)
|
||||
{
|
||||
guint mode;
|
||||
|
||||
switch (action_type)
|
||||
{
|
||||
case META_PAD_ACTION_BUTTON:
|
||||
return meta_pad_action_mapper_get_button_label (mapper, pad, number);
|
||||
case META_PAD_ACTION_RING:
|
||||
mode = get_current_pad_mode (mapper, pad, action_type, number);
|
||||
return meta_pad_action_mapper_get_ring_label (mapper, pad, number, mode);
|
||||
case META_PAD_ACTION_STRIP:
|
||||
mode = get_current_pad_mode (mapper, pad, action_type, number);
|
||||
return meta_pad_action_mapper_get_strip_label (mapper, pad, number, mode);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
46
src/core/meta-pad-action-mapper.h
Normal file
46
src/core/meta-pad-action-mapper.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_PAD_ACTION_MAPPER_H
|
||||
#define META_PAD_ACTION_MAPPER_H
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#include "meta/display.h"
|
||||
|
||||
#define META_TYPE_PAD_ACTION_MAPPER (meta_pad_action_mapper_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaPadActionMapper, meta_pad_action_mapper,
|
||||
META, PAD_ACTION_MAPPER, GObject)
|
||||
|
||||
MetaPadActionMapper * meta_pad_action_mapper_new (void);
|
||||
|
||||
gboolean meta_pad_action_mapper_is_button_grabbed (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
gboolean meta_pad_action_mapper_handle_event (MetaPadActionMapper *mapper,
|
||||
const ClutterEvent *event);
|
||||
gchar * meta_pad_action_mapper_get_action_label (MetaPadActionMapper *mapper,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action,
|
||||
guint number);
|
||||
|
||||
#endif /* META_PAD_ACTION_MAPPER_H */
|
@ -8183,19 +8183,19 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
||||
MetaDisplay *display = window->display;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
int root_x, root_y;
|
||||
graphene_point_t point;
|
||||
guint32 timestamp;
|
||||
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
goto out;
|
||||
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &root_x, &root_y, NULL);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
|
||||
|
||||
if (root_x != focus_data->pointer_x ||
|
||||
root_y != focus_data->pointer_y)
|
||||
if ((int) point.x != focus_data->pointer_x ||
|
||||
(int) point.y != focus_data->pointer_y)
|
||||
{
|
||||
focus_data->pointer_x = root_x;
|
||||
focus_data->pointer_y = root_y;
|
||||
focus_data->pointer_x = point.x;
|
||||
focus_data->pointer_y = point.y;
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -233,6 +233,8 @@ mutter_sources = [
|
||||
'backends/meta-settings-private.h',
|
||||
'backends/meta-stage.c',
|
||||
'backends/meta-stage-private.h',
|
||||
'backends/meta-viewport-info.c',
|
||||
'backends/meta-viewport-info.h',
|
||||
'backends/x11/cm/meta-backend-x11-cm.c',
|
||||
'backends/x11/cm/meta-backend-x11-cm.h',
|
||||
'backends/x11/cm/meta-cursor-sprite-xfixes.c',
|
||||
@ -374,6 +376,7 @@ mutter_sources = [
|
||||
'core/meta-inhibit-shortcuts-dialog-default.c',
|
||||
'core/meta-inhibit-shortcuts-dialog-default-private.h',
|
||||
'core/meta-launch-context.c',
|
||||
'core/meta-pad-action-mapper.c',
|
||||
'core/meta-selection.c',
|
||||
'core/meta-selection-source.c',
|
||||
'core/meta-selection-source-memory.c',
|
||||
@ -672,6 +675,8 @@ if have_native_backend
|
||||
'backends/native/meta-kms-crtc-private.h',
|
||||
'backends/native/meta-kms-crtc.c',
|
||||
'backends/native/meta-kms-crtc.h',
|
||||
'backends/native/meta-kms-cursor-renderer.c',
|
||||
'backends/native/meta-kms-cursor-renderer.h',
|
||||
'backends/native/meta-kms-device-private.h',
|
||||
'backends/native/meta-kms-device.c',
|
||||
'backends/native/meta-kms-device.h',
|
||||
@ -695,9 +700,13 @@ if have_native_backend
|
||||
'backends/native/meta-kms-utils.h',
|
||||
'backends/native/meta-kms.c',
|
||||
'backends/native/meta-kms.h',
|
||||
'backends/native/meta-pointer-constraint-native.c',
|
||||
'backends/native/meta-pointer-constraint-native.h',
|
||||
'backends/native/meta-renderer-native-gles3.c',
|
||||
'backends/native/meta-renderer-native-gles3.h',
|
||||
'backends/native/meta-renderer-native.h',
|
||||
'backends/native/meta-seat-impl.c',
|
||||
'backends/native/meta-seat-impl.h',
|
||||
'backends/native/meta-seat-native.c',
|
||||
'backends/native/meta-seat-native.h',
|
||||
'backends/native/meta-stage-native.c',
|
||||
@ -749,14 +758,6 @@ dbus_idle_monitor_built_sources = gnome.gdbus_codegen('meta-dbus-idle-monitor',
|
||||
)
|
||||
mutter_built_sources += dbus_idle_monitor_built_sources
|
||||
|
||||
mutter_marshal = gnome.genmarshal('meta-marshal',
|
||||
sources: ['meta-marshal.list'],
|
||||
prefix: 'meta_marshal',
|
||||
internal: true,
|
||||
valist_marshallers: true,
|
||||
)
|
||||
mutter_built_sources += mutter_marshal
|
||||
|
||||
if have_profiler
|
||||
mutter_sources += [
|
||||
'backends/meta-profiler.c',
|
||||
|
@ -1 +0,0 @@
|
||||
VOID:FLOAT,FLOAT
|
@ -50,8 +50,7 @@ CoglTexture *meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker);
|
||||
|
||||
META_EXPORT
|
||||
void meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
|
||||
int *x,
|
||||
int *y,
|
||||
graphene_point_t *coords,
|
||||
ClutterModifierType *mods);
|
||||
|
||||
META_EXPORT
|
||||
|
@ -173,8 +173,6 @@ seat_device_added_cb (ClutterSeat *seat,
|
||||
g_print ("*** enabling device '%s' ***\n",
|
||||
clutter_input_device_get_device_name (device));
|
||||
|
||||
clutter_input_device_set_enabled (device, TRUE);
|
||||
|
||||
hand = clutter_test_utils_create_texture_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
@ -272,8 +270,6 @@ test_devices_main (int argc, char **argv)
|
||||
g_print ("*** enabling device '%s' ***\n",
|
||||
clutter_input_device_get_device_name (device));
|
||||
|
||||
clutter_input_device_set_enabled (device, TRUE);
|
||||
|
||||
hand = clutter_test_utils_create_texture_from_file (TESTS_DATADIR
|
||||
G_DIR_SEPARATOR_S
|
||||
"redhand.png",
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <clutter/clutter-mutter.h>
|
||||
|
||||
#include "tests/clutter-test-utils.h"
|
||||
|
||||
@ -109,7 +110,6 @@ static gboolean perf_fake_mouse_cb (gpointer stage)
|
||||
event2->crossing.related = NULL;
|
||||
|
||||
clutter_event_set_device (event2, device);
|
||||
clutter_input_device_update_from_event (device, event2, TRUE);
|
||||
|
||||
clutter_event_put (event2);
|
||||
clutter_event_free (event2);
|
||||
|
@ -41,667 +41,70 @@
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "compositor/meta-surface-actor-wayland.h"
|
||||
#include "core/meta-border.h"
|
||||
#include "wayland/meta-wayland-pointer-constraints.h"
|
||||
#include "wayland/meta-wayland-pointer.h"
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
|
||||
struct _MetaPointerConfinementWayland
|
||||
{
|
||||
MetaPointerConstraint parent;
|
||||
typedef struct _MetaPointerConfinementWaylandPrivate MetaPointerConfinementWaylandPrivate;
|
||||
|
||||
struct _MetaPointerConfinementWaylandPrivate
|
||||
{
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
gboolean enabled;
|
||||
};
|
||||
|
||||
typedef struct _MetaBox
|
||||
enum
|
||||
{
|
||||
int x1;
|
||||
int y1;
|
||||
int x2;
|
||||
int y2;
|
||||
} MetaBox;
|
||||
|
||||
G_DEFINE_TYPE (MetaPointerConfinementWayland, meta_pointer_confinement_wayland,
|
||||
META_TYPE_POINTER_CONSTRAINT);
|
||||
|
||||
static MetaBorder *
|
||||
add_border (GArray *borders,
|
||||
float x1, float y1,
|
||||
float x2, float y2,
|
||||
MetaBorderMotionDirection blocking_directions)
|
||||
{
|
||||
MetaBorder border;
|
||||
|
||||
border = (MetaBorder) {
|
||||
.line = (MetaLine2) {
|
||||
.a = (MetaVector2) {
|
||||
.x = x1,
|
||||
.y = y1,
|
||||
},
|
||||
.b = (MetaVector2) {
|
||||
.x = x2,
|
||||
.y = y2,
|
||||
},
|
||||
},
|
||||
.blocking_directions = blocking_directions,
|
||||
PROP_0,
|
||||
PROP_WAYLAND_POINTER_CONSTRAINT,
|
||||
N_PROPS,
|
||||
};
|
||||
|
||||
g_array_append_val (borders, border);
|
||||
static GParamSpec *props[N_PROPS] = { 0 };
|
||||
|
||||
return &g_array_index (borders, MetaBorder, borders->len - 1);
|
||||
}
|
||||
|
||||
static gint
|
||||
compare_lines_x (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
const MetaBorder *border_a = a;
|
||||
const MetaBorder *border_b = b;
|
||||
|
||||
if (border_a->line.a.x == border_b->line.a.x)
|
||||
return border_a->line.b.x < border_b->line.b.x;
|
||||
else
|
||||
return border_a->line.a.x > border_b->line.a.x;
|
||||
}
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaPointerConfinementWayland,
|
||||
meta_pointer_confinement_wayland,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
add_non_overlapping_edges (MetaBox *boxes,
|
||||
unsigned int band_above_start,
|
||||
unsigned int band_below_start,
|
||||
unsigned int band_below_end,
|
||||
GArray *borders)
|
||||
meta_pointer_confinement_wayland_update (MetaPointerConfinementWayland *self)
|
||||
{
|
||||
unsigned int i;
|
||||
GArray *band_merge;
|
||||
MetaBorder *border;
|
||||
MetaBorder *prev_border;
|
||||
MetaBorder *new_border;
|
||||
MetaPointerConstraint *constraint;
|
||||
|
||||
band_merge = g_array_new (FALSE, FALSE, sizeof *border);
|
||||
|
||||
/* Add bottom band of previous row, and top band of current row, and
|
||||
* sort them so lower left x coordinate comes first. If there are two
|
||||
* borders with the same left x coordinate, the wider one comes first.
|
||||
*/
|
||||
for (i = band_above_start; i < band_below_start; i++)
|
||||
{
|
||||
MetaBox *box = &boxes[i];
|
||||
add_border (band_merge, box->x1, box->y2, box->x2, box->y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
for (i = band_below_start; i < band_below_end; i++)
|
||||
{
|
||||
MetaBox *box= &boxes[i];
|
||||
add_border (band_merge, box->x1, box->y1, box->x2, box->y1,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
g_array_sort (band_merge, compare_lines_x);
|
||||
|
||||
/* Combine the two combined bands so that any overlapping border is
|
||||
* eliminated. */
|
||||
prev_border = NULL;
|
||||
for (i = 0; i < band_merge->len; i++)
|
||||
{
|
||||
border = &g_array_index (band_merge, MetaBorder, i);
|
||||
|
||||
g_assert (border->line.a.y == border->line.b.y);
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.a.y == border->line.a.y);
|
||||
g_assert (!prev_border ||
|
||||
(prev_border->line.a.x != border->line.a.x ||
|
||||
prev_border->line.b.x != border->line.b.x));
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.a.x <= border->line.a.x);
|
||||
|
||||
if (prev_border &&
|
||||
prev_border->line.a.x == border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* ------------ +
|
||||
* ------- =
|
||||
* [ ]-----
|
||||
*/
|
||||
prev_border->line.a.x = border->line.b.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x == border->line.b.x)
|
||||
{
|
||||
/*
|
||||
* ------------ +
|
||||
* ------ =
|
||||
* ------[ ]
|
||||
*/
|
||||
prev_border->line.b.x = border->line.a.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x == border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* -------- +
|
||||
* ------ =
|
||||
* --------------
|
||||
*/
|
||||
prev_border->line.b.x = border->line.b.x;
|
||||
}
|
||||
else if (prev_border &&
|
||||
prev_border->line.b.x >= border->line.a.x)
|
||||
{
|
||||
/*
|
||||
* --------------- +
|
||||
* ------ =
|
||||
* -----[ ]----
|
||||
*/
|
||||
new_border = add_border (borders,
|
||||
border->line.b.x,
|
||||
border->line.b.y,
|
||||
prev_border->line.b.x,
|
||||
prev_border->line.b.y,
|
||||
prev_border->blocking_directions);
|
||||
prev_border->line.b.x = border->line.a.x;
|
||||
prev_border = new_border;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_assert (!prev_border ||
|
||||
prev_border->line.b.x < border->line.a.x);
|
||||
/*
|
||||
* First border or non-overlapping.
|
||||
*
|
||||
* ----- +
|
||||
* ----- =
|
||||
* ----- -----
|
||||
*/
|
||||
g_array_append_val (borders, *border);
|
||||
prev_border = &g_array_index (borders, MetaBorder, borders->len - 1);
|
||||
}
|
||||
}
|
||||
|
||||
g_array_free (band_merge, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
add_band_bottom_edges (MetaBox *boxes,
|
||||
int band_start,
|
||||
int band_end,
|
||||
GArray *borders)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = band_start; i < band_end; i++)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
region_to_outline (cairo_region_t *region,
|
||||
GArray *borders)
|
||||
{
|
||||
MetaBox *boxes;
|
||||
int num_boxes;
|
||||
int i;
|
||||
int top_most, bottom_most;
|
||||
int current_roof;
|
||||
int prev_top;
|
||||
int band_start, prev_band_start;
|
||||
|
||||
/*
|
||||
* Remove any overlapping lines from the set of rectangles. Note that
|
||||
* pixman regions are grouped as rows of rectangles, where rectangles
|
||||
* in one row never touch or overlap and are all of the same height.
|
||||
*
|
||||
* -------- --- -------- ---
|
||||
* | | | | | | | |
|
||||
* ----------====---- --- ----------- ----- ---
|
||||
* | | => | |
|
||||
* ----==========--------- ----- ----------
|
||||
* | | | |
|
||||
* ------------------- -------------------
|
||||
*
|
||||
*/
|
||||
|
||||
num_boxes = cairo_region_num_rectangles (region);
|
||||
boxes = g_new (MetaBox, num_boxes);
|
||||
for (i = 0; i < num_boxes; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
boxes[i] = (MetaBox) {
|
||||
.x1 = rect.x,
|
||||
.y1 = rect.y,
|
||||
.x2 = rect.x + rect.width,
|
||||
.y2 = rect.y + rect.height,
|
||||
};
|
||||
}
|
||||
prev_top = 0;
|
||||
top_most = boxes[0].y1;
|
||||
current_roof = top_most;
|
||||
bottom_most = boxes[num_boxes - 1].y2;
|
||||
band_start = 0;
|
||||
prev_band_start = 0;
|
||||
for (i = 0; i < num_boxes; i++)
|
||||
{
|
||||
/* Detect if there is a vertical empty space, and add the lower
|
||||
* level of the previous band if so was the case. */
|
||||
if (i > 0 &&
|
||||
boxes[i].y1 != prev_top &&
|
||||
boxes[i].y1 != boxes[i - 1].y2)
|
||||
{
|
||||
current_roof = boxes[i].y1;
|
||||
add_band_bottom_edges (boxes,
|
||||
band_start,
|
||||
i,
|
||||
borders);
|
||||
}
|
||||
|
||||
/* Special case adding the last band, since it won't be handled
|
||||
* by the band change detection below. */
|
||||
if (boxes[i].y1 != current_roof && i == num_boxes - 1)
|
||||
{
|
||||
if (boxes[i].y1 != prev_top)
|
||||
{
|
||||
/* The last band is a single box, so we don't
|
||||
* have a prev_band_start to tell us when the
|
||||
* previous band started. */
|
||||
add_non_overlapping_edges (boxes,
|
||||
band_start,
|
||||
i,
|
||||
i + 1,
|
||||
borders);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_non_overlapping_edges (boxes,
|
||||
prev_band_start,
|
||||
band_start,
|
||||
i + 1,
|
||||
borders);
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect when passing a band and combine the top border of the
|
||||
* just passed band with the bottom band of the previous band.
|
||||
*/
|
||||
if (boxes[i].y1 != top_most && boxes[i].y1 != prev_top)
|
||||
{
|
||||
/* Combine the two passed bands. */
|
||||
if (prev_top != current_roof)
|
||||
{
|
||||
add_non_overlapping_edges (boxes,
|
||||
prev_band_start,
|
||||
band_start,
|
||||
i,
|
||||
borders);
|
||||
}
|
||||
|
||||
prev_band_start = band_start;
|
||||
band_start = i;
|
||||
}
|
||||
|
||||
/* Add the top border if the box is part of the current roof. */
|
||||
if (boxes[i].y1 == current_roof)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y1,
|
||||
boxes[i].x2, boxes[i].y1,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
|
||||
/* Add the bottom border of the last band. */
|
||||
if (boxes[i].y2 == bottom_most)
|
||||
{
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_Y);
|
||||
}
|
||||
|
||||
/* Always add the left border. */
|
||||
add_border (borders,
|
||||
boxes[i].x1, boxes[i].y1,
|
||||
boxes[i].x1, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X);
|
||||
|
||||
/* Always add the right border. */
|
||||
add_border (borders,
|
||||
boxes[i].x2, boxes[i].y1,
|
||||
boxes[i].x2, boxes[i].y2,
|
||||
META_BORDER_MOTION_DIRECTION_POSITIVE_X);
|
||||
|
||||
prev_top = boxes[i].y1;
|
||||
}
|
||||
|
||||
g_free (boxes);
|
||||
}
|
||||
|
||||
static MetaBorder *
|
||||
get_closest_border (GArray *borders,
|
||||
MetaLine2 *motion,
|
||||
uint32_t directions)
|
||||
{
|
||||
MetaBorder *border;
|
||||
MetaVector2 intersection;
|
||||
MetaVector2 delta;
|
||||
float distance_2;
|
||||
MetaBorder *closest_border = NULL;
|
||||
float closest_distance_2 = DBL_MAX;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < borders->len; i++)
|
||||
{
|
||||
border = &g_array_index (borders, MetaBorder, i);
|
||||
|
||||
if (!meta_border_is_blocking_directions (border, directions))
|
||||
continue;
|
||||
|
||||
if (!meta_line2_intersects_with (&border->line, motion, &intersection))
|
||||
continue;
|
||||
|
||||
delta = meta_vector2_subtract (intersection, motion->a);
|
||||
distance_2 = delta.x*delta.x + delta.y*delta.y;
|
||||
if (distance_2 < closest_distance_2)
|
||||
{
|
||||
closest_border = border;
|
||||
closest_distance_2 = distance_2;
|
||||
}
|
||||
}
|
||||
|
||||
return closest_border;
|
||||
}
|
||||
|
||||
static void
|
||||
clamp_to_border (MetaBorder *border,
|
||||
MetaLine2 *motion,
|
||||
uint32_t *motion_dir)
|
||||
{
|
||||
/*
|
||||
* When clamping either rightward or downward motions, the motion needs to be
|
||||
* clamped so that the destination coordinate does not end up on the border
|
||||
* (see weston_pointer_clamp_event_to_region). Do this by clamping such
|
||||
* motions to the border minus the smallest possible wl_fixed_t value.
|
||||
*
|
||||
* When clamping in either leftward or upward motion, the resulting coordinate
|
||||
* needs to be clamped so that it is enough on the inside to avoid the
|
||||
* inaccuracies of clutter's stage to actor transformation algorithm (the one
|
||||
* used in clutter_actor_transform_stage_point) to make it end up outside the
|
||||
* next motion. It also needs to be clamped so that to the wl_fixed_t
|
||||
* coordinate may still be right on the border (i.e. at .0). Testing shows
|
||||
* that the smallest wl_fixed_t value divided by 10 is small enough to make
|
||||
* the wl_fixed_t coordinate .0 and large enough to avoid the inaccuracies of
|
||||
* clutters transform algorithm.
|
||||
*/
|
||||
if (meta_border_is_horizontal (border))
|
||||
{
|
||||
if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_Y)
|
||||
motion->b.y = border->line.a.y - wl_fixed_to_double (1);
|
||||
else
|
||||
motion->b.y = border->line.a.y + wl_fixed_to_double (1) / 10;
|
||||
*motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_Y |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_Y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*motion_dir & META_BORDER_MOTION_DIRECTION_POSITIVE_X)
|
||||
motion->b.x = border->line.a.x - wl_fixed_to_double (1);
|
||||
else
|
||||
motion->b.x = border->line.a.x + wl_fixed_to_double (1) / 10;
|
||||
*motion_dir &= ~(META_BORDER_MOTION_DIRECTION_POSITIVE_X |
|
||||
META_BORDER_MOTION_DIRECTION_NEGATIVE_X);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_motion_directions (MetaLine2 *motion)
|
||||
{
|
||||
uint32_t directions = 0;
|
||||
|
||||
if (motion->a.x < motion->b.x)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_X;
|
||||
else if (motion->a.x > motion->b.x)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_X;
|
||||
if (motion->a.y < motion->b.y)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_POSITIVE_Y;
|
||||
else if (motion->a.y > motion->b.y)
|
||||
directions |= META_BORDER_MOTION_DIRECTION_NEGATIVE_Y;
|
||||
|
||||
return directions;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_confinement_wayland_constrain (MetaPointerConstraint *constraint,
|
||||
ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
MetaPointerConfinementWayland *self =
|
||||
META_POINTER_CONFINEMENT_WAYLAND (constraint);
|
||||
MetaWaylandSurface *surface;
|
||||
cairo_region_t *region;
|
||||
float sx, sy;
|
||||
float prev_sx, prev_sy;
|
||||
GArray *borders;
|
||||
MetaLine2 motion;
|
||||
MetaBorder *closest_border;
|
||||
uint32_t directions;
|
||||
|
||||
surface = meta_wayland_pointer_constraint_get_surface (self->constraint);
|
||||
|
||||
meta_wayland_surface_get_relative_coordinates (surface, *x, *y, &sx, &sy);
|
||||
meta_wayland_surface_get_relative_coordinates (surface, prev_x, prev_y,
|
||||
&prev_sx, &prev_sy);
|
||||
|
||||
/* For motions in a positive direction on any axis, append the smallest
|
||||
* possible value representable in a Wayland absolute coordinate. This is
|
||||
* in order to avoid not clamping motion that as a floating point number
|
||||
* won't be clamped, but will be rounded up to be outside of the range
|
||||
* of wl_fixed_t. */
|
||||
if (sx > prev_sx)
|
||||
sx += (float)wl_fixed_to_double(1);
|
||||
if (sy > prev_sy)
|
||||
sy += (float)wl_fixed_to_double(1);
|
||||
|
||||
borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder));
|
||||
|
||||
/*
|
||||
* Generate borders given the confine region we are to use. The borders
|
||||
* are defined to be the outer region of the allowed area. This means
|
||||
* top/left borders are "within" the allowed area, while bottom/right
|
||||
* borders are outside. This needs to be considered when clamping
|
||||
* confined motion vectors.
|
||||
*/
|
||||
region =
|
||||
meta_wayland_pointer_constraint_calculate_effective_region (self->constraint);
|
||||
region_to_outline (region, borders);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
motion = (MetaLine2) {
|
||||
.a = (MetaVector2) {
|
||||
.x = prev_sx,
|
||||
.y = prev_sy,
|
||||
},
|
||||
.b = (MetaVector2) {
|
||||
.x = sx,
|
||||
.y = sy,
|
||||
},
|
||||
};
|
||||
directions = get_motion_directions (&motion);
|
||||
|
||||
while (directions)
|
||||
{
|
||||
closest_border = get_closest_border (borders,
|
||||
&motion,
|
||||
directions);
|
||||
if (closest_border)
|
||||
clamp_to_border (closest_border, &motion, &directions);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
meta_wayland_surface_get_absolute_coordinates (surface,
|
||||
motion.b.x, motion.b.y,
|
||||
x, y);
|
||||
|
||||
g_array_free (borders, FALSE);
|
||||
}
|
||||
|
||||
static float
|
||||
point_to_border_distance_2 (MetaBorder *border,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
float orig_x, orig_y;
|
||||
float dx, dy;
|
||||
|
||||
if (meta_border_is_horizontal (border))
|
||||
{
|
||||
if (x < border->line.a.x)
|
||||
orig_x = border->line.a.x;
|
||||
else if (x > border->line.b.x)
|
||||
orig_x = border->line.b.x;
|
||||
else
|
||||
orig_x = x;
|
||||
orig_y = border->line.a.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (y < border->line.a.y)
|
||||
orig_y = border->line.a.y;
|
||||
else if (y > border->line.b.y)
|
||||
orig_y = border->line.b.y;
|
||||
else
|
||||
orig_y = y;
|
||||
orig_x = border->line.a.x;
|
||||
}
|
||||
|
||||
dx = fabsf (orig_x - x);
|
||||
dy = fabsf (orig_y - y);
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
static void
|
||||
warp_to_behind_border (MetaBorder *border,
|
||||
float *sx,
|
||||
float *sy)
|
||||
{
|
||||
switch (border->blocking_directions)
|
||||
{
|
||||
case META_BORDER_MOTION_DIRECTION_POSITIVE_X:
|
||||
case META_BORDER_MOTION_DIRECTION_NEGATIVE_X:
|
||||
if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_X)
|
||||
*sx = border->line.a.x - wl_fixed_to_double (1);
|
||||
else
|
||||
*sx = border->line.a.x + wl_fixed_to_double (1);
|
||||
if (*sy < border->line.a.y)
|
||||
*sy = border->line.a.y + wl_fixed_to_double (1);
|
||||
else if (*sy > border->line.b.y)
|
||||
*sy = border->line.b.y - wl_fixed_to_double (1);
|
||||
break;
|
||||
case META_BORDER_MOTION_DIRECTION_POSITIVE_Y:
|
||||
case META_BORDER_MOTION_DIRECTION_NEGATIVE_Y:
|
||||
if (border->blocking_directions == META_BORDER_MOTION_DIRECTION_POSITIVE_Y)
|
||||
*sy = border->line.a.y - wl_fixed_to_double (1);
|
||||
else
|
||||
*sy = border->line.a.y + wl_fixed_to_double (1);
|
||||
if (*sx < border->line.a.x)
|
||||
*sx = border->line.a.x + wl_fixed_to_double (1);
|
||||
else if (*sx > (border->line.b.x))
|
||||
*sx = border->line.b.x - wl_fixed_to_double (1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_confinement_wayland_maybe_warp (MetaPointerConfinementWayland *self)
|
||||
{
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandSurface *surface;
|
||||
graphene_point_t point;
|
||||
float sx;
|
||||
float sy;
|
||||
cairo_region_t *region;
|
||||
|
||||
seat = meta_wayland_pointer_constraint_get_seat (self->constraint);
|
||||
surface = meta_wayland_pointer_constraint_get_surface (self->constraint);
|
||||
|
||||
clutter_input_device_get_coords (seat->pointer->device, NULL, &point);
|
||||
meta_wayland_surface_get_relative_coordinates (surface,
|
||||
point.x, point.y,
|
||||
&sx, &sy);
|
||||
|
||||
region =
|
||||
meta_wayland_pointer_constraint_calculate_effective_region (self->constraint);
|
||||
|
||||
if (!cairo_region_contains_point (region, (int)sx, (int)sy))
|
||||
{
|
||||
GArray *borders;
|
||||
float closest_distance_2 = FLT_MAX;
|
||||
MetaBorder *closest_border = NULL;
|
||||
ClutterSeat *seat;
|
||||
unsigned int i;
|
||||
float x;
|
||||
float y;
|
||||
|
||||
borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder));
|
||||
|
||||
region_to_outline (region, borders);
|
||||
|
||||
for (i = 0; i < borders->len; i++)
|
||||
{
|
||||
MetaBorder *border = &g_array_index (borders, MetaBorder, i);
|
||||
float distance_2;
|
||||
|
||||
distance_2 = point_to_border_distance_2 (border, sx, sy);
|
||||
if (distance_2 < closest_distance_2)
|
||||
{
|
||||
closest_border = border;
|
||||
closest_distance_2 = distance_2;
|
||||
}
|
||||
}
|
||||
|
||||
warp_to_behind_border (closest_border, &sx, &sy);
|
||||
|
||||
meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, &x, &y);
|
||||
|
||||
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
clutter_seat_warp_pointer (seat, (int)x, (int)y);
|
||||
}
|
||||
|
||||
cairo_region_destroy (region);
|
||||
constraint =
|
||||
META_POINTER_CONFINEMENT_WAYLAND_GET_CLASS (self)->create_constraint (self);
|
||||
meta_backend_set_client_pointer_constraint (meta_get_backend (), constraint);
|
||||
g_object_unref (constraint);
|
||||
}
|
||||
|
||||
static void
|
||||
surface_geometry_changed (MetaWaylandSurface *surface,
|
||||
MetaPointerConfinementWayland *self)
|
||||
{
|
||||
meta_pointer_confinement_wayland_maybe_warp (self);
|
||||
meta_pointer_confinement_wayland_update (self);
|
||||
}
|
||||
|
||||
static void
|
||||
window_position_changed (MetaWindow *window,
|
||||
MetaPointerConfinementWayland *self)
|
||||
{
|
||||
meta_pointer_confinement_wayland_maybe_warp (self);
|
||||
meta_pointer_confinement_wayland_update (self);
|
||||
}
|
||||
|
||||
MetaPointerConstraint *
|
||||
meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint)
|
||||
void
|
||||
meta_pointer_confinement_wayland_enable (MetaPointerConfinementWayland *confinement)
|
||||
{
|
||||
GObject *object;
|
||||
MetaPointerConfinementWayland *confinement;
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWindow *window;
|
||||
|
||||
object = g_object_new (META_TYPE_POINTER_CONFINEMENT_WAYLAND, NULL);
|
||||
confinement = META_POINTER_CONFINEMENT_WAYLAND (object);
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
g_assert (!priv->enabled);
|
||||
|
||||
confinement->constraint = constraint;
|
||||
priv->enabled = TRUE;
|
||||
constraint = priv->constraint;
|
||||
|
||||
surface = meta_wayland_pointer_constraint_get_surface (constraint);
|
||||
g_signal_connect_object (surface,
|
||||
@ -720,7 +123,34 @@ meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint)
|
||||
0);
|
||||
}
|
||||
|
||||
return META_POINTER_CONSTRAINT (confinement);
|
||||
meta_pointer_confinement_wayland_update (confinement);
|
||||
}
|
||||
|
||||
void
|
||||
meta_pointer_confinement_wayland_disable (MetaPointerConfinementWayland *confinement)
|
||||
{
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
MetaWaylandSurface *surface;
|
||||
MetaWindow *window;
|
||||
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
constraint = priv->constraint;
|
||||
g_assert (priv->enabled);
|
||||
|
||||
priv->enabled = FALSE;
|
||||
surface = meta_wayland_pointer_constraint_get_surface (constraint);
|
||||
g_signal_handlers_disconnect_by_func (surface, surface_geometry_changed,
|
||||
confinement);
|
||||
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (window)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (window, window_position_changed,
|
||||
confinement);
|
||||
}
|
||||
|
||||
meta_backend_set_client_pointer_constraint (meta_get_backend (), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -728,11 +158,110 @@ meta_pointer_confinement_wayland_init (MetaPointerConfinementWayland *confinemen
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_confinement_wayland_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPointerConfinementWayland *confinement;
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
|
||||
confinement = META_POINTER_CONFINEMENT_WAYLAND (object);
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WAYLAND_POINTER_CONSTRAINT:
|
||||
g_value_set_object (value, priv->constraint);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_confinement_wayland_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MetaPointerConfinementWayland *confinement;
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
|
||||
confinement = META_POINTER_CONFINEMENT_WAYLAND (object);
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WAYLAND_POINTER_CONSTRAINT:
|
||||
priv->constraint = g_value_get_object (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static MetaPointerConstraint *
|
||||
meta_pointer_confinement_wayland_create_constraint (MetaPointerConfinementWayland *confinement)
|
||||
{
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
MetaPointerConstraint *constraint;
|
||||
MetaWaylandSurface *surface;
|
||||
cairo_region_t *region;
|
||||
float dx, dy;
|
||||
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
|
||||
surface = meta_wayland_pointer_constraint_get_surface (priv->constraint);
|
||||
region =
|
||||
meta_wayland_pointer_constraint_calculate_effective_region (priv->constraint);
|
||||
|
||||
meta_wayland_surface_get_absolute_coordinates (surface, 0, 0, &dx, &dy);
|
||||
cairo_region_translate (region, dx, dy);
|
||||
|
||||
constraint = meta_pointer_constraint_new (region);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
return constraint;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_pointer_confinement_wayland_class_init (MetaPointerConfinementWaylandClass *klass)
|
||||
{
|
||||
MetaPointerConstraintClass *pointer_constraint_class =
|
||||
META_POINTER_CONSTRAINT_CLASS (klass);
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
pointer_constraint_class->constrain = meta_pointer_confinement_wayland_constrain;
|
||||
object_class->set_property = meta_pointer_confinement_wayland_set_property;
|
||||
object_class->get_property = meta_pointer_confinement_wayland_get_property;
|
||||
|
||||
klass->create_constraint = meta_pointer_confinement_wayland_create_constraint;
|
||||
|
||||
props[PROP_WAYLAND_POINTER_CONSTRAINT] =
|
||||
g_param_spec_object ("wayland-pointer-constraint",
|
||||
"Wayland pointer constraint",
|
||||
"Wayland pointer constraint",
|
||||
META_TYPE_WAYLAND_POINTER_CONSTRAINT,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||
}
|
||||
|
||||
MetaPointerConfinementWayland *
|
||||
meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
return g_object_new (META_TYPE_POINTER_CONFINEMENT_WAYLAND,
|
||||
"wayland-pointer-constraint", constraint,
|
||||
NULL);
|
||||
}
|
||||
|
||||
MetaWaylandPointerConstraint *
|
||||
meta_pointer_confinement_wayland_get_wayland_pointer_constraint (MetaPointerConfinementWayland *confinement)
|
||||
{
|
||||
MetaPointerConfinementWaylandPrivate *priv;
|
||||
|
||||
priv = meta_pointer_confinement_wayland_get_instance_private (confinement);
|
||||
return priv->constraint;
|
||||
}
|
||||
|
@ -33,12 +33,23 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_POINTER_CONFINEMENT_WAYLAND (meta_pointer_confinement_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaPointerConfinementWayland,
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaPointerConfinementWayland,
|
||||
meta_pointer_confinement_wayland,
|
||||
META, POINTER_CONFINEMENT_WAYLAND,
|
||||
MetaPointerConstraint);
|
||||
GObject)
|
||||
|
||||
MetaPointerConstraint *meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint);
|
||||
struct _MetaPointerConfinementWaylandClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
MetaPointerConstraint * (*create_constraint) (MetaPointerConfinementWayland *confinement);
|
||||
};
|
||||
|
||||
MetaPointerConfinementWayland *meta_pointer_confinement_wayland_new (MetaWaylandPointerConstraint *constraint);
|
||||
MetaWaylandPointerConstraint *
|
||||
meta_pointer_confinement_wayland_get_wayland_pointer_constraint (MetaPointerConfinementWayland *confinement);
|
||||
void meta_pointer_confinement_wayland_enable (MetaPointerConfinementWayland *confinement);
|
||||
void meta_pointer_confinement_wayland_disable (MetaPointerConfinementWayland *confinement);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -37,33 +37,55 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "compositor/meta-surface-actor-wayland.h"
|
||||
|
||||
struct _MetaPointerLockWayland
|
||||
{
|
||||
MetaPointerConstraint parent;
|
||||
GObject parent;
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland,
|
||||
META_TYPE_POINTER_CONSTRAINT);
|
||||
META_TYPE_POINTER_CONFINEMENT_WAYLAND)
|
||||
|
||||
static void
|
||||
meta_pointer_lock_wayland_constrain (MetaPointerConstraint *constraint,
|
||||
ClutterInputDevice *device,
|
||||
guint32 time,
|
||||
float prev_x,
|
||||
float prev_y,
|
||||
float *x,
|
||||
float *y)
|
||||
static MetaPointerConstraint *
|
||||
meta_pointer_lock_wayland_create_constraint (MetaPointerConfinementWayland *confinement)
|
||||
{
|
||||
*x = prev_x;
|
||||
*y = prev_y;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterInputDevice *pointer = clutter_seat_get_pointer (seat);
|
||||
MetaWaylandPointerConstraint *wayland_constraint;
|
||||
MetaPointerConstraint *constraint;
|
||||
MetaWaylandSurface *surface;
|
||||
graphene_point_t point;
|
||||
cairo_region_t *region;
|
||||
float sx, sy, x, y;
|
||||
|
||||
clutter_input_device_get_coords (pointer, NULL, &point);
|
||||
wayland_constraint =
|
||||
meta_pointer_confinement_wayland_get_wayland_pointer_constraint (confinement);
|
||||
surface = meta_wayland_pointer_constraint_get_surface (wayland_constraint);
|
||||
meta_wayland_surface_get_relative_coordinates (surface,
|
||||
point.x, point.y,
|
||||
&sx, &sy);
|
||||
|
||||
meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, &x, &y);
|
||||
region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { (int) x, (int) y, 1 , 1 });
|
||||
|
||||
constraint = meta_pointer_constraint_new (region);
|
||||
cairo_region_destroy (region);
|
||||
|
||||
return constraint;
|
||||
}
|
||||
|
||||
MetaPointerConstraint *
|
||||
meta_pointer_lock_wayland_new (void)
|
||||
MetaPointerConfinementWayland *
|
||||
meta_pointer_lock_wayland_new (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
return g_object_new (META_TYPE_POINTER_LOCK_WAYLAND, NULL);
|
||||
return g_object_new (META_TYPE_POINTER_LOCK_WAYLAND,
|
||||
"wayland-pointer-constraint", constraint,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -74,8 +96,9 @@ meta_pointer_lock_wayland_init (MetaPointerLockWayland *lock_wayland)
|
||||
static void
|
||||
meta_pointer_lock_wayland_class_init (MetaPointerLockWaylandClass *klass)
|
||||
{
|
||||
MetaPointerConstraintClass *pointer_constraint_class =
|
||||
META_POINTER_CONSTRAINT_CLASS (klass);
|
||||
MetaPointerConfinementWaylandClass *confinement_class =
|
||||
META_POINTER_CONFINEMENT_WAYLAND_CLASS (klass);
|
||||
|
||||
pointer_constraint_class->constrain = meta_pointer_lock_wayland_constrain;
|
||||
confinement_class->create_constraint =
|
||||
meta_pointer_lock_wayland_create_constraint;
|
||||
}
|
||||
|
@ -27,15 +27,15 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "wayland/meta-pointer-confinement-wayland.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_POINTER_LOCK_WAYLAND (meta_pointer_lock_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaPointerLockWayland, meta_pointer_lock_wayland,
|
||||
META, POINTER_LOCK_WAYLAND, MetaPointerConstraint);
|
||||
META, POINTER_LOCK_WAYLAND, MetaPointerConfinementWayland)
|
||||
|
||||
MetaPointerConstraint *meta_pointer_lock_wayland_new (void);
|
||||
MetaPointerConfinementWayland *meta_pointer_lock_wayland_new (MetaWaylandPointerConstraint *constraint);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -81,6 +81,7 @@ update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface)
|
||||
|
||||
static void
|
||||
cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite,
|
||||
float best_scale,
|
||||
int x,
|
||||
int y,
|
||||
MetaWaylandCursorSurface *cursor_surface)
|
||||
@ -186,6 +187,7 @@ meta_wayland_cursor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *role,
|
||||
META_WAYLAND_CURSOR_SURFACE (surface->role);
|
||||
MetaWaylandCursorSurfacePrivate *priv =
|
||||
meta_wayland_cursor_surface_get_instance_private (cursor_surface);
|
||||
ClutterInputDevice *device;
|
||||
graphene_point_t point;
|
||||
graphene_rect_t logical_monitor_rect;
|
||||
|
||||
@ -195,7 +197,8 @@ meta_wayland_cursor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *role,
|
||||
logical_monitor_rect =
|
||||
meta_rectangle_to_graphene_rect (&logical_monitor->rect);
|
||||
|
||||
point = meta_cursor_renderer_get_position (priv->cursor_renderer);
|
||||
device = meta_cursor_renderer_get_input_device (priv->cursor_renderer);
|
||||
clutter_input_device_get_coords (device, NULL, &point);
|
||||
|
||||
return graphene_rect_contains_point (&logical_monitor_rect, &point);
|
||||
}
|
||||
|
@ -74,16 +74,15 @@ static MetaLogicalMonitor *
|
||||
dnd_surface_find_logical_monitor (MetaWaylandActorSurface *actor_surface)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (backend);
|
||||
MetaCursorTracker *cursor_tracker =
|
||||
meta_backend_get_cursor_tracker (backend);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
graphene_point_t pointer_pos;
|
||||
graphene_point_t point;
|
||||
|
||||
pointer_pos = meta_cursor_renderer_get_position (cursor_renderer);
|
||||
meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL);
|
||||
return meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
pointer_pos.x,
|
||||
pointer_pos.y);
|
||||
point.x, point.y);
|
||||
}
|
||||
|
||||
static double
|
||||
|
@ -68,7 +68,7 @@ struct _MetaWaylandPointerConstraint
|
||||
wl_fixed_t x_hint;
|
||||
wl_fixed_t y_hint;
|
||||
|
||||
MetaPointerConstraint *constraint;
|
||||
MetaPointerConfinementWayland *confinement;
|
||||
};
|
||||
|
||||
typedef struct _MetaWaylandSurfacePointerConstraintsData
|
||||
@ -375,7 +375,7 @@ meta_wayland_pointer_constraint_notify_deactivated (MetaWaylandPointerConstraint
|
||||
zwp_confined_pointer_v1_send_unconfined (resource);
|
||||
}
|
||||
|
||||
static MetaPointerConstraint *
|
||||
static MetaPointerConfinementWayland *
|
||||
meta_wayland_pointer_constraint_create_pointer_constraint (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
struct wl_resource *resource = constraint->resource;
|
||||
@ -384,7 +384,7 @@ meta_wayland_pointer_constraint_create_pointer_constraint (MetaWaylandPointerCon
|
||||
&zwp_locked_pointer_v1_interface,
|
||||
&locked_pointer_interface))
|
||||
{
|
||||
return meta_pointer_lock_wayland_new ();
|
||||
return meta_pointer_lock_wayland_new (constraint);
|
||||
}
|
||||
else if (wl_resource_instance_of (resource,
|
||||
&zwp_confined_pointer_v1_interface,
|
||||
@ -399,8 +399,6 @@ meta_wayland_pointer_constraint_create_pointer_constraint (MetaWaylandPointerCon
|
||||
static void
|
||||
meta_wayland_pointer_constraint_enable (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
g_assert (!constraint->is_enabled);
|
||||
|
||||
constraint->is_enabled = TRUE;
|
||||
@ -408,20 +406,25 @@ meta_wayland_pointer_constraint_enable (MetaWaylandPointerConstraint *constraint
|
||||
meta_wayland_pointer_start_grab (constraint->seat->pointer,
|
||||
&constraint->grab);
|
||||
|
||||
constraint->constraint =
|
||||
constraint->confinement =
|
||||
meta_wayland_pointer_constraint_create_pointer_constraint (constraint);
|
||||
meta_backend_set_client_pointer_constraint (backend, constraint->constraint);
|
||||
g_object_add_weak_pointer (G_OBJECT (constraint->constraint),
|
||||
(gpointer *) &constraint->constraint);
|
||||
g_object_unref (constraint->constraint);
|
||||
meta_pointer_confinement_wayland_enable (constraint->confinement);
|
||||
g_object_add_weak_pointer (G_OBJECT (constraint->confinement),
|
||||
(gpointer *) &constraint->confinement);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_constraint_disable (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
constraint->is_enabled = FALSE;
|
||||
|
||||
if (constraint->confinement)
|
||||
{
|
||||
meta_pointer_confinement_wayland_disable (constraint->confinement);
|
||||
g_object_unref (constraint->confinement);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_constraint_notify_deactivated (constraint);
|
||||
meta_backend_set_client_pointer_constraint (meta_get_backend (), NULL);
|
||||
meta_wayland_pointer_end_grab (constraint->grab.pointer);
|
||||
}
|
||||
|
||||
|
@ -1044,7 +1044,11 @@ meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
void
|
||||
meta_wayland_pointer_repick (MetaWaylandPointer *pointer)
|
||||
{
|
||||
clutter_input_device_update (pointer->device, NULL, FALSE);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterStage *stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||
|
||||
clutter_input_device_update (pointer->device, NULL, stage, FALSE,
|
||||
CLUTTER_CURRENT_TIME);
|
||||
repick_for_event (pointer, NULL);
|
||||
}
|
||||
|
||||
@ -1164,8 +1168,13 @@ pointer_set_cursor (struct wl_client *client,
|
||||
|
||||
if (surface)
|
||||
{
|
||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||
ClutterSeat *clutter_seat =
|
||||
clutter_backend_get_default_seat (clutter_backend);
|
||||
ClutterInputDevice *device = clutter_seat_get_pointer (clutter_seat);
|
||||
MetaCursorRenderer *cursor_renderer =
|
||||
meta_backend_get_cursor_renderer (meta_get_backend ());
|
||||
meta_backend_get_cursor_renderer_for_device (meta_get_backend (),
|
||||
device);
|
||||
MetaWaylandCursorSurface *cursor_surface;
|
||||
|
||||
cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role);
|
||||
|
@ -242,30 +242,3 @@ meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
|
||||
|
||||
return tablet_seat;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_manager_update_cursor_position (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandTabletSeat *tablet_seat = NULL;
|
||||
MetaWaylandTabletTool *tool = NULL;
|
||||
ClutterInputDeviceTool *device_tool;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
device_tool = clutter_event_get_device_tool (event);
|
||||
|
||||
if (device)
|
||||
tablet_seat = meta_wayland_tablet_manager_lookup_seat (manager, device);
|
||||
|
||||
if (tablet_seat && device_tool)
|
||||
tool = meta_wayland_tablet_seat_lookup_tool (tablet_seat, device_tool);
|
||||
|
||||
if (tool)
|
||||
{
|
||||
gfloat new_x, new_y;
|
||||
|
||||
clutter_event_get_coords (event, &new_x, &new_y);
|
||||
meta_wayland_tablet_tool_set_cursor_position (tool, new_x, new_y);
|
||||
}
|
||||
}
|
||||
|
@ -50,7 +50,4 @@ MetaWaylandTabletSeat *
|
||||
meta_wayland_tablet_manager_ensure_seat (MetaWaylandTabletManager *manager,
|
||||
MetaWaylandSeat *seat);
|
||||
|
||||
void meta_wayland_tablet_manager_update_cursor_position (MetaWaylandTabletManager *manager,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_MANAGER_H */
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "backends/meta-input-settings-private.h"
|
||||
#include "core/display-private.h"
|
||||
#include "compositor/meta-surface-actor-wayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-tablet-pad-group.h"
|
||||
@ -244,15 +245,14 @@ tablet_pad_set_feedback (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandTabletPad *pad = wl_resource_get_user_data (resource);
|
||||
MetaWaylandTabletPadGroup *group = tablet_pad_lookup_button_group (pad, button);
|
||||
MetaInputSettings *input_settings;
|
||||
MetaPadActionMapper *mapper;
|
||||
|
||||
if (!group || group->mode_switch_serial != serial)
|
||||
return;
|
||||
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
mapper = meta_get_display ()->pad_action_mapper;
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, pad->device, button))
|
||||
if (meta_pad_action_mapper_is_button_grabbed (mapper, pad->device, button))
|
||||
return;
|
||||
|
||||
if (meta_wayland_tablet_pad_group_is_mode_switch_button (group, button))
|
||||
@ -367,14 +367,13 @@ static gboolean
|
||||
meta_wayland_tablet_pad_handle_event_action (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
MetaPadActionMapper *mapper;
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
mapper = meta_get_display ()->pad_action_mapper;
|
||||
|
||||
if (input_settings &&
|
||||
meta_input_settings_is_pad_button_grabbed (input_settings, device,
|
||||
if (meta_pad_action_mapper_is_button_grabbed (mapper, device,
|
||||
event->pad_button.button))
|
||||
return TRUE;
|
||||
|
||||
|
@ -395,6 +395,7 @@ tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener,
|
||||
|
||||
static void
|
||||
tool_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
|
||||
float best_scale,
|
||||
int x,
|
||||
int y,
|
||||
MetaWaylandTabletTool *tool)
|
||||
@ -931,7 +932,14 @@ meta_wayland_tablet_tool_update (MetaWaylandTabletTool *tool,
|
||||
break;
|
||||
case CLUTTER_PROXIMITY_IN:
|
||||
if (!tool->cursor_renderer)
|
||||
tool->cursor_renderer = meta_cursor_renderer_new (meta_get_backend ());
|
||||
{
|
||||
MetaCursorRenderer *renderer;
|
||||
|
||||
renderer =
|
||||
meta_backend_get_cursor_renderer_for_device (meta_get_backend (),
|
||||
clutter_event_get_source_device (event));
|
||||
g_set_object (&tool->cursor_renderer, renderer);
|
||||
}
|
||||
tool->current_tablet =
|
||||
meta_wayland_tablet_seat_lookup_tablet (tool->seat,
|
||||
clutter_event_get_source_device (event));
|
||||
@ -976,15 +984,6 @@ meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool,
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *tool,
|
||||
float new_x,
|
||||
float new_y)
|
||||
{
|
||||
if (tool->cursor_renderer)
|
||||
meta_cursor_renderer_set_position (tool->cursor_renderer, new_x, new_y);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface)
|
||||
|
@ -78,10 +78,6 @@ void meta_wayland_tablet_tool_update (MetaWaylandTabletTool *t
|
||||
gboolean meta_wayland_tablet_tool_handle_event (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event);
|
||||
|
||||
void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *tool,
|
||||
float new_x,
|
||||
float new_y);
|
||||
|
||||
gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface,
|
||||
uint32_t serial);
|
||||
|
@ -401,35 +401,34 @@ touch_send_frame_event (MetaWaylandTouch *touch)
|
||||
g_list_free (surfaces);
|
||||
}
|
||||
|
||||
static void
|
||||
check_send_frame_event (MetaWaylandTouch *touch,
|
||||
const ClutterEvent *event)
|
||||
static gboolean
|
||||
queue_frame_event_cb (MetaWaylandTouch *touch)
|
||||
{
|
||||
gboolean send_frame_event;
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterEventSequence *sequence;
|
||||
gint32 slot;
|
||||
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
sequence = clutter_event_get_event_sequence (event);
|
||||
slot = meta_event_native_sequence_get_slot (sequence);
|
||||
touch->frame_slots &= ~(1 << slot);
|
||||
|
||||
if (touch->frame_slots == 0)
|
||||
send_frame_event = TRUE;
|
||||
else
|
||||
send_frame_event = FALSE;
|
||||
}
|
||||
else
|
||||
#endif /* HAVE_NATIVE_BACKEND */
|
||||
{
|
||||
send_frame_event = TRUE;
|
||||
}
|
||||
|
||||
if (send_frame_event)
|
||||
touch_send_frame_event (touch);
|
||||
touch->queued_frame_id = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
send_or_queue_frame_event (MetaWaylandTouch *touch)
|
||||
{
|
||||
if (clutter_events_pending ())
|
||||
{
|
||||
if (!touch->queued_frame_id)
|
||||
{
|
||||
touch->queued_frame_id =
|
||||
g_idle_add_full (CLUTTER_PRIORITY_EVENTS + 1,
|
||||
(GSourceFunc) queue_frame_event_cb,
|
||||
touch, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There's no more events */
|
||||
g_clear_handle_id (&touch->queued_frame_id, g_source_remove);
|
||||
touch_send_frame_event (touch);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -450,11 +449,15 @@ meta_wayland_touch_handle_event (MetaWaylandTouch *touch,
|
||||
handle_touch_end (touch, event);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_CANCEL:
|
||||
meta_wayland_touch_cancel (touch);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
check_send_frame_event (touch, event);
|
||||
send_or_queue_frame_event (touch);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -511,45 +514,6 @@ meta_wayland_touch_cancel (MetaWaylandTouch *touch)
|
||||
g_list_free (surfaces);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static gboolean
|
||||
evdev_filter_func (struct libinput_event *event,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWaylandTouch *touch = data;
|
||||
|
||||
switch (libinput_event_get_type (event))
|
||||
{
|
||||
case LIBINPUT_EVENT_TOUCH_DOWN:
|
||||
case LIBINPUT_EVENT_TOUCH_UP:
|
||||
case LIBINPUT_EVENT_TOUCH_MOTION: {
|
||||
struct libinput_event_touch *touch_event;
|
||||
int32_t slot;
|
||||
|
||||
touch_event = libinput_event_get_touch_event (event);
|
||||
slot = libinput_event_touch_get_slot (touch_event);
|
||||
|
||||
/* XXX: Could theoretically overflow, 64 slots should be
|
||||
* enough for most hw/usecases though.
|
||||
*/
|
||||
touch->frame_slots |= (1 << slot);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TOUCH_CANCEL:
|
||||
/* Clutter translates this into individual CLUTTER_TOUCH_CANCEL events,
|
||||
* which are not so useful when sending a global signal as the protocol
|
||||
* requires.
|
||||
*/
|
||||
meta_wayland_touch_cancel (touch);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CLUTTER_EVENT_PROPAGATE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_wayland_touch_enable (MetaWaylandTouch *touch)
|
||||
{
|
||||
@ -561,35 +525,11 @@ meta_wayland_touch_enable (MetaWaylandTouch *touch)
|
||||
#endif /* HAVE_NATIVE_BACKEND */
|
||||
|
||||
wl_list_init (&touch->resource_list);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
||||
|
||||
meta_seat_native_add_filter (META_SEAT_NATIVE (seat),
|
||||
evdev_filter_func, touch, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_touch_disable (MetaWaylandTouch *touch)
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
||||
|
||||
meta_seat_native_remove_filter (META_SEAT_NATIVE (seat),
|
||||
evdev_filter_func, touch);
|
||||
}
|
||||
#endif
|
||||
|
||||
meta_wayland_touch_cancel (touch);
|
||||
|
||||
g_clear_pointer (&touch->touch_surfaces, g_hash_table_unref);
|
||||
|
@ -41,10 +41,9 @@ struct _MetaWaylandTouch
|
||||
|
||||
struct wl_list resource_list;
|
||||
|
||||
guint queued_frame_id;
|
||||
GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */
|
||||
GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */
|
||||
|
||||
guint64 frame_slots;
|
||||
};
|
||||
|
||||
void meta_wayland_touch_enable (MetaWaylandTouch *touch);
|
||||
|
@ -2802,7 +2802,7 @@ query_pressed_buttons (MetaWindow *window)
|
||||
ClutterModifierType mods;
|
||||
int button = 0;
|
||||
|
||||
meta_cursor_tracker_get_pointer (tracker, NULL, NULL, &mods);
|
||||
meta_cursor_tracker_get_pointer (tracker, NULL, &mods);
|
||||
|
||||
if (mods & CLUTTER_BUTTON1_MASK)
|
||||
button |= 1 << 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user