Compare commits
22 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4c3e166469 | ||
![]() |
9d0b49439e | ||
![]() |
eb6f74987e | ||
![]() |
726296f022 | ||
![]() |
901490545c | ||
![]() |
8478d8a002 | ||
![]() |
81dd9aa1da | ||
![]() |
5d7b94abb8 | ||
![]() |
cdb5ead795 | ||
![]() |
0159efe34b | ||
![]() |
9f68507f0c | ||
![]() |
e52408d259 | ||
![]() |
45014a27a4 | ||
![]() |
d4e02527d3 | ||
![]() |
7f594bbe46 | ||
![]() |
e66091d8aa | ||
![]() |
d538016ce7 | ||
![]() |
6d34b2e7dd | ||
![]() |
f0b758b891 | ||
![]() |
a150225a59 | ||
![]() |
2df1bd3dda | ||
![]() |
c02638e614 |
19
NEWS
19
NEWS
@@ -1,3 +1,22 @@
|
||||
3.24.4
|
||||
======
|
||||
* Fix wacom cursor offset on wayland [Jason; #784009]
|
||||
* Do not throttle motion events on tablet tools [Carlos; #783535]
|
||||
* Handle left-handed mode on pen/eraser devices [Carlos; #782027]
|
||||
* Fix crash when decreasing number of workspaces [Florian; #784223]
|
||||
* Fix crash when moving across on-adjacent monitors [Jonas; #783630]
|
||||
* Fix window moving/resizing via tablet tools [Jason; #777333]
|
||||
* Improve stability of tablet plugs/unplugs [Carlos; #784881]
|
||||
* Implement tablet rings/strips configuration [Carlos; #782033]
|
||||
* Support tablet wheel events on wayland [Jason; #783716]
|
||||
* Misc. bug fixes [Carlos, Jonas; #784402, #784867, #781723]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Carlos Garnacho, Jason Gerecke, Florian Müllner
|
||||
|
||||
Translations:
|
||||
Jordi Mas [ca]
|
||||
|
||||
3.24.3
|
||||
======
|
||||
* Fix handling of tiled monitors [Jonas; #781723]
|
||||
|
@@ -2179,3 +2179,61 @@ clutter_event_get_mode_group (const ClutterEvent *event)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_pad_event_details:
|
||||
* @event: a pad event
|
||||
* @number: (out) (optional): ring/strip/button number
|
||||
* @mode: (out) (optional): pad mode as per the event
|
||||
* @value: (out) (optional): event axis value
|
||||
*
|
||||
* Returns the details of a pad event.
|
||||
*
|
||||
* Returns: #TRUE if event details could be obtained
|
||||
**/
|
||||
gboolean
|
||||
clutter_event_get_pad_event_details (const ClutterEvent *event,
|
||||
guint *number,
|
||||
guint *mode,
|
||||
gdouble *value)
|
||||
{
|
||||
guint n, m;
|
||||
gdouble v;
|
||||
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
||||
event->type == CLUTTER_PAD_RING ||
|
||||
event->type == CLUTTER_PAD_STRIP, FALSE);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
n = event->pad_button.button;
|
||||
m = event->pad_button.mode;
|
||||
v = 0.0;
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
n = event->pad_ring.ring_number;
|
||||
m = event->pad_ring.mode;
|
||||
v = event->pad_ring.angle;
|
||||
break;
|
||||
case CLUTTER_PAD_STRIP:
|
||||
n = event->pad_strip.strip_number;
|
||||
m = event->pad_strip.mode;
|
||||
v = event->pad_strip.value;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (number)
|
||||
*number = n;
|
||||
if (mode)
|
||||
*mode = m;
|
||||
if (value)
|
||||
*value = v;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -778,6 +778,12 @@ ClutterScrollFinishFlags clutter_event_get_scroll_finish_flags (const Clut
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
guint clutter_event_get_mode_group (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_MUTTER
|
||||
gboolean clutter_event_get_pad_event_details (const ClutterEvent *event,
|
||||
guint *number,
|
||||
guint *mode,
|
||||
gdouble *value);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -2243,10 +2243,15 @@ clutter_input_device_get_device_node (ClutterInputDevice *device)
|
||||
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);
|
||||
g_return_val_if_fail (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_TABLET_DEVICE,
|
||||
|
||||
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;
|
||||
@@ -2256,9 +2261,14 @@ void
|
||||
clutter_input_device_set_mapping_mode (ClutterInputDevice *device,
|
||||
ClutterInputDeviceMapping mapping)
|
||||
{
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE (device));
|
||||
g_return_if_fail (clutter_input_device_get_device_type (device) ==
|
||||
CLUTTER_TABLET_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;
|
||||
|
@@ -971,6 +971,7 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
ClutterEvent *next_event;
|
||||
ClutterInputDevice *device;
|
||||
ClutterInputDevice *next_device;
|
||||
ClutterInputDeviceType device_type;
|
||||
gboolean check_device = FALSE;
|
||||
|
||||
event = l->data;
|
||||
@@ -986,8 +987,16 @@ _clutter_stage_process_queued_events (ClutterStage *stage)
|
||||
if (device != NULL && next_device != NULL)
|
||||
check_device = TRUE;
|
||||
|
||||
/* Skip consecutive motion events coming from the same device */
|
||||
if (priv->throttle_motion_events && next_event != NULL)
|
||||
device_type = clutter_input_device_get_device_type (device);
|
||||
|
||||
/* Skip consecutive motion events coming from the same device,
|
||||
* except those of tablet tools, since users of these events
|
||||
* want no precision loss.
|
||||
*/
|
||||
if (priv->throttle_motion_events && next_event != NULL &&
|
||||
device_type != CLUTTER_TABLET_DEVICE &&
|
||||
device_type != CLUTTER_PEN_DEVICE &&
|
||||
device_type != CLUTTER_ERASER_DEVICE)
|
||||
{
|
||||
if (event->type == CLUTTER_MOTION &&
|
||||
(next_event->type == CLUTTER_MOTION ||
|
||||
|
@@ -163,6 +163,9 @@ clutter_input_device_evdev_update_from_tool (ClutterInputDevice *device,
|
||||
if (libinput_tablet_tool_has_slider (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_SLIDER, -1, 1, 0);
|
||||
|
||||
if (libinput_tablet_tool_has_wheel (evdev_tool->tool))
|
||||
_clutter_input_device_add_axis (device, CLUTTER_INPUT_AXIS_WHEEL, -180, 180, 0);
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (device));
|
||||
}
|
||||
|
||||
|
@@ -66,6 +66,14 @@ static const char *clutter_input_axis_atom_names[] = {
|
||||
|
||||
#define N_AXIS_ATOMS G_N_ELEMENTS (clutter_input_axis_atom_names)
|
||||
|
||||
enum {
|
||||
PAD_AXIS_FIRST = 3, /* First axes are always x/y/pressure, ignored in pads */
|
||||
PAD_AXIS_STRIP1 = PAD_AXIS_FIRST,
|
||||
PAD_AXIS_STRIP2,
|
||||
PAD_AXIS_RING1,
|
||||
PAD_AXIS_RING2,
|
||||
};
|
||||
|
||||
static Atom clutter_input_axis_atoms[N_AXIS_ATOMS] = { 0, };
|
||||
|
||||
static void clutter_event_translator_iface_init (ClutterEventTranslatorIface *iface);
|
||||
@@ -359,6 +367,36 @@ get_device_node_path (ClutterBackendX11 *backend_x11,
|
||||
return node_path;
|
||||
}
|
||||
|
||||
static void
|
||||
get_pad_features (XIDeviceInfo *info,
|
||||
guint *n_rings,
|
||||
guint *n_strips)
|
||||
{
|
||||
gint i, rings = 0, strips = 0;
|
||||
|
||||
for (i = PAD_AXIS_FIRST; i < info->num_classes; i++)
|
||||
{
|
||||
XIValuatorClassInfo *valuator = (XIValuatorClassInfo*) info->classes[i];
|
||||
int axis = valuator->number;
|
||||
|
||||
if (valuator->type != XIValuatorClass)
|
||||
continue;
|
||||
if (valuator->max <= 1)
|
||||
continue;
|
||||
|
||||
/* Ring/strip axes are fixed in pad devices as handled by the
|
||||
* wacom driver. Match those to detect pad features.
|
||||
*/
|
||||
if (axis == PAD_AXIS_STRIP1 || axis == PAD_AXIS_STRIP2)
|
||||
strips++;
|
||||
else if (axis == PAD_AXIS_RING1 || axis == PAD_AXIS_RING2)
|
||||
rings++;
|
||||
}
|
||||
|
||||
*n_rings = rings;
|
||||
*n_strips = strips;
|
||||
}
|
||||
|
||||
static ClutterInputDevice *
|
||||
create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
ClutterBackendX11 *backend_x11,
|
||||
@@ -368,7 +406,7 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
ClutterInputDevice *retval;
|
||||
ClutterInputMode mode;
|
||||
gboolean is_enabled;
|
||||
guint num_touches = 0;
|
||||
guint num_touches = 0, num_rings = 0, num_strips = 0;
|
||||
gchar *vendor_id = NULL, *product_id = NULL, *node_path = NULL;
|
||||
|
||||
if (info->use == XIMasterKeyboard || info->use == XISlaveKeyboard)
|
||||
@@ -436,6 +474,12 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
node_path = get_device_node_path (backend_x11, info);
|
||||
}
|
||||
|
||||
if (source == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
is_enabled = TRUE;
|
||||
get_pad_features (info, &num_rings, &num_strips);
|
||||
}
|
||||
|
||||
retval = g_object_new (CLUTTER_TYPE_INPUT_DEVICE_XI2,
|
||||
"name", info->name,
|
||||
"id", info->deviceid,
|
||||
@@ -448,6 +492,8 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
"vendor-id", vendor_id,
|
||||
"product-id", product_id,
|
||||
"device-node", node_path,
|
||||
"n-rings", num_rings,
|
||||
"n-strips", num_strips,
|
||||
NULL);
|
||||
|
||||
translate_device_classes (backend_x11->xdpy, retval,
|
||||
@@ -847,6 +893,54 @@ translate_axes (ClutterInputDevice *device,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
translate_pad_axis (ClutterInputDevice *device,
|
||||
XIValuatorState *valuators,
|
||||
ClutterEventType *evtype,
|
||||
guint *number,
|
||||
gdouble *value)
|
||||
{
|
||||
double *values;
|
||||
gint i;
|
||||
|
||||
values = valuators->values;
|
||||
|
||||
for (i = PAD_AXIS_FIRST; i < valuators->mask_len * 8; i++)
|
||||
{
|
||||
gdouble val;
|
||||
guint axis_number = 0;
|
||||
|
||||
if (!XIMaskIsSet (valuators->mask, i))
|
||||
continue;
|
||||
|
||||
val = *values++;
|
||||
if (val <= 0)
|
||||
continue;
|
||||
|
||||
_clutter_input_device_translate_axis (device, i, val, value);
|
||||
|
||||
if (i == PAD_AXIS_RING1 || i == PAD_AXIS_RING2)
|
||||
{
|
||||
*evtype = CLUTTER_PAD_RING;
|
||||
(*value) *= 360.0;
|
||||
}
|
||||
else if (i == PAD_AXIS_STRIP1 || i == PAD_AXIS_STRIP2)
|
||||
{
|
||||
*evtype = CLUTTER_PAD_STRIP;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
if (i == PAD_AXIS_STRIP2 || i == PAD_AXIS_RING2)
|
||||
axis_number++;
|
||||
|
||||
*number = axis_number;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
translate_coords (ClutterStageX11 *stage_x11,
|
||||
gdouble event_x,
|
||||
@@ -1025,6 +1119,54 @@ handle_property_event (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
translate_pad_event (ClutterEvent *event,
|
||||
XIDeviceEvent *xev,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
gdouble value;
|
||||
guint number;
|
||||
|
||||
if (!translate_pad_axis (device, &xev->valuators,
|
||||
&event->any.type,
|
||||
&number, &value))
|
||||
return FALSE;
|
||||
|
||||
/* When touching a ring/strip a first XI_Motion event
|
||||
* is generated. Use it to reset the pad state, so
|
||||
* later events actually have a directionality.
|
||||
*/
|
||||
if (xev->evtype == XI_Motion)
|
||||
value = -1;
|
||||
|
||||
if (event->any.type == CLUTTER_PAD_RING)
|
||||
{
|
||||
event->pad_ring.ring_number = number;
|
||||
event->pad_ring.angle = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
event->pad_strip.strip_number = number;
|
||||
event->pad_strip.value = value;
|
||||
}
|
||||
|
||||
event->any.time = xev->time;
|
||||
clutter_event_set_device (event, device);
|
||||
clutter_event_set_source_device (event, device);
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"%s: win:0x%x, device:%d '%s', time:%d "
|
||||
"(value:%f)",
|
||||
event->any.type == CLUTTER_PAD_RING
|
||||
? "pad ring "
|
||||
: "pad strip",
|
||||
(unsigned int) stage_x11->xwin,
|
||||
device->id,
|
||||
device->device_name,
|
||||
event->any.time, value);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static ClutterTranslateReturn
|
||||
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
gpointer native,
|
||||
@@ -1206,15 +1348,23 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
XIAsyncDevice,
|
||||
xev->time);
|
||||
|
||||
/* Ignore 4-7 buttons */
|
||||
if (xev->detail >= 4 && xev->detail <= 7)
|
||||
return CLUTTER_TRANSLATE_REMOVE;
|
||||
event->any.stage = stage;
|
||||
|
||||
event->pad_button.type =
|
||||
if (xev->detail >= 4 && xev->detail <= 7)
|
||||
{
|
||||
retval = CLUTTER_TRANSLATE_REMOVE;
|
||||
|
||||
if (xi_event->evtype == XI_ButtonPress &&
|
||||
translate_pad_event (event, xev, source_device))
|
||||
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
event->any.type =
|
||||
(xi_event->evtype == XI_ButtonPress) ? CLUTTER_PAD_BUTTON_PRESS
|
||||
: CLUTTER_PAD_BUTTON_RELEASE;
|
||||
event->pad_button.time = xev->time;
|
||||
event->pad_button.stage = stage;
|
||||
event->any.time = xev->time;
|
||||
|
||||
/* The 4-7 button range is taken as non-existent on pad devices,
|
||||
* let the buttons above that take over this range.
|
||||
@@ -1224,6 +1374,7 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
|
||||
/* Pad buttons are 0-indexed */
|
||||
event->pad_button.button = xev->detail - 1;
|
||||
clutter_event_set_device (event, device);
|
||||
clutter_event_set_source_device (event, source_device);
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
@@ -1380,6 +1531,15 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
|
||||
if (clutter_input_device_get_device_type (source_device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
event->any.stage = stage;
|
||||
|
||||
if (translate_pad_event (event, xev, source_device))
|
||||
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||
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 &&
|
||||
|
@@ -2,7 +2,7 @@ AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [24])
|
||||
m4_define([mutter_micro_version], [3])
|
||||
m4_define([mutter_micro_version], [4])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
|
126
po/ca.po
126
po/ca.po
@@ -13,16 +13,16 @@ msgstr ""
|
||||
"Project-Id-Version: metacity 2.24\n"
|
||||
"Report-Msgid-Bugs-To: https://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2017-04-28 15:40+0000\n"
|
||||
"PO-Revision-Date: 2016-03-13 14:45+0100\n"
|
||||
"Last-Translator: Gil Forcada <gilforcada@guifi.net>\n"
|
||||
"POT-Creation-Date: 2017-07-07 04:21+0000\n"
|
||||
"PO-Revision-Date: 2017-07-10 02:05+0200\n"
|
||||
"Last-Translator: Jordi Mas <jmas@softcatala.org>\n"
|
||||
"Language-Team: Catalan <tradgnome@softcatala.org>\n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bits\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Gtranslator 2.91.6\n"
|
||||
"X-Generator: Poedit 2.0.1\n"
|
||||
|
||||
#: data/50-mutter-navigation.xml:6
|
||||
msgid "Navigation"
|
||||
@@ -105,10 +105,8 @@ msgid "Switch to previous window of an application"
|
||||
msgstr "Canvia a la finestra anterior d'una aplicació"
|
||||
|
||||
#: data/50-mutter-navigation.xml:76
|
||||
#, fuzzy
|
||||
#| msgid "Switch system controls directly"
|
||||
msgid "Switch system controls"
|
||||
msgstr "Canvia immediatament entre els controls del sistema"
|
||||
msgstr "Canvia els controls del sistema"
|
||||
|
||||
#: data/50-mutter-navigation.xml:81
|
||||
msgid "Switch to previous system control"
|
||||
@@ -279,12 +277,6 @@ msgstr ""
|
||||
"finestres"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:8
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "This key will initiate the \"overlay\", which is a combination window "
|
||||
#| "overview and application launching system. The default is intended to be "
|
||||
#| "the \"Windows key\" on PC hardware. It's expected that this binding "
|
||||
#| "either the default or set to the empty string."
|
||||
msgid ""
|
||||
"This key will initiate the “overlay”, which is a combination window overview "
|
||||
"and application launching system. The default is intended to be the “Windows "
|
||||
@@ -333,11 +325,6 @@ msgid "Workspaces are managed dynamically"
|
||||
msgstr "Els espais de treball es gestionen dinàmicament"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:41
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Determines whether workspaces are managed dynamically or whether there's "
|
||||
#| "a static number of workspaces (determined by the num-workspaces key in "
|
||||
#| "org.gnome.desktop.wm.preferences)."
|
||||
msgid ""
|
||||
"Determines whether workspaces are managed dynamically or whether there’s a "
|
||||
"static number of workspaces (determined by the num-workspaces key in org."
|
||||
@@ -376,11 +363,6 @@ msgid "Delay focus changes until the pointer stops moving"
|
||||
msgstr "Retarda el canvi del focus fins que s'aturi el punter"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:69
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
|
||||
#| "the focus will not be changed immediately when entering a window, but "
|
||||
#| "only after the pointer stops moving."
|
||||
msgid ""
|
||||
"If set to true, and the focus mode is either “sloppy” or “mouse” then the "
|
||||
"focus will not be changed immediately when entering a window, but only after "
|
||||
@@ -395,10 +377,6 @@ msgid "Draggable border width"
|
||||
msgstr "Amplada del contorn arrossegable"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:80
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The amount of total draggable borders. If the theme's visible borders are "
|
||||
#| "not enough, invisible borders will be added to meet this value."
|
||||
msgid ""
|
||||
"The amount of total draggable borders. If the theme’s visible borders are "
|
||||
"not enough, invisible borders will be added to meet this value."
|
||||
@@ -433,11 +411,31 @@ msgstr ""
|
||||
"Si és «true» (cert), les finestres noves seran posicionades al centre de la "
|
||||
"pantalla activa del monitor."
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:120
|
||||
#: data/org.gnome.mutter.gschema.xml.in:107
|
||||
msgid "Enable experimental features"
|
||||
msgstr "Habilita les funcionalitats experimentals"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:108
|
||||
msgid ""
|
||||
"To enable experimental features, add the feature keyword to the list. "
|
||||
"Whether the feature requires restarting the compositor depends on the given "
|
||||
"feature. Any experimental feature is not required to still be available, or "
|
||||
"configurable. Don’t expect adding anything in this setting to be future "
|
||||
"proof. Currently possible keywords: • “monitor-config-manager” — use the new "
|
||||
"monitor configuration system, aimed to replace the old one. This enables a "
|
||||
"higher level configuration API to be used by configuration applications, as "
|
||||
"well as the ability to configure per logical monitor scale. • “scale-monitor-"
|
||||
"framebuffer” — makes mutter default to layout logical monitors in a logical "
|
||||
"pixel coordinate space, while scaling monitor framebuffers instead of window "
|
||||
"content, to manage HiDPI monitors. Does not require a restart. Also enabling "
|
||||
"“monitor-config-manager” is required for this feature to be enabled."
|
||||
msgstr ""
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:151
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "Selecció de finestra entre les emergents d'una pestanya"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:125
|
||||
#: data/org.gnome.mutter.gschema.xml.in:156
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Cancel·lació de les finestres emergents a les pestanyes"
|
||||
|
||||
@@ -492,7 +490,7 @@ msgstr "Canvia al terminal virtual 12"
|
||||
#. TRANSLATORS: This string refers to a button that switches between
|
||||
#. * different modes.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:1848
|
||||
#: src/backends/meta-input-settings.c:1871
|
||||
#, c-format
|
||||
msgid "Mode Switch (Group %d)"
|
||||
msgstr "Mode de commutació (grup %d)"
|
||||
@@ -500,37 +498,37 @@ msgstr "Mode de commutació (grup %d)"
|
||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
#. * mapping through the available outputs.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:1870
|
||||
#: src/backends/meta-input-settings.c:1893
|
||||
msgid "Switch monitor"
|
||||
msgstr "Commuta el monitor"
|
||||
|
||||
#: src/backends/meta-input-settings.c:1872
|
||||
#: src/backends/meta-input-settings.c:1895
|
||||
msgid "Show on-screen help"
|
||||
msgstr "Mostra l'ajuda en pantalla"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:630
|
||||
#: src/backends/meta-monitor-manager.c:879
|
||||
msgid "Built-in display"
|
||||
msgstr "Pantalla integrada"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:653
|
||||
#: src/backends/meta-monitor-manager.c:902
|
||||
msgid "Unknown"
|
||||
msgstr "Desconeguda"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:655
|
||||
#: src/backends/meta-monitor-manager.c:904
|
||||
msgid "Unknown Display"
|
||||
msgstr "Pantalla desconeguda"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: src/backends/meta-monitor-manager.c:663
|
||||
#: src/backends/meta-monitor-manager.c:912
|
||||
#, c-format
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: src/compositor/compositor.c:474
|
||||
#: src/compositor/compositor.c:476
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display “%s”."
|
||||
@@ -542,32 +540,6 @@ msgstr ""
|
||||
msgid "Bell event"
|
||||
msgstr "Esdeveniment de campana"
|
||||
|
||||
#. Translators: %s is a window title
|
||||
#: src/core/delete.c:127
|
||||
#, c-format
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "«%s» no està responent."
|
||||
|
||||
#: src/core/delete.c:129
|
||||
msgid "Application is not responding."
|
||||
msgstr "L'aplicació no està responent."
|
||||
|
||||
#: src/core/delete.c:134
|
||||
msgid ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
msgstr ""
|
||||
"Podeu esperar un moment perquè continuï o podeu forçar-ne la sortida "
|
||||
"completa."
|
||||
|
||||
#: src/core/delete.c:141
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Força'n la sortida"
|
||||
|
||||
#: src/core/delete.c:141
|
||||
msgid "_Wait"
|
||||
msgstr "_Espera"
|
||||
|
||||
#: src/core/display.c:608
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display “%s”\n"
|
||||
@@ -615,6 +587,32 @@ msgstr "Funciona com a compositor imbricat"
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Funciona com a servidor de pantalla completa, en comptes d'imbricat"
|
||||
|
||||
#. Translators: %s is a window title
|
||||
#: src/core/meta-close-dialog-default.c:147
|
||||
#, c-format
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "«%s» no està responent."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:149
|
||||
msgid "Application is not responding."
|
||||
msgstr "L'aplicació no està responent."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:154
|
||||
msgid ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
msgstr ""
|
||||
"Podeu esperar un moment perquè continuï o podeu forçar-ne la sortida "
|
||||
"completa."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:161
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Força'n la sortida"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:161
|
||||
msgid "_Wait"
|
||||
msgstr "_Espera"
|
||||
|
||||
#: src/core/mutter.c:39
|
||||
#, c-format
|
||||
msgid ""
|
||||
|
@@ -140,11 +140,12 @@ gboolean meta_input_settings_is_pad_button_grabbed (MetaIn
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
||||
gboolean meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
const ClutterPadButtonEvent *event);
|
||||
gchar * meta_input_settings_get_pad_button_action_label (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);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice * meta_input_settings_get_tablet_wacom_device (MetaInputSettings *settings,
|
||||
|
@@ -53,9 +53,11 @@ struct _DeviceMappingInfo
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
guint changed_id;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
guint *group_modes;
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsPrivate
|
||||
@@ -79,6 +81,14 @@ struct _MetaInputSettingsPrivate
|
||||
#endif
|
||||
|
||||
GHashTable *two_finger_devices;
|
||||
|
||||
/* Pad ring/strip emission */
|
||||
struct {
|
||||
ClutterInputDevice *pad;
|
||||
MetaPadActionType action;
|
||||
guint number;
|
||||
gdouble value;
|
||||
} last_pad_action_info;
|
||||
};
|
||||
|
||||
typedef void (*ConfigBoolFunc) (MetaInputSettings *input_settings,
|
||||
@@ -91,6 +101,14 @@ typedef void (*ConfigUintFunc) (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
guint value);
|
||||
|
||||
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;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettings, meta_input_settings, G_TYPE_OBJECT)
|
||||
|
||||
static GSList *
|
||||
@@ -863,7 +881,7 @@ update_device_display (MetaInputSettings *input_settings,
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
|
||||
/* If mapping is relative, the device can move on all displays */
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE ||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE ||
|
||||
clutter_input_device_get_mapping_mode (device) ==
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
||||
logical_monitor = meta_input_settings_find_logical_monitor (input_settings,
|
||||
@@ -1075,10 +1093,15 @@ static void
|
||||
apply_mappable_device_settings (MetaInputSettings *input_settings,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
update_device_display (input_settings, info->settings, info->device);
|
||||
ClutterInputDeviceType device_type;
|
||||
|
||||
if (clutter_input_device_get_device_type (info->device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (info->device) == CLUTTER_PAD_DEVICE)
|
||||
update_device_display (input_settings, info->settings, info->device);
|
||||
device_type = clutter_input_device_get_device_type (info->device);
|
||||
|
||||
if (device_type == CLUTTER_TABLET_DEVICE ||
|
||||
device_type == CLUTTER_PEN_DEVICE ||
|
||||
device_type == CLUTTER_ERASER_DEVICE ||
|
||||
device_type == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
update_tablet_mapping (input_settings, info->settings, info->device);
|
||||
update_tablet_area (input_settings, info->settings, info->device);
|
||||
@@ -1161,20 +1184,58 @@ lookup_tool_settings (ClutterInputDeviceTool *tool,
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_pad_button_settings (ClutterInputDevice *device,
|
||||
guint button)
|
||||
lookup_pad_action_settings (ClutterInputDevice *device,
|
||||
MetaPadActionType action,
|
||||
guint number,
|
||||
MetaPadDirection direction,
|
||||
gint mode)
|
||||
{
|
||||
const gchar *vendor, *product;
|
||||
const gchar *vendor, *product, *action_type, *detail_type = NULL;
|
||||
GSettings *settings;
|
||||
gchar *path;
|
||||
GString *path;
|
||||
gchar action_label;
|
||||
|
||||
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/button%c/",
|
||||
vendor, product, 'A' + button);
|
||||
|
||||
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);
|
||||
g_free (path);
|
||||
path->str);
|
||||
g_string_free (path, TRUE);
|
||||
|
||||
return settings;
|
||||
}
|
||||
@@ -1203,7 +1264,9 @@ device_mapping_info_free (DeviceMappingInfo *info)
|
||||
if (info->wacom_device)
|
||||
libwacom_destroy (info->wacom_device);
|
||||
#endif
|
||||
g_signal_handler_disconnect (info->settings, info->changed_id);
|
||||
g_object_unref (info->settings);
|
||||
g_free (info->group_modes);
|
||||
g_slice_free (DeviceMappingInfo, info);
|
||||
}
|
||||
|
||||
@@ -1247,8 +1310,15 @@ check_add_mappable_device (MetaInputSettings *input_settings,
|
||||
}
|
||||
#endif
|
||||
|
||||
g_signal_connect (settings, "changed",
|
||||
G_CALLBACK (mapped_device_changed_cb), info);
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
info->group_modes =
|
||||
g_new0 (guint, clutter_input_device_get_n_mode_groups (device));
|
||||
}
|
||||
|
||||
info->changed_id = g_signal_connect (settings, "changed",
|
||||
G_CALLBACK (mapped_device_changed_cb),
|
||||
info);
|
||||
|
||||
g_hash_table_insert (priv->mappable_devices, device, info);
|
||||
|
||||
@@ -1604,7 +1674,8 @@ meta_input_settings_get_pad_button_action (MetaInputSettings *input_settings,
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (pad),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
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);
|
||||
|
||||
@@ -1753,24 +1824,20 @@ emulate_modifiers (ClutterVirtualInputDevice *device,
|
||||
|
||||
static void
|
||||
meta_input_settings_emulate_keybinding (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button,
|
||||
const gchar *accel,
|
||||
gboolean is_press)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterKeyState state;
|
||||
GSettings *settings;
|
||||
guint key, mods;
|
||||
gchar *accel;
|
||||
|
||||
if (!accel || !*accel)
|
||||
return;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
g_object_unref (settings);
|
||||
|
||||
/* FIXME: This is appalling */
|
||||
gtk_accelerator_parse (accel, &key, &mods);
|
||||
g_free (accel);
|
||||
|
||||
if (!priv->virtual_pad_keyboard)
|
||||
{
|
||||
@@ -1807,20 +1874,21 @@ meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
const ClutterPadButtonEvent *event)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
ClutterInputDevice *pad;
|
||||
gint button, group, mode;
|
||||
gboolean is_press;
|
||||
GSettings *settings;
|
||||
gchar *accel;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), FALSE);
|
||||
g_return_val_if_fail (event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE, FALSE);
|
||||
|
||||
pad = clutter_event_get_source_device ((ClutterEvent *) event);
|
||||
button = event->button;
|
||||
mode = event->mode;
|
||||
group = clutter_input_device_get_mode_switch_button_group (pad, button);
|
||||
@@ -1830,18 +1898,19 @@ meta_input_settings_handle_pad_button (MetaInputSettings *input_settin
|
||||
{
|
||||
guint n_modes = clutter_input_device_get_group_n_modes (pad, group);
|
||||
const gchar *pretty_name = NULL;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, pad);
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (info && info->wacom_device)
|
||||
pretty_name = libwacom_get_name (info->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_input_settings_get_pad_button_action (input_settings, pad, button);
|
||||
@@ -1857,8 +1926,12 @@ meta_input_settings_handle_pad_button (MetaInputSettings *input_settin
|
||||
meta_display_request_pad_osd (meta_get_display (), pad, FALSE);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING:
|
||||
meta_input_settings_emulate_keybinding (input_settings, pad,
|
||||
button, is_press);
|
||||
settings = lookup_pad_action_settings (pad, META_PAD_ACTION_BUTTON,
|
||||
button, META_PAD_DIRECTION_NONE, -1);
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
meta_input_settings_emulate_keybinding (input_settings, accel, is_press);
|
||||
g_object_unref (settings);
|
||||
g_free (accel);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
@@ -1866,10 +1939,189 @@ meta_input_settings_handle_pad_button (MetaInputSettings *input_settin
|
||||
}
|
||||
}
|
||||
|
||||
gchar *
|
||||
meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
static gboolean
|
||||
meta_input_settings_handle_pad_action (MetaInputSettings *input_settings,
|
||||
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_input_settings_emulate_keybinding (input_settings, accel, TRUE);
|
||||
meta_input_settings_emulate_keybinding (input_settings, accel, FALSE);
|
||||
handled = TRUE;
|
||||
}
|
||||
|
||||
g_object_unref (settings);
|
||||
g_free (accel);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_input_settings_get_pad_action_direction (MetaInputSettings *input_settings,
|
||||
const ClutterEvent *event,
|
||||
MetaPadDirection *direction)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterInputDevice *pad = clutter_event_get_device (event);
|
||||
MetaPadActionType pad_action;
|
||||
gboolean has_direction = FALSE;
|
||||
MetaPadDirection inc_dir, dec_dir;
|
||||
guint number;
|
||||
gdouble value;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
*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 (priv->last_pad_action_info.pad == pad &&
|
||||
priv->last_pad_action_info.action == pad_action &&
|
||||
priv->last_pad_action_info.number == number &&
|
||||
value >= 0 && priv->last_pad_action_info.value >= 0)
|
||||
{
|
||||
*direction = (value - priv->last_pad_action_info.value) > 0 ?
|
||||
inc_dir : dec_dir;
|
||||
has_direction = TRUE;
|
||||
}
|
||||
|
||||
priv->last_pad_action_info.pad = pad;
|
||||
priv->last_pad_action_info.action = pad_action;
|
||||
priv->last_pad_action_info.number = number;
|
||||
priv->last_pad_action_info.value = value;
|
||||
return has_direction;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_input_settings_handle_pad_event (MetaInputSettings *input_settings,
|
||||
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_input_settings_handle_pad_button (input_settings, pad,
|
||||
&event->pad_button);
|
||||
case CLUTTER_PAD_RING:
|
||||
if (!meta_input_settings_get_pad_action_direction (input_settings,
|
||||
event, &direction))
|
||||
return FALSE;
|
||||
return meta_input_settings_handle_pad_action (input_settings, pad,
|
||||
META_PAD_ACTION_RING,
|
||||
event->pad_ring.ring_number,
|
||||
direction,
|
||||
event->pad_ring.mode);
|
||||
case CLUTTER_PAD_STRIP:
|
||||
if (!meta_input_settings_get_pad_action_direction (input_settings,
|
||||
event, &direction))
|
||||
return FALSE;
|
||||
return meta_input_settings_handle_pad_action (input_settings, 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_input_settings_get_ring_label (MetaInputSettings *settings,
|
||||
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_input_settings_get_strip_label (MetaInputSettings *settings,
|
||||
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_input_settings_get_button_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
GDesktopPadButtonAction action;
|
||||
gint group;
|
||||
@@ -1898,7 +2150,8 @@ meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_setti
|
||||
GSettings *settings;
|
||||
gchar *accel;
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
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);
|
||||
|
||||
@@ -1916,3 +2169,55 @@ meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_setti
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static guint
|
||||
get_current_pad_mode (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint number)
|
||||
{
|
||||
MetaInputSettingsPrivate *priv;
|
||||
DeviceMappingInfo *info;
|
||||
guint group = 0, n_groups;
|
||||
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
info = g_hash_table_lookup (priv->mappable_devices, 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_input_settings_get_pad_action_label (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
MetaPadActionType action_type,
|
||||
guint number)
|
||||
{
|
||||
guint mode;
|
||||
|
||||
switch (action_type)
|
||||
{
|
||||
case META_PAD_ACTION_BUTTON:
|
||||
return meta_input_settings_get_button_label (input_settings, pad, number);
|
||||
case META_PAD_ACTION_RING:
|
||||
mode = get_current_pad_mode (input_settings, pad, action_type, number);
|
||||
return meta_input_settings_get_ring_label (input_settings, pad,
|
||||
number, mode);
|
||||
case META_PAD_ACTION_STRIP:
|
||||
mode = get_current_pad_mode (input_settings, pad, action_type, number);
|
||||
return meta_input_settings_get_strip_label (input_settings, pad,
|
||||
number, mode);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@@ -147,19 +147,6 @@ meta_monitor_manager_rebuild_logical_monitors (MetaMonitorManager *manager,
|
||||
primary_logical_monitor);
|
||||
}
|
||||
|
||||
static void
|
||||
derive_monitor_layout (MetaMonitor *monitor,
|
||||
MetaRectangle *layout)
|
||||
{
|
||||
MetaOutput *main_output;
|
||||
|
||||
main_output = meta_monitor_get_main_output (monitor);
|
||||
layout->x = main_output->crtc->rect.x;
|
||||
layout->y = main_output->crtc->rect.y;
|
||||
|
||||
meta_monitor_derive_dimensions (monitor, &layout->width, &layout->height);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manager)
|
||||
{
|
||||
@@ -179,7 +166,7 @@ meta_monitor_manager_rebuild_logical_monitors_derived (MetaMonitorManager *manag
|
||||
if (!meta_monitor_is_active (monitor))
|
||||
continue;
|
||||
|
||||
derive_monitor_layout (monitor, &layout);
|
||||
meta_monitor_derive_layout (monitor, &layout);
|
||||
logical_monitor = logical_monitor_from_layout (manager, logical_monitors,
|
||||
&layout);
|
||||
if (logical_monitor)
|
||||
|
@@ -232,11 +232,10 @@ meta_monitor_get_current_resolution (MetaMonitor *monitor,
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_derive_dimensions (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height)
|
||||
meta_monitor_derive_layout (MetaMonitor *monitor,
|
||||
MetaRectangle *layout)
|
||||
{
|
||||
META_MONITOR_GET_CLASS (monitor)->derive_dimensions (monitor, width, height);
|
||||
META_MONITOR_GET_CLASS (monitor)->derive_layout (monitor, layout);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -382,15 +381,18 @@ meta_monitor_normal_get_main_output (MetaMonitor *monitor)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_normal_derive_dimensions (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height)
|
||||
meta_monitor_normal_derive_layout (MetaMonitor *monitor,
|
||||
MetaRectangle *layout)
|
||||
{
|
||||
MetaOutput *output;
|
||||
|
||||
output = meta_monitor_get_main_output (monitor);
|
||||
*width = output->crtc->rect.width;
|
||||
*height = output->crtc->rect.height;
|
||||
*layout = (MetaRectangle) {
|
||||
.x = output->crtc->rect.x,
|
||||
.y = output->crtc->rect.y,
|
||||
.width = output->crtc->rect.width,
|
||||
.height = output->crtc->rect.height
|
||||
};
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -421,7 +423,7 @@ meta_monitor_normal_class_init (MetaMonitorNormalClass *klass)
|
||||
MetaMonitorClass *monitor_class = META_MONITOR_CLASS (klass);
|
||||
|
||||
monitor_class->get_main_output = meta_monitor_normal_get_main_output;
|
||||
monitor_class->derive_dimensions = meta_monitor_normal_derive_dimensions;
|
||||
monitor_class->derive_layout = meta_monitor_normal_derive_layout;
|
||||
monitor_class->get_suggested_position = meta_monitor_normal_get_suggested_position;
|
||||
}
|
||||
|
||||
@@ -958,9 +960,8 @@ meta_monitor_tiled_get_main_output (MetaMonitor *monitor)
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_tiled_derive_dimensions (MetaMonitor *monitor,
|
||||
int *out_width,
|
||||
int *out_height)
|
||||
meta_monitor_derived_derive_layout (MetaMonitor *monitor,
|
||||
MetaRectangle *layout)
|
||||
{
|
||||
MetaMonitorPrivate *monitor_priv =
|
||||
meta_monitor_get_instance_private (monitor);
|
||||
@@ -984,8 +985,12 @@ meta_monitor_tiled_derive_dimensions (MetaMonitor *monitor,
|
||||
max_y = MAX (output->crtc->rect.y + output->crtc->rect.height, max_y);
|
||||
}
|
||||
|
||||
*out_width = max_x - min_x;
|
||||
*out_height = max_y - min_y;
|
||||
*layout = (MetaRectangle) {
|
||||
.x = min_x,
|
||||
.y = min_y,
|
||||
.width = max_x - min_x,
|
||||
.height = max_y - min_y
|
||||
};
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1021,7 +1026,7 @@ meta_monitor_tiled_class_init (MetaMonitorTiledClass *klass)
|
||||
object_class->finalize = meta_monitor_tiled_finalize;
|
||||
|
||||
monitor_class->get_main_output = meta_monitor_tiled_get_main_output;
|
||||
monitor_class->derive_dimensions = meta_monitor_tiled_derive_dimensions;
|
||||
monitor_class->derive_layout = meta_monitor_derived_derive_layout;
|
||||
monitor_class->get_suggested_position = meta_monitor_tiled_get_suggested_position;
|
||||
}
|
||||
|
||||
|
@@ -65,9 +65,8 @@ struct _MetaMonitorClass
|
||||
GObjectClass parent_class;
|
||||
|
||||
MetaOutput * (* get_main_output) (MetaMonitor *monitor);
|
||||
void (* derive_dimensions) (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height);
|
||||
void (* derive_layout) (MetaMonitor *monitor,
|
||||
MetaRectangle *layout);
|
||||
gboolean (* get_suggested_position) (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height);
|
||||
@@ -107,9 +106,8 @@ void meta_monitor_get_current_resolution (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
void meta_monitor_derive_dimensions (MetaMonitor *monitor,
|
||||
int *width,
|
||||
int *height);
|
||||
void meta_monitor_derive_layout (MetaMonitor *monitor,
|
||||
MetaRectangle *layout);
|
||||
|
||||
void meta_monitor_get_physical_dimensions (MetaMonitor *monitor,
|
||||
int *width_mm,
|
||||
|
@@ -188,9 +188,22 @@ on_evdev_device_open (const char *path,
|
||||
/* Allow readonly access to sysfs */
|
||||
if (g_str_has_prefix (path, "/sys/"))
|
||||
{
|
||||
fd = open (path, flags);
|
||||
if (fd >= 0)
|
||||
g_hash_table_add (self->sysfs_fds, GINT_TO_POINTER (fd));
|
||||
do
|
||||
{
|
||||
fd = open (path, flags);
|
||||
}
|
||||
while (fd < 0 && errno == EINTR);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_FILE_ERROR,
|
||||
g_file_error_from_errno (errno),
|
||||
"Could not open /sys file: %s: %m", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_hash_table_add (self->sysfs_fds, GINT_TO_POINTER (fd));
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@@ -551,10 +551,21 @@ 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
|
||||
device_query_area (ClutterInputDevice *device,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
@@ -580,9 +591,15 @@ device_query_area (ClutterInputDevice *device,
|
||||
if (valuator->type != XIValuatorClass)
|
||||
continue;
|
||||
if (valuator->label == abs_x)
|
||||
*width = valuator->max - valuator->min;
|
||||
{
|
||||
*x = valuator->min;
|
||||
*width = valuator->max - valuator->min;
|
||||
}
|
||||
else if (valuator->label == abs_y)
|
||||
*height = valuator->max - valuator->min;
|
||||
{
|
||||
*y = valuator->min;
|
||||
*height = valuator->max - valuator->min;
|
||||
}
|
||||
}
|
||||
|
||||
XIFreeDeviceInfo (info);
|
||||
@@ -606,15 +623,15 @@ meta_input_settings_x11_set_tablet_area (MetaInputSettings *settings,
|
||||
gdouble padding_top,
|
||||
gdouble padding_bottom)
|
||||
{
|
||||
gint32 width, height, area[4] = { 0 };
|
||||
gint32 x, y, width, height, area[4] = { 0 };
|
||||
|
||||
if (!device_query_area (device, &width, &height))
|
||||
if (!device_query_area (device, &x, &y, &width, &height))
|
||||
return;
|
||||
|
||||
area[0] = width * padding_left;
|
||||
area[1] = height * padding_top;
|
||||
area[2] = width - (width * padding_right);
|
||||
area[3] = height - (height * padding_bottom);
|
||||
area[0] = (width * padding_left) + x;
|
||||
area[1] = (height * padding_top) + y;
|
||||
area[2] = width - (width * padding_right) + x;
|
||||
area[3] = height - (height * padding_bottom) + y;
|
||||
update_tablet_area (settings, device, area);
|
||||
}
|
||||
|
||||
@@ -624,9 +641,9 @@ meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
MetaLogicalMonitor *logical_monitor,
|
||||
gboolean keep_aspect)
|
||||
{
|
||||
gint32 width, height, dev_width, dev_height, area[4] = { 0 };
|
||||
gint32 width, height, dev_x, dev_y, dev_width, dev_height, area[4] = { 0 };
|
||||
|
||||
if (!device_query_area (device, &dev_width, &dev_height))
|
||||
if (!device_query_area (device, &dev_x, &dev_y, &dev_width, &dev_height))
|
||||
return;
|
||||
|
||||
if (keep_aspect)
|
||||
@@ -658,8 +675,10 @@ meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
dev_height = dev_width / aspect_ratio;
|
||||
}
|
||||
|
||||
area[2] = dev_width;
|
||||
area[3] = dev_height;
|
||||
area[0] = dev_x;
|
||||
area[1] = dev_y;
|
||||
area[2] = dev_width + dev_x;
|
||||
area[3] = dev_height + dev_y;
|
||||
update_tablet_area (settings, device, area);
|
||||
}
|
||||
|
||||
|
@@ -3160,18 +3160,14 @@ 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 */
|
||||
if (action_type == META_PAD_ACTION_BUTTON)
|
||||
{
|
||||
MetaInputSettings *settings;
|
||||
|
||||
settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
label = meta_input_settings_get_pad_button_action_label (settings, pad, action_number);
|
||||
if (label)
|
||||
return label;
|
||||
}
|
||||
settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
label = meta_input_settings_get_pad_action_label (settings, pad, action_type, action_number);
|
||||
if (label)
|
||||
return label;
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
/* Second, if this wayland, lookup the actions set by the clients */
|
||||
|
@@ -220,10 +220,12 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
|
||||
if (!display->current_pad_osd &&
|
||||
(event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE))
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE ||
|
||||
event->type == CLUTTER_PAD_RING ||
|
||||
event->type == CLUTTER_PAD_STRIP))
|
||||
{
|
||||
if (meta_input_settings_handle_pad_button (meta_backend_get_input_settings (backend),
|
||||
&event->pad_button))
|
||||
if (meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend),
|
||||
event))
|
||||
{
|
||||
bypass_wayland = bypass_clutter = TRUE;
|
||||
goto out;
|
||||
|
@@ -1260,7 +1260,6 @@ update_num_workspaces (MetaScreen *screen,
|
||||
{
|
||||
MetaWorkspace *w = l->data;
|
||||
|
||||
g_assert (w->windows == NULL);
|
||||
meta_workspace_remove (w);
|
||||
}
|
||||
|
||||
|
@@ -530,7 +530,8 @@ struct _MetaWindowClass
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon);
|
||||
uint32_t (*get_client_pid) (MetaWindow *window);
|
||||
void (*update_main_monitor) (MetaWindow *window);
|
||||
void (*update_main_monitor) (MetaWindow *window,
|
||||
gboolean user_op);
|
||||
void (*main_monitor_changed) (MetaWindow *window,
|
||||
const MetaLogicalMonitor *old);
|
||||
};
|
||||
|
@@ -3592,7 +3592,7 @@ meta_window_update_monitor (MetaWindow *window,
|
||||
const MetaLogicalMonitor *old;
|
||||
|
||||
old = window->monitor;
|
||||
META_WINDOW_GET_CLASS (window)->update_main_monitor (window);
|
||||
META_WINDOW_GET_CLASS (window)->update_main_monitor (window, user_op);
|
||||
if (old != window->monitor)
|
||||
{
|
||||
meta_window_on_all_workspaces_changed (window);
|
||||
@@ -5581,6 +5581,60 @@ update_move_timeout (gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_move_maybe_tile (MetaWindow *window,
|
||||
int shake_threshold,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
MetaRectangle work_area;
|
||||
|
||||
/* For side-by-side tiling we are interested in the inside vertical
|
||||
* edges of the work area of the monitor where the pointer is located,
|
||||
* and in the outside top edge for maximized tiling.
|
||||
*
|
||||
* For maximized tiling we use the outside edge instead of the
|
||||
* inside edge, because we don't want to force users to maximize
|
||||
* windows they are placing near the top of their screens.
|
||||
*
|
||||
* The "current" idea of meta_window_get_work_area_current_monitor() and
|
||||
* meta_screen_get_current_monitor() is slightly different: the former
|
||||
* refers to the monitor which contains the largest part of the window,
|
||||
* the latter to the one where the pointer is located.
|
||||
*/
|
||||
logical_monitor =
|
||||
meta_monitor_manager_get_logical_monitor_at (monitor_manager, x, y);
|
||||
if (!logical_monitor)
|
||||
return;
|
||||
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
logical_monitor->number,
|
||||
&work_area);
|
||||
|
||||
/* Check if the cursor is in a position which triggers tiling
|
||||
* and set tile_mode accordingly.
|
||||
*/
|
||||
if (meta_window_can_tile_side_by_side (window) &&
|
||||
x >= logical_monitor->rect.x && x < (work_area.x + shake_threshold))
|
||||
window->tile_mode = META_TILE_LEFT;
|
||||
else if (meta_window_can_tile_side_by_side (window) &&
|
||||
x >= work_area.x + work_area.width - shake_threshold &&
|
||||
x < (logical_monitor->rect.x + logical_monitor->rect.width))
|
||||
window->tile_mode = META_TILE_RIGHT;
|
||||
else if (meta_window_can_tile_maximized (window) &&
|
||||
y >= logical_monitor->rect.y && y <= work_area.y)
|
||||
window->tile_mode = META_TILE_MAXIMIZED;
|
||||
else
|
||||
window->tile_mode = META_TILE_NONE;
|
||||
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
window->tile_monitor_number = logical_monitor->number;
|
||||
}
|
||||
|
||||
static void
|
||||
update_move (MetaWindow *window,
|
||||
gboolean snap,
|
||||
@@ -5636,49 +5690,7 @@ update_move (MetaWindow *window,
|
||||
!META_WINDOW_MAXIMIZED (window) &&
|
||||
!META_WINDOW_TILED_SIDE_BY_SIDE (window))
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
const MetaLogicalMonitor *monitor;
|
||||
MetaRectangle work_area;
|
||||
|
||||
/* For side-by-side tiling we are interested in the inside vertical
|
||||
* edges of the work area of the monitor where the pointer is located,
|
||||
* and in the outside top edge for maximized tiling.
|
||||
*
|
||||
* For maximized tiling we use the outside edge instead of the
|
||||
* inside edge, because we don't want to force users to maximize
|
||||
* windows they are placing near the top of their screens.
|
||||
*
|
||||
* The "current" idea of meta_window_get_work_area_current_monitor() and
|
||||
* meta_screen_get_current_monitor() is slightly different: the former
|
||||
* refers to the monitor which contains the largest part of the window,
|
||||
* the latter to the one where the pointer is located.
|
||||
*/
|
||||
monitor = meta_monitor_manager_get_logical_monitor_at (monitor_manager,
|
||||
x, y);
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
monitor->number,
|
||||
&work_area);
|
||||
|
||||
/* Check if the cursor is in a position which triggers tiling
|
||||
* and set tile_mode accordingly.
|
||||
*/
|
||||
if (meta_window_can_tile_side_by_side (window) &&
|
||||
x >= monitor->rect.x && x < (work_area.x + shake_threshold))
|
||||
window->tile_mode = META_TILE_LEFT;
|
||||
else if (meta_window_can_tile_side_by_side (window) &&
|
||||
x >= work_area.x + work_area.width - shake_threshold &&
|
||||
x < (monitor->rect.x + monitor->rect.width))
|
||||
window->tile_mode = META_TILE_RIGHT;
|
||||
else if (meta_window_can_tile_maximized (window) &&
|
||||
y >= monitor->rect.y && y <= work_area.y)
|
||||
window->tile_mode = META_TILE_MAXIMIZED;
|
||||
else
|
||||
window->tile_mode = META_TILE_NONE;
|
||||
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
window->tile_monitor_number = monitor->number;
|
||||
update_move_maybe_tile (window, shake_threshold, x, y);
|
||||
}
|
||||
|
||||
/* shake loose (unmaximize) maximized or tiled window if dragged beyond
|
||||
|
@@ -1433,6 +1433,153 @@ meta_test_monitor_tiled_non_preferred_linear_config (void)
|
||||
check_monitor_configuration (&test_case);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_monitor_tiled_non_main_origin_linear_config (void)
|
||||
{
|
||||
MonitorTestCase test_case = {
|
||||
.setup = {
|
||||
.modes = {
|
||||
{
|
||||
.width = 400,
|
||||
.height = 600,
|
||||
.refresh_rate = 60.0
|
||||
},
|
||||
{
|
||||
.width = 800,
|
||||
.height = 600,
|
||||
.refresh_rate = 30.0
|
||||
},
|
||||
},
|
||||
.n_modes = 2,
|
||||
.outputs = {
|
||||
{
|
||||
.crtc = -1,
|
||||
.modes = { 0, 1 },
|
||||
.n_modes = 2,
|
||||
.preferred_mode = 0,
|
||||
.possible_crtcs = { 0 },
|
||||
.n_possible_crtcs = 1,
|
||||
.width_mm = 222,
|
||||
.height_mm = 125,
|
||||
.tile_info = {
|
||||
.group_id = 1,
|
||||
.max_h_tiles = 2,
|
||||
.max_v_tiles = 1,
|
||||
.loc_h_tile = 1,
|
||||
.loc_v_tile = 0,
|
||||
.tile_w = 400,
|
||||
.tile_h = 600
|
||||
}
|
||||
},
|
||||
{
|
||||
.crtc = -1,
|
||||
.modes = { 0 },
|
||||
.n_modes = 1,
|
||||
.preferred_mode = 0,
|
||||
.possible_crtcs = { 1 },
|
||||
.n_possible_crtcs = 1,
|
||||
.width_mm = 222,
|
||||
.height_mm = 125,
|
||||
.tile_info = {
|
||||
.group_id = 1,
|
||||
.max_h_tiles = 2,
|
||||
.max_v_tiles = 1,
|
||||
.loc_h_tile = 0,
|
||||
.loc_v_tile = 0,
|
||||
.tile_w = 400,
|
||||
.tile_h = 600
|
||||
}
|
||||
}
|
||||
},
|
||||
.n_outputs = 2,
|
||||
.crtcs = {
|
||||
{
|
||||
.current_mode = -1
|
||||
},
|
||||
{
|
||||
.current_mode = -1
|
||||
}
|
||||
},
|
||||
.n_crtcs = 2
|
||||
},
|
||||
|
||||
.expect = {
|
||||
.monitors = {
|
||||
{
|
||||
.outputs = { 0, 1 },
|
||||
.n_outputs = 2,
|
||||
.modes = {
|
||||
{
|
||||
.width = 800,
|
||||
.height = 600,
|
||||
.crtc_modes = {
|
||||
{
|
||||
.output = 0,
|
||||
.crtc_mode = 0,
|
||||
.x = 400,
|
||||
.y = 0
|
||||
},
|
||||
{
|
||||
.output = 1,
|
||||
.crtc_mode = 0,
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
.width = 800,
|
||||
.height = 600,
|
||||
.crtc_modes = {
|
||||
{
|
||||
.output = 0,
|
||||
.crtc_mode = 1
|
||||
},
|
||||
{
|
||||
.output = 1,
|
||||
.crtc_mode = -1,
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
.n_modes = 2,
|
||||
.current_mode = 0,
|
||||
.width_mm = 222,
|
||||
.height_mm = 125,
|
||||
}
|
||||
},
|
||||
.n_monitors = 1,
|
||||
.logical_monitors = {
|
||||
{
|
||||
.monitors = { 0 },
|
||||
.n_monitors = 1,
|
||||
.layout = { .x = 0, .y = 0, .width = 800, .height = 600 },
|
||||
.scale = 1
|
||||
},
|
||||
},
|
||||
.n_logical_monitors = 1,
|
||||
.primary_logical_monitor = 0,
|
||||
.n_outputs = 2,
|
||||
.crtcs = {
|
||||
{
|
||||
.current_mode = 0,
|
||||
},
|
||||
{
|
||||
.current_mode = 0,
|
||||
}
|
||||
},
|
||||
.n_crtcs = 2,
|
||||
.n_tiled_monitors = 1,
|
||||
.screen_width = 800,
|
||||
.screen_height = 600,
|
||||
}
|
||||
};
|
||||
MetaMonitorTestSetup *test_setup;
|
||||
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
check_monitor_configuration (&test_case);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_monitor_hidpi_linear_config (void)
|
||||
{
|
||||
@@ -3007,6 +3154,8 @@ init_monitor_tests (void)
|
||||
meta_test_monitor_tiled_linear_config);
|
||||
g_test_add_func ("/backends/monitor/tiled-non-preferred-linear-config",
|
||||
meta_test_monitor_tiled_non_preferred_linear_config);
|
||||
g_test_add_func ("/backends/monitor/tiled-non-main-origin-linear-config",
|
||||
meta_test_monitor_tiled_non_main_origin_linear_config);
|
||||
g_test_add_func ("/backends/monitor/hidpi-linear-config",
|
||||
meta_test_monitor_hidpi_linear_config);
|
||||
g_test_add_func ("/backends/monitor/suggested-config",
|
||||
|
@@ -411,36 +411,58 @@ meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
|
||||
gfloat *x,
|
||||
gfloat *y)
|
||||
{
|
||||
ClutterEventSequence *sequence = NULL;
|
||||
gboolean can_grab_surface = FALSE;
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
GList *tools, *l;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||
tools = g_hash_table_get_values (tablet_seat->tools);
|
||||
|
||||
if (meta_wayland_seat_has_touch (seat))
|
||||
sequence = meta_wayland_touch_find_grab_sequence (seat->touch,
|
||||
surface,
|
||||
serial);
|
||||
|
||||
if (sequence)
|
||||
{
|
||||
meta_wayland_touch_get_press_coords (seat->touch, sequence, x, y);
|
||||
ClutterEventSequence *sequence;
|
||||
sequence = meta_wayland_touch_find_grab_sequence (seat->touch,
|
||||
surface,
|
||||
serial);
|
||||
if (sequence)
|
||||
{
|
||||
meta_wayland_touch_get_press_coords (seat->touch, sequence, x, y);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (meta_wayland_seat_has_pointer (seat) &&
|
||||
(!require_pressed || seat->pointer->button_count > 0))
|
||||
can_grab_surface = meta_wayland_pointer_can_grab_surface (seat->pointer,
|
||||
surface,
|
||||
serial);
|
||||
|
||||
if (can_grab_surface)
|
||||
if (meta_wayland_seat_has_pointer (seat))
|
||||
{
|
||||
if ((!require_pressed || seat->pointer->button_count > 0) &&
|
||||
meta_wayland_pointer_can_grab_surface (seat->pointer, surface, serial))
|
||||
{
|
||||
if (x)
|
||||
*x = seat->pointer->grab_x;
|
||||
if (y)
|
||||
*y = seat->pointer->grab_y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return sequence || can_grab_surface;
|
||||
for (l = tools; l; l = l->next)
|
||||
{
|
||||
MetaWaylandTabletTool *tool = l->data;
|
||||
|
||||
if ((!require_pressed || tool->button_count > 0) &&
|
||||
meta_wayland_tablet_tool_can_grab_surface (tool, surface, serial))
|
||||
{
|
||||
if (x)
|
||||
*x = tool->grab_x;
|
||||
if (y)
|
||||
*y = tool->grab_y;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "meta-wayland-keyboard.h"
|
||||
#include "meta-wayland-touch.h"
|
||||
#include "meta-wayland-data-device.h"
|
||||
#include "meta-wayland-tablet-tool.h"
|
||||
|
||||
struct _MetaWaylandSeat
|
||||
{
|
||||
|
@@ -572,9 +572,15 @@ meta_wayland_tablet_tool_account_button (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
if (event->type == CLUTTER_BUTTON_PRESS)
|
||||
tool->pressed_buttons |= 1 << (event->button.button - 1);
|
||||
{
|
||||
tool->pressed_buttons |= 1 << (event->button.button - 1);
|
||||
tool->button_count++;
|
||||
}
|
||||
else if (event->type == CLUTTER_BUTTON_RELEASE)
|
||||
tool->pressed_buttons &= ~(1 << (event->button.button - 1));
|
||||
{
|
||||
tool->pressed_buttons &= ~(1 << (event->button.button - 1));
|
||||
tool->button_count--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -621,17 +627,16 @@ repick_for_event (MetaWaylandTabletTool *tool,
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool,
|
||||
ClutterInputDevice *device,
|
||||
const ClutterEvent *event,
|
||||
MetaWaylandSurface *surface,
|
||||
wl_fixed_t *sx,
|
||||
wl_fixed_t *sy)
|
||||
{
|
||||
float xf = 0.0f, yf = 0.0f;
|
||||
ClutterPoint pos;
|
||||
float xf, yf;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, &pos);
|
||||
clutter_event_get_coords (event, &xf, &yf);
|
||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface->surface_actor)),
|
||||
pos.x, pos.y, &xf, &yf);
|
||||
xf, yf, &xf, &yf);
|
||||
|
||||
*sx = wl_fixed_from_double (xf) / surface->scale;
|
||||
*sy = wl_fixed_from_double (yf) / surface->scale;
|
||||
@@ -642,11 +647,9 @@ broadcast_motion (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *device;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
meta_wayland_tablet_tool_get_relative_coordinates (tool, device,
|
||||
meta_wayland_tablet_tool_get_relative_coordinates (tool, event,
|
||||
tool->focus_surface,
|
||||
&sx, &sy);
|
||||
|
||||
@@ -797,6 +800,38 @@ broadcast_rotation (MetaWaylandTabletTool *tool,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_wheel (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
ClutterInputDevice *source;
|
||||
gdouble angle;
|
||||
gint32 clicks = 0;
|
||||
|
||||
source = clutter_event_get_source_device (event);
|
||||
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes,
|
||||
CLUTTER_INPUT_AXIS_WHEEL,
|
||||
&angle))
|
||||
return;
|
||||
|
||||
/* FIXME: Perform proper angle-to-clicks accumulation elsewhere */
|
||||
if (angle > 0.01)
|
||||
clicks = 1;
|
||||
else if (angle < -0.01)
|
||||
clicks = -1;
|
||||
else
|
||||
return;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
{
|
||||
zwp_tablet_tool_v2_send_wheel (resource,
|
||||
wl_fixed_from_double (angle),
|
||||
clicks);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_axes (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
@@ -820,8 +855,8 @@ broadcast_axes (MetaWaylandTabletTool *tool,
|
||||
broadcast_rotation (tool, event);
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER))
|
||||
broadcast_axis (tool, event, CLUTTER_INPUT_AXIS_SLIDER);
|
||||
|
||||
/* FIXME: Missing wp_tablet_tool.wheel */
|
||||
if (capabilities & (1 << ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL))
|
||||
broadcast_wheel (tool, event);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -843,6 +878,9 @@ handle_button_event (MetaWaylandTabletTool *tool,
|
||||
if (!tool->focus_surface)
|
||||
return;
|
||||
|
||||
if (event->type == CLUTTER_BUTTON_PRESS && tool->button_count == 1)
|
||||
clutter_event_get_coords (event, &tool->grab_x, &tool->grab_y);
|
||||
|
||||
if (event->type == CLUTTER_BUTTON_PRESS && event->button.button == 1)
|
||||
broadcast_down (tool, event);
|
||||
else if (event->type == CLUTTER_BUTTON_RELEASE && event->button.button == 1)
|
||||
@@ -921,3 +959,32 @@ meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *tool,
|
||||
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)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
if (tool->focus_surface == surface)
|
||||
return TRUE;
|
||||
|
||||
for (l = surface->subsurfaces; l; l = l->next)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = l->data;
|
||||
|
||||
if (tablet_tool_can_grab_surface (tool, subsurface))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface,
|
||||
uint32_t serial)
|
||||
{
|
||||
return ((tool->down_serial == serial || tool->button_serial == serial) &&
|
||||
tablet_tool_can_grab_surface (tool, surface));
|
||||
}
|
||||
|
@@ -48,11 +48,14 @@ struct _MetaWaylandTabletTool
|
||||
|
||||
MetaWaylandSurface *current;
|
||||
guint32 pressed_buttons;
|
||||
guint32 button_count;
|
||||
|
||||
guint32 proximity_serial;
|
||||
guint32 down_serial;
|
||||
guint32 button_serial;
|
||||
|
||||
float grab_x, grab_y;
|
||||
|
||||
MetaWaylandTablet *current_tablet;
|
||||
};
|
||||
|
||||
@@ -79,5 +82,8 @@ void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *t
|
||||
int new_x,
|
||||
int new_y);
|
||||
|
||||
gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface,
|
||||
uint32_t serial);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_TOOL_H */
|
||||
|
@@ -334,7 +334,8 @@ scale_rect_size (MetaRectangle *rect,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_update_main_monitor (MetaWindow *window)
|
||||
meta_window_wayland_update_main_monitor (MetaWindow *window,
|
||||
gboolean user_op)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
@@ -353,6 +354,7 @@ meta_window_wayland_update_main_monitor (MetaWindow *window)
|
||||
toplevel_window = meta_wayland_surface_get_toplevel_window (window->surface);
|
||||
if (toplevel_window != window)
|
||||
{
|
||||
meta_window_update_monitor (toplevel_window, user_op);
|
||||
window->monitor = toplevel_window->monitor;
|
||||
return;
|
||||
}
|
||||
|
@@ -1456,7 +1456,8 @@ meta_window_x11_update_icon (MetaWindow *window,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_update_main_monitor (MetaWindow *window)
|
||||
meta_window_x11_update_main_monitor (MetaWindow *window,
|
||||
gboolean user_op)
|
||||
{
|
||||
window->monitor = meta_window_calculate_main_logical_monitor (window);
|
||||
}
|
||||
|
Reference in New Issue
Block a user