Compare commits
131 Commits
Author | SHA1 | Date | |
---|---|---|---|
7f49b5144b | |||
e8380d11c4 | |||
ff5a7ba9b9 | |||
c50ae726a9 | |||
2b59b4c793 | |||
0249993377 | |||
d9a9844005 | |||
227187f1f1 | |||
77384ffa9a | |||
1956a6ae76 | |||
5df5b00927 | |||
1d280d8fa1 | |||
9c03e78505 | |||
4af62438f2 | |||
0aa6d9782c | |||
c2e72823fc | |||
d829fa19d2 | |||
76b6cc02d6 | |||
8acfa0a79c | |||
2ed7ca5b6a | |||
5774fcdd80 | |||
eed4dab0fc | |||
f5bdf75f70 | |||
1f0ce80fb4 | |||
7c31fb2450 | |||
11783ffdd0 | |||
41c96921d6 | |||
23455985cd | |||
659c987335 | |||
ecc1f56009 | |||
18b9cf8a85 | |||
934184e236 | |||
b735bdcf2f | |||
f692eb3677 | |||
b1597b4291 | |||
faa96444b5 | |||
78c121eb10 | |||
cb6adc45d1 | |||
59b4b5e9e8 | |||
ad784501a6 | |||
68d690225a | |||
8f716772c2 | |||
da21f02eb9 | |||
4ce7d3a772 | |||
77b7ecfd04 | |||
da1c1d9c22 | |||
f7cd6af9c6 | |||
678ebbb7f6 | |||
87d6e45da5 | |||
80c61c4b3b | |||
4547c6e9f3 | |||
cde622b8e1 | |||
8b810193dd | |||
22f019826c | |||
7fa3f41df2 | |||
f99a086444 | |||
925b1aec64 | |||
be5c2ebcb5 | |||
ae73e9d84d | |||
af920851ca | |||
ea4dbdd66f | |||
ff9753688f | |||
b35b531f00 | |||
6257f1195b | |||
b252771a8f | |||
75c3f0ffba | |||
bd83873a7f | |||
cea7d629d9 | |||
1831a1dd9b | |||
9abf6892c4 | |||
674a48335d | |||
db9d8fcc90 | |||
15db18901c | |||
4cfc21d49d | |||
cf0a453d32 | |||
4186833df7 | |||
30fa764c90 | |||
236417be38 | |||
2641b364e8 | |||
fb5e591bc9 | |||
bfb46ff850 | |||
2012eab842 | |||
9ecb488437 | |||
4295fdb892 | |||
998d921d41 | |||
d491063110 | |||
e2bfaf0751 | |||
f1e1a5ff06 | |||
ef2000053a | |||
8a7876ded5 | |||
b50da46f43 | |||
8b0e9706ca | |||
1d4a5a7520 | |||
8290e1f09a | |||
89672fad04 | |||
1cb9cfe11d | |||
280e297afe | |||
fc8de3d0c8 | |||
3e2555667f | |||
1ecadb6e57 | |||
2abee91dbc | |||
68645df3a3 | |||
d2f79afc1a | |||
8a6fa726d3 | |||
a3d7ae6214 | |||
c0c132a320 | |||
0dfb5d3ef7 | |||
6480a7ee4a | |||
6cc8450f8e | |||
7ae4b28bda | |||
bb8e6afae6 | |||
d7f61e48ac | |||
9de6de5802 | |||
6e7057426e | |||
5306d36522 | |||
7990182f56 | |||
93a6be08a5 | |||
d5d5084151 | |||
d3cff9a962 | |||
133bbdfefa | |||
a8c3470cf2 | |||
578e527869 | |||
312f215fc3 | |||
d639c28e3b | |||
c3f7259cbb | |||
56e8f98c13 | |||
c2217373df | |||
4a3781d7db | |||
911a838c3a | |||
c6106f90d4 | |||
ed52e17886 |
41
NEWS
41
NEWS
@ -1,3 +1,44 @@
|
||||
3.23.2
|
||||
======
|
||||
* Stack docks below other windows on fullscreen monitors [Rui; #772937]
|
||||
* Fix popup grabs blocking screen lock on wayland [Rui; #771235]
|
||||
* Handle touchpad pinch gestures with more than two fingers [Carlos; #765937]
|
||||
* Implement drawing tablet support on X11 [Carlos; #773779]
|
||||
* Fix some Wine games starting minimized [Carlos; #774333]
|
||||
* Fix switching between two finger- and edge scrolling on wayland [Rui; #771744]
|
||||
* Implement support for EGLStream/EGLDevice [Jonas; #773629]
|
||||
* Add size_changed vfunc to handle async client size changes [Rui; #770345]
|
||||
* Change focus window on clicks with any modifiers [Rui; #746642]
|
||||
* Misc. bug fixes and cleanups [Carlos, Daniel, Jonas, Rui; #771067, #774330, #774613,
|
||||
#771297, #774135, #774827, #774923]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Carlos Garnacho, Rui Matos, Florian Müllner, Daniel Stone
|
||||
|
||||
Translations:
|
||||
Kjartan Maraas [nb]
|
||||
|
||||
3.23.1
|
||||
======
|
||||
* Fix handling of Escape shortcut in force-quit dialog [Landry; #737109]
|
||||
* Improve pointer constraints support [Jonas; #771859]
|
||||
* Really fix framebuffer capture origin offset [Rui; #771502]
|
||||
* Fix session going into idle mode immediately on startup [Rui; #772839]
|
||||
* Fix mirror mode with stage views [Rui; #773115]
|
||||
* Fall back to X with connectors spread across multiple GPUs [Ray; #771442]
|
||||
* Fix various crashes on wayland [Jonas, Carlos; #771646, #771858, #772929]
|
||||
* Fix various placement issues on wayland [Olivier, Jonas, Sjoerd; #772729,
|
||||
#768039, #771841, #771841, #773141]
|
||||
* Misc. bug fixes [Rui, Jonas, Olivier; #771019, #773116, #772914, #773210]
|
||||
|
||||
Contributors:
|
||||
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Rui Matos, Landry MINOZA,
|
||||
Sjoerd Simons, Ray Strode
|
||||
|
||||
Translations:
|
||||
Theppitak Karoonboonyanan [th], Kjartan Maraas [nb], Hannie Dumoleyn [nl],
|
||||
liushuyu [zh_CN]
|
||||
|
||||
3.22.1
|
||||
======
|
||||
* Fix feedback loop between StClipboard and X11 bridge [Carlos; #760745]
|
||||
|
@ -25,6 +25,7 @@ AM_CPPFLAGS = \
|
||||
-I$(top_builddir)/clutter \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
$(CLUTTER_DEPRECATED_CFLAGS) \
|
||||
$(CLUTTER_DEBUG_CFLAGS) \
|
||||
$(CLUTTER_HIDDEN_VISIBILITY_CFLAGS) \
|
||||
@ -112,7 +113,6 @@ source_h = \
|
||||
clutter-snap-constraint.h \
|
||||
clutter-stage.h \
|
||||
clutter-stage-manager.h \
|
||||
clutter-stage-view.h \
|
||||
clutter-tap-action.h \
|
||||
clutter-test-utils.h \
|
||||
clutter-texture.h \
|
||||
@ -198,7 +198,6 @@ source_c = \
|
||||
clutter-snap-constraint.c \
|
||||
clutter-stage.c \
|
||||
clutter-stage-manager.c \
|
||||
clutter-stage-view.c \
|
||||
clutter-stage-window.c \
|
||||
clutter-tap-action.c \
|
||||
clutter-test-utils.c \
|
||||
@ -240,6 +239,7 @@ source_h_priv = \
|
||||
clutter-settings-private.h \
|
||||
clutter-stage-manager-private.h \
|
||||
clutter-stage-private.h \
|
||||
clutter-stage-view.h \
|
||||
clutter-stage-window.h \
|
||||
$(NULL)
|
||||
|
||||
@ -248,6 +248,7 @@ source_c_priv = \
|
||||
clutter-easing.c \
|
||||
clutter-event-translator.c \
|
||||
clutter-id-pool.c \
|
||||
clutter-stage-view.c \
|
||||
$(NULL)
|
||||
|
||||
# deprecated installed headers
|
||||
@ -413,11 +414,13 @@ x11_source_c_priv = \
|
||||
x11_source_c += \
|
||||
x11/clutter-device-manager-xi2.c \
|
||||
x11/clutter-input-device-xi2.c \
|
||||
x11/clutter-input-device-tool-xi2.c \
|
||||
$(NULL)
|
||||
|
||||
x11_source_h_priv += \
|
||||
x11/clutter-device-manager-xi2.h \
|
||||
x11/clutter-input-device-xi2.h \
|
||||
x11/clutter-input-device-tool-xi2.h \
|
||||
$(NULL)
|
||||
|
||||
x11_source_c += \
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-stage-private.h"
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "clutter-input-device-tool.h"
|
||||
|
||||
struct _ClutterDeviceManagerPrivate
|
||||
{
|
||||
@ -70,6 +71,7 @@ enum
|
||||
{
|
||||
DEVICE_ADDED,
|
||||
DEVICE_REMOVED,
|
||||
TOOL_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
@ -184,6 +186,16 @@ clutter_device_manager_class_init (ClutterDeviceManagerClass *klass)
|
||||
_clutter_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_INPUT_DEVICE);
|
||||
|
||||
manager_signals[TOOL_CHANGED] =
|
||||
g_signal_new (I_("tool-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_clutter_marshal_VOID__OBJECT_OBJECT,
|
||||
G_TYPE_NONE, 2,
|
||||
CLUTTER_TYPE_INPUT_DEVICE,
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -83,7 +83,7 @@ struct _ClutterDeviceManagerClass
|
||||
ClutterInputDevice *device);
|
||||
void (* select_stage_events) (ClutterDeviceManager *manager,
|
||||
ClutterStage *stage);
|
||||
ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *manager,
|
||||
ClutterVirtualInputDevice *(* create_virtual_device) (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDeviceType device_type);
|
||||
void (* compress_motion) (ClutterDeviceManager *device_manger,
|
||||
ClutterEvent *event,
|
||||
|
@ -1990,22 +1990,28 @@ clutter_event_remove_filter (guint id)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_gesture_swipe_finger_count:
|
||||
* @event: a touchpad swipe event
|
||||
* clutter_event_get_touchpad_gesture_finger_count:
|
||||
* @event: a touchpad swipe/pinch event
|
||||
*
|
||||
* Returns the number of fingers that is triggering the touchpad gesture.
|
||||
*
|
||||
* Returns: the number of fingers swiping.
|
||||
* Returns: the number of fingers in the gesture.
|
||||
*
|
||||
* Since: 1.24
|
||||
**/
|
||||
guint
|
||||
clutter_event_get_gesture_swipe_finger_count (const ClutterEvent *event)
|
||||
clutter_event_get_touchpad_gesture_finger_count (const ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, 0);
|
||||
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE, 0);
|
||||
g_return_val_if_fail (event->type == CLUTTER_TOUCHPAD_SWIPE ||
|
||||
event->type == CLUTTER_TOUCHPAD_PINCH, 0);
|
||||
|
||||
return event->touchpad_swipe.n_fingers;
|
||||
if (event->type == CLUTTER_TOUCHPAD_SWIPE)
|
||||
return event->touchpad_swipe.n_fingers;
|
||||
else if (event->type == CLUTTER_TOUCHPAD_PINCH)
|
||||
return event->touchpad_pinch.n_fingers;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -459,6 +459,7 @@ struct _ClutterTouchpadPinchEvent
|
||||
gfloat dy;
|
||||
gfloat angle_delta;
|
||||
gfloat scale;
|
||||
guint n_fingers;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -752,7 +753,7 @@ CLUTTER_AVAILABLE_IN_1_2
|
||||
const ClutterEvent * clutter_get_current_event (void);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_24
|
||||
guint clutter_event_get_gesture_swipe_finger_count (const ClutterEvent *event);
|
||||
guint clutter_event_get_touchpad_gesture_finger_count (const ClutterEvent *event);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_1_24
|
||||
gdouble clutter_event_get_gesture_pinch_angle_delta (const ClutterEvent *event);
|
||||
|
@ -23,6 +23,7 @@ VOID:OBJECT
|
||||
VOID:OBJECT,FLAGS
|
||||
VOID:OBJECT,FLOAT,FLOAT
|
||||
VOID:OBJECT,FLOAT,FLOAT,FLAGS
|
||||
VOID:OBJECT,OBJECT
|
||||
VOID:OBJECT,PARAM
|
||||
VOID:OBJECT,POINTER
|
||||
VOID:OBJECT,UINT
|
||||
|
@ -4712,8 +4712,8 @@ capture_view (ClutterStage *stage,
|
||||
clutter_stage_view_get_layout (view, &view_layout);
|
||||
|
||||
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
|
||||
view_layout.x + rect->x,
|
||||
view_layout.y + rect->y,
|
||||
rect->x - view_layout.x,
|
||||
rect->y - view_layout.y,
|
||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||
bitmap);
|
||||
|
||||
|
@ -530,7 +530,8 @@ notify_pinch_gesture_event (ClutterInputDevice *input_device,
|
||||
gdouble dx,
|
||||
gdouble dy,
|
||||
gdouble angle_delta,
|
||||
gdouble scale)
|
||||
gdouble scale,
|
||||
guint n_fingers)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev;
|
||||
ClutterSeatEvdev *seat;
|
||||
@ -561,6 +562,7 @@ notify_pinch_gesture_event (ClutterInputDevice *input_device,
|
||||
event->touchpad_pinch.dy = dy;
|
||||
event->touchpad_pinch.angle_delta = angle_delta;
|
||||
event->touchpad_pinch.scale = scale;
|
||||
event->touchpad_pinch.n_fingers = n_fingers;
|
||||
|
||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||
|
||||
@ -1208,11 +1210,17 @@ input_device_update_tool (ClutterInputDevice *input_device,
|
||||
}
|
||||
}
|
||||
|
||||
evdev_device->last_tool = tool;
|
||||
if (evdev_device->last_tool != tool)
|
||||
{
|
||||
evdev_device->last_tool = tool;
|
||||
g_signal_emit_by_name (clutter_device_manager_get_default (),
|
||||
"tool-changed", input_device, tool);
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble *
|
||||
translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
|
||||
translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
GArray *axes = g_array_new (FALSE, FALSE, sizeof (gdouble));
|
||||
struct libinput_tablet_tool *libinput_tool;
|
||||
@ -1234,6 +1242,7 @@ translate_tablet_axes (struct libinput_event_tablet_tool *tablet_event)
|
||||
if (libinput_tablet_tool_has_pressure (libinput_tool))
|
||||
{
|
||||
value = libinput_event_tablet_tool_get_pressure (tablet_event);
|
||||
value = clutter_input_device_tool_evdev_translate_pressure (tool, value);
|
||||
g_array_append_val (axes, value);
|
||||
}
|
||||
|
||||
@ -1617,6 +1626,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
struct libinput_event_gesture *gesture_event =
|
||||
libinput_event_get_gesture_event (event);
|
||||
ClutterTouchpadGesturePhase phase;
|
||||
guint n_fingers;
|
||||
guint64 time_us;
|
||||
|
||||
if (libinput_event_get_type (event) == LIBINPUT_EVENT_GESTURE_PINCH_BEGIN)
|
||||
@ -1625,9 +1635,10 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
phase = libinput_event_gesture_get_cancelled (gesture_event) ?
|
||||
CLUTTER_TOUCHPAD_GESTURE_PHASE_CANCEL : CLUTTER_TOUCHPAD_GESTURE_PHASE_END;
|
||||
|
||||
n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time_us = libinput_event_gesture_get_time_usec (gesture_event);
|
||||
notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0);
|
||||
notify_pinch_gesture_event (device, phase, time_us, 0, 0, 0, 0, n_fingers);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
|
||||
@ -1635,8 +1646,10 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
struct libinput_event_gesture *gesture_event =
|
||||
libinput_event_get_gesture_event (event);
|
||||
gdouble angle_delta, scale, dx, dy;
|
||||
guint n_fingers;
|
||||
guint64 time_us;
|
||||
|
||||
n_fingers = libinput_event_gesture_get_finger_count (gesture_event);
|
||||
device = libinput_device_get_user_data (libinput_device);
|
||||
time_us = libinput_event_gesture_get_time_usec (gesture_event);
|
||||
angle_delta = libinput_event_gesture_get_angle_delta (gesture_event);
|
||||
@ -1646,7 +1659,7 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
|
||||
notify_pinch_gesture_event (device,
|
||||
CLUTTER_TOUCHPAD_GESTURE_PHASE_UPDATE,
|
||||
time_us, dx, dy, angle_delta, scale);
|
||||
time_us, dx, dy, angle_delta, scale, n_fingers);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
|
||||
@ -1707,7 +1720,8 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
if (!stage)
|
||||
break;
|
||||
|
||||
axes = translate_tablet_axes (tablet_event);
|
||||
axes = translate_tablet_axes (tablet_event,
|
||||
evdev_device->last_tool);
|
||||
if (!axes)
|
||||
break;
|
||||
|
||||
@ -1747,8 +1761,11 @@ process_device_event (ClutterDeviceManagerEvdev *manager_evdev,
|
||||
|
||||
libinput_tool = libinput_event_tablet_tool_get_tool (tablet_event);
|
||||
|
||||
input_device_update_tool (device, libinput_tool);
|
||||
if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN)
|
||||
input_device_update_tool (device, libinput_tool);
|
||||
notify_proximity (device, time, state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN);
|
||||
if (state == LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT)
|
||||
input_device_update_tool (device, NULL);
|
||||
break;
|
||||
}
|
||||
case LIBINPUT_EVENT_TABLET_TOOL_BUTTON:
|
||||
|
@ -150,6 +150,14 @@ gboolean clutter_evdev_event_get_relative_motion (const ClutterEvent *event,
|
||||
double *dx_unaccel,
|
||||
double *dy_unaccel);
|
||||
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_evdev_input_device_tool_set_pressure_curve (ClutterInputDeviceTool *tool,
|
||||
gdouble curve[4]);
|
||||
CLUTTER_AVAILABLE_IN_ALL
|
||||
void clutter_evdev_input_device_tool_set_button_code (ClutterInputDeviceTool *tool,
|
||||
guint button,
|
||||
guint evcode);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_EVDEV_H__ */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#endif
|
||||
|
||||
#include "clutter-input-device-tool-evdev.h"
|
||||
#include "clutter-evdev.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterInputDeviceToolEvdev, clutter_input_device_tool_evdev,
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL)
|
||||
@ -35,6 +36,7 @@ clutter_input_device_tool_evdev_finalize (GObject *object)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (object);
|
||||
|
||||
g_hash_table_unref (tool->button_map);
|
||||
libinput_tablet_tool_unref (tool->tool);
|
||||
|
||||
G_OBJECT_CLASS (clutter_input_device_tool_evdev_parent_class)->finalize (object);
|
||||
@ -51,6 +53,7 @@ clutter_input_device_tool_evdev_class_init (ClutterInputDeviceToolEvdevClass *kl
|
||||
static void
|
||||
clutter_input_device_tool_evdev_init (ClutterInputDeviceToolEvdev *tool)
|
||||
{
|
||||
tool->button_map = g_hash_table_new (NULL, NULL);
|
||||
}
|
||||
|
||||
ClutterInputDeviceTool *
|
||||
@ -70,3 +73,96 @@ clutter_input_device_tool_evdev_new (struct libinput_tablet_tool *tool,
|
||||
|
||||
return CLUTTER_INPUT_DEVICE_TOOL (evdev_tool);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_evdev_input_device_tool_set_pressure_curve (ClutterInputDeviceTool *tool,
|
||||
gdouble curve[4])
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV (tool));
|
||||
g_return_if_fail (curve[0] >= 0 && curve[0] <= 1 &&
|
||||
curve[1] >= 0 && curve[1] <= 1 &&
|
||||
curve[2] >= 0 && curve[2] <= 1 &&
|
||||
curve[3] >= 0 && curve[3] <= 1);
|
||||
|
||||
evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool);
|
||||
evdev_tool->pressure_curve[0] = curve[0];
|
||||
evdev_tool->pressure_curve[1] = curve[1];
|
||||
evdev_tool->pressure_curve[2] = curve[2];
|
||||
evdev_tool->pressure_curve[3] = curve[3];
|
||||
}
|
||||
|
||||
void
|
||||
clutter_evdev_input_device_tool_set_button_code (ClutterInputDeviceTool *tool,
|
||||
guint button,
|
||||
guint evcode)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL_EVDEV (tool));
|
||||
|
||||
evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool);
|
||||
|
||||
if (evcode == 0)
|
||||
{
|
||||
g_hash_table_remove (evdev_tool->button_map, GUINT_TO_POINTER (button));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_hash_table_insert (evdev_tool->button_map, GUINT_TO_POINTER (button),
|
||||
GUINT_TO_POINTER (evcode));
|
||||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
calculate_bezier_position (gdouble pos,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2)
|
||||
{
|
||||
gdouble int1_y, int2_y;
|
||||
|
||||
pos = CLAMP (pos, 0, 1);
|
||||
|
||||
/* Intersection between 0,0 and x1,y1 */
|
||||
int1_y = pos * y1;
|
||||
|
||||
/* Intersection between x2,y2 and 1,1 */
|
||||
int2_y = (pos * (1 - y2)) + y2;
|
||||
|
||||
/* Find the new position in the line traced by the previous points */
|
||||
return (pos * (int2_y - int1_y)) + int1_y;
|
||||
}
|
||||
|
||||
gdouble
|
||||
clutter_input_device_tool_evdev_translate_pressure (ClutterInputDeviceTool *tool,
|
||||
gdouble pressure)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), pressure);
|
||||
|
||||
evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool);
|
||||
|
||||
return calculate_bezier_position (CLAMP (pressure, 0, 1),
|
||||
evdev_tool->pressure_curve[0],
|
||||
evdev_tool->pressure_curve[1],
|
||||
evdev_tool->pressure_curve[2],
|
||||
evdev_tool->pressure_curve[3]);
|
||||
}
|
||||
|
||||
guint
|
||||
clutter_input_device_tool_evdev_get_button_code (ClutterInputDeviceTool *tool,
|
||||
guint button)
|
||||
{
|
||||
ClutterInputDeviceToolEvdev *evdev_tool;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), 0);
|
||||
|
||||
evdev_tool = CLUTTER_INPUT_DEVICE_TOOL_EVDEV (tool);
|
||||
|
||||
return GPOINTER_TO_UINT (g_hash_table_lookup (evdev_tool->button_map,
|
||||
GUINT_TO_POINTER (button)));
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ struct _ClutterInputDeviceToolEvdev
|
||||
{
|
||||
ClutterInputDeviceTool parent_instance;
|
||||
struct libinput_tablet_tool *tool;
|
||||
GHashTable *button_map;
|
||||
gdouble pressure_curve[4];
|
||||
};
|
||||
|
||||
struct _ClutterInputDeviceToolEvdevClass
|
||||
@ -72,6 +74,11 @@ ClutterInputDeviceTool * clutter_input_device_tool_evdev_new (struct libinp
|
||||
guint64 serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
gdouble clutter_input_device_tool_evdev_translate_pressure (ClutterInputDeviceTool *tool,
|
||||
gdouble pressure);
|
||||
guint clutter_input_device_tool_evdev_get_button_code (ClutterInputDeviceTool *tool,
|
||||
guint button);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_EVDEV_TOOL_H__ */
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "clutter-event-private.h"
|
||||
#include "clutter-input-device-evdev.h"
|
||||
#include "clutter-input-device-tool-evdev.h"
|
||||
#include "clutter-main.h"
|
||||
|
||||
/* Try to keep the pointer inside the stage. Hopefully no one is using
|
||||
@ -433,6 +434,7 @@ clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
|
||||
uint32_t button,
|
||||
uint32_t state)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev = (ClutterInputDeviceEvdev *) input_device;
|
||||
ClutterStage *stage;
|
||||
ClutterEvent *event = NULL;
|
||||
gint button_nr;
|
||||
@ -528,13 +530,21 @@ clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat,
|
||||
clutter_event_set_device (event, seat->core_pointer);
|
||||
clutter_event_set_source_device (event, input_device);
|
||||
|
||||
if (device_evdev->last_tool)
|
||||
{
|
||||
/* Apply the button event code as per the tool mapping */
|
||||
guint mapped_button;
|
||||
|
||||
mapped_button = clutter_input_device_tool_evdev_get_button_code (device_evdev->last_tool,
|
||||
button_nr);
|
||||
if (mapped_button != 0)
|
||||
button = mapped_button;
|
||||
}
|
||||
|
||||
_clutter_evdev_event_set_event_code (event, button);
|
||||
|
||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
ClutterInputDeviceEvdev *device_evdev =
|
||||
CLUTTER_INPUT_DEVICE_EVDEV (input_device);
|
||||
|
||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||
clutter_event_set_device (event, input_device);
|
||||
}
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include "clutter-backend-x11.h"
|
||||
#include "clutter-input-device-xi2.h"
|
||||
#include "clutter-input-device-tool-xi2.h"
|
||||
#include "clutter-virtual-input-device-x11.h"
|
||||
#include "clutter-stage-x11.h"
|
||||
|
||||
#include "clutter-backend.h"
|
||||
@ -394,6 +396,8 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
source = CLUTTER_ERASER_DEVICE;
|
||||
else if (strstr (name, "cursor") != NULL)
|
||||
source = CLUTTER_CURSOR_DEVICE;
|
||||
else if (strstr (name, " pad") != NULL)
|
||||
source = CLUTTER_PAD_DEVICE;
|
||||
else if (strstr (name, "wacom") != NULL || strstr (name, "pen") != NULL)
|
||||
source = CLUTTER_PEN_DEVICE;
|
||||
else if (strstr (name, "touchpad") != NULL)
|
||||
@ -460,6 +464,46 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
pad_passive_button_grab (ClutterInputDevice *device)
|
||||
{
|
||||
XIGrabModifiers xi_grab_mods = { XIAnyModifier, };
|
||||
XIEventMask xi_event_mask;
|
||||
gint device_id, rc;
|
||||
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
xi_event_mask.deviceid = device_id;
|
||||
xi_event_mask.mask_len = XIMaskLen (XI_LASTEVENT);
|
||||
xi_event_mask.mask = g_new0 (unsigned char, xi_event_mask.mask_len);
|
||||
|
||||
XISetMask (xi_event_mask.mask, XI_Motion);
|
||||
XISetMask (xi_event_mask.mask, XI_ButtonPress);
|
||||
XISetMask (xi_event_mask.mask, XI_ButtonRelease);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
rc = XIGrabButton (clutter_x11_get_default_display (),
|
||||
device_id, XIAnyButton,
|
||||
clutter_x11_get_root_window (), None,
|
||||
XIGrabModeSync, XIGrabModeSync,
|
||||
True, &xi_event_mask, 1, &xi_grab_mods);
|
||||
if (rc != 0)
|
||||
{
|
||||
g_warning ("Could not passively grab pad device: %s",
|
||||
clutter_input_device_get_device_name (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
XIAllowEvents (clutter_x11_get_default_display (),
|
||||
device_id, XIAsyncDevice,
|
||||
CLUTTER_CURRENT_TIME);
|
||||
}
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
g_free (xi_event_mask.mask);
|
||||
}
|
||||
|
||||
static ClutterInputDevice *
|
||||
add_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
ClutterBackendX11 *backend_x11,
|
||||
@ -494,6 +538,9 @@ add_device (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
g_warning ("Unhandled device: %s",
|
||||
clutter_input_device_get_device_name (device));
|
||||
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE)
|
||||
pad_passive_button_grab (device);
|
||||
|
||||
/* relationships between devices and signal emissions are not
|
||||
* necessary while we're constructing the device manager instance
|
||||
*/
|
||||
@ -906,6 +953,78 @@ clutter_device_manager_xi2_select_stage_events (ClutterDeviceManager *manager,
|
||||
g_free (mask);
|
||||
}
|
||||
|
||||
static guint
|
||||
device_get_tool_serial (ClutterBackendX11 *backend_x11,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
gulong nitems, bytes_after;
|
||||
guint32 *data = NULL;
|
||||
guint serial_id = 0;
|
||||
int rc, format;
|
||||
Atom type;
|
||||
Atom prop;
|
||||
|
||||
prop = XInternAtom (backend_x11->xdpy, "Wacom Serial IDs", True);
|
||||
if (prop == None)
|
||||
return 0;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
rc = XIGetProperty (backend_x11->xdpy,
|
||||
clutter_input_device_get_device_id (device),
|
||||
prop, 0, 4, FALSE, XA_INTEGER, &type, &format, &nitems, &bytes_after,
|
||||
(guchar **) &data);
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
if (rc == Success && type == XA_INTEGER && format == 32 && nitems >= 4)
|
||||
serial_id = data[3];
|
||||
|
||||
XFree (data);
|
||||
|
||||
return serial_id;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_property_event (ClutterDeviceManagerXI2 *manager_xi2,
|
||||
XIEvent *event)
|
||||
{
|
||||
XIPropertyEvent *xev = (XIPropertyEvent *) event;
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
|
||||
Atom serial_ids_prop = XInternAtom (backend_x11->xdpy, "Wacom Serial IDs", True);
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
if (!device)
|
||||
return;
|
||||
|
||||
if (xev->property == serial_ids_prop)
|
||||
{
|
||||
ClutterInputDeviceTool *tool = NULL;
|
||||
ClutterInputDeviceToolType type;
|
||||
guint serial_id;
|
||||
|
||||
serial_id = device_get_tool_serial (backend_x11, device);
|
||||
|
||||
if (serial_id != 0)
|
||||
{
|
||||
tool = g_hash_table_lookup (manager_xi2->tools_by_serial,
|
||||
GUINT_TO_POINTER (serial_id));
|
||||
if (!tool)
|
||||
{
|
||||
type = clutter_input_device_get_device_type (device) == CLUTTER_ERASER_DEVICE ?
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER : CLUTTER_INPUT_DEVICE_TOOL_PEN;
|
||||
tool = clutter_input_device_tool_xi2_new (serial_id, type);
|
||||
g_hash_table_insert (manager_xi2->tools_by_serial,
|
||||
GUINT_TO_POINTER (serial_id),
|
||||
tool);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_input_device_xi2_update_tool (device, tool);
|
||||
g_signal_emit_by_name (manager_xi2, "tool-changed", device, tool);
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterTranslateReturn
|
||||
clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
gpointer native,
|
||||
@ -937,7 +1056,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
return CLUTTER_TRANSLATE_REMOVE;
|
||||
|
||||
if (!(xi_event->evtype == XI_HierarchyChanged ||
|
||||
xi_event->evtype == XI_DeviceChanged))
|
||||
xi_event->evtype == XI_DeviceChanged ||
|
||||
xi_event->evtype == XI_PropertyEvent))
|
||||
{
|
||||
stage = get_event_stage (translator, xi_event);
|
||||
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||
@ -1078,6 +1198,50 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
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 */
|
||||
XIAllowEvents (clutter_x11_get_default_display (),
|
||||
xev->sourceid,
|
||||
XIAsyncDevice,
|
||||
xev->time);
|
||||
|
||||
/* Ignore 4-7 buttons */
|
||||
if (xev->detail >= 4 && xev->detail <= 7)
|
||||
return CLUTTER_TRANSLATE_REMOVE;
|
||||
|
||||
event->pad_button.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;
|
||||
|
||||
/* The 4-7 button range is taken as non-existent on pad devices,
|
||||
* let the buttons above that take over this range.
|
||||
*/
|
||||
if (xev->detail > 7)
|
||||
xev->detail -= 4;
|
||||
|
||||
/* Pad buttons are 0-indexed */
|
||||
event->pad_button.button = xev->detail - 1;
|
||||
clutter_event_set_source_device (event, source_device);
|
||||
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"%s: win:0x%x, device:%d '%s', time:%d "
|
||||
"(button:%d)",
|
||||
event->any.type == CLUTTER_BUTTON_PRESS
|
||||
? "pad button press "
|
||||
: "pad button release",
|
||||
(unsigned int) stage_x11->xwin,
|
||||
device->id,
|
||||
device->device_name,
|
||||
event->any.time,
|
||||
event->pad_button.button);
|
||||
|
||||
retval = CLUTTER_TRANSLATE_QUEUE;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (xev->detail)
|
||||
{
|
||||
case 4:
|
||||
@ -1157,6 +1321,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
|
||||
clutter_event_set_source_device (event, source_device);
|
||||
clutter_event_set_device (event, device);
|
||||
clutter_event_set_device_tool (event,
|
||||
clutter_input_device_xi2_get_current_tool (source_device));
|
||||
|
||||
event->button.axes = translate_axes (event->button.device,
|
||||
event->button.x,
|
||||
@ -1265,6 +1431,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
|
||||
clutter_event_set_source_device (event, source_device);
|
||||
clutter_event_set_device (event, device);
|
||||
clutter_event_set_device_tool (event,
|
||||
clutter_input_device_xi2_get_current_tool (source_device));
|
||||
|
||||
event->motion.axes = translate_axes (event->motion.device,
|
||||
event->motion.x,
|
||||
@ -1466,6 +1634,10 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
|
||||
case XI_FocusOut:
|
||||
retval = CLUTTER_TRANSLATE_CONTINUE;
|
||||
break;
|
||||
case XI_PropertyEvent:
|
||||
handle_property_event (manager_xi2, xi_event);
|
||||
retval = CLUTTER_TRANSLATE_CONTINUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return retval;
|
||||
@ -1643,6 +1815,7 @@ clutter_device_manager_xi2_constructed (GObject *gobject)
|
||||
|
||||
XISetMask (mask, XI_HierarchyChanged);
|
||||
XISetMask (mask, XI_DeviceChanged);
|
||||
XISetMask (mask, XI_PropertyEvent);
|
||||
|
||||
event_mask.deviceid = XIAllDevices;
|
||||
event_mask.mask_len = sizeof (mask);
|
||||
@ -1678,6 +1851,16 @@ clutter_device_manager_xi2_set_property (GObject *gobject,
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterVirtualInputDevice *
|
||||
clutter_device_manager_xi2_create_virtual_device (ClutterDeviceManager *manager,
|
||||
ClutterInputDeviceType device_type)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_VIRTUAL_INPUT_DEVICE_X11,
|
||||
"device-manager", manager,
|
||||
"device-type", device_type,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_device_manager_xi2_class_init (ClutterDeviceManagerXI2Class *klass)
|
||||
{
|
||||
@ -1705,6 +1888,7 @@ clutter_device_manager_xi2_class_init (ClutterDeviceManagerXI2Class *klass)
|
||||
manager_class->get_core_device = clutter_device_manager_xi2_get_core_device;
|
||||
manager_class->get_device = clutter_device_manager_xi2_get_device;
|
||||
manager_class->select_stage_events = clutter_device_manager_xi2_select_stage_events;
|
||||
manager_class->create_virtual_device = clutter_device_manager_xi2_create_virtual_device;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1713,4 +1897,6 @@ clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self)
|
||||
self->devices_by_id = g_hash_table_new_full (NULL, NULL,
|
||||
NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
self->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ struct _ClutterDeviceManagerXI2
|
||||
ClutterDeviceManager parent_instance;
|
||||
|
||||
GHashTable *devices_by_id;
|
||||
GHashTable *tools_by_serial;
|
||||
|
||||
GSList *all_devices;
|
||||
|
||||
|
51
clutter/clutter/x11/clutter-input-device-tool-xi2.c
Normal file
51
clutter/clutter/x11/clutter-input-device-tool-xi2.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2016 Red Hat
|
||||
*
|
||||
* 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: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clutter-build-config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-input-device-tool-xi2.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterInputDeviceToolXI2, clutter_input_device_tool_xi2,
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL)
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_xi2_class_init (ClutterInputDeviceToolXI2Class *klass)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_input_device_tool_xi2_init (ClutterInputDeviceToolXI2 *tool)
|
||||
{
|
||||
}
|
||||
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_tool_xi2_new (guint serial,
|
||||
ClutterInputDeviceToolType type)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2,
|
||||
"type", type,
|
||||
"serial", serial,
|
||||
NULL);
|
||||
}
|
74
clutter/clutter/x11/clutter-input-device-tool-xi2.h
Normal file
74
clutter/clutter/x11/clutter-input-device-tool-xi2.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright © 2016 Red Hat
|
||||
*
|
||||
* 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: Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__
|
||||
#define __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__
|
||||
|
||||
#include <clutter/clutter-input-device-tool.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2 (clutter_input_device_tool_xi2_get_type ())
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_XI2(o) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2))
|
||||
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL_XI2(o) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2))
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_XI2_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((c), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2Class))
|
||||
|
||||
#define CLUTTER_IS_INPUT_DEVICE_TOOL_XI2_CLASS(c) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((c), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2))
|
||||
|
||||
#define CLUTTER_INPUT_DEVICE_TOOL_XI2_GET_CLASS(o) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((o), \
|
||||
CLUTTER_TYPE_INPUT_DEVICE_TOOL_XI2, ClutterInputDeviceToolXI2Class))
|
||||
|
||||
typedef struct _ClutterInputDeviceToolXI2 ClutterInputDeviceToolXI2;
|
||||
typedef struct _ClutterInputDeviceToolXI2Class ClutterInputDeviceToolXI2Class;
|
||||
|
||||
struct _ClutterInputDeviceToolXI2
|
||||
{
|
||||
ClutterInputDeviceTool parent_instance;
|
||||
struct libinput_tablet_tool *tool;
|
||||
};
|
||||
|
||||
struct _ClutterInputDeviceToolXI2Class
|
||||
{
|
||||
ClutterInputDeviceToolClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_input_device_tool_xi2_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterInputDeviceTool * clutter_input_device_tool_xi2_new (guint serial,
|
||||
ClutterInputDeviceToolType type);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_INPUT_DEVICE_XI2_TOOL_H__ */
|
@ -44,6 +44,7 @@ struct _ClutterInputDeviceXI2
|
||||
ClutterInputDevice device;
|
||||
|
||||
gint device_id;
|
||||
ClutterInputDeviceTool *current_tool;
|
||||
};
|
||||
|
||||
#define N_BUTTONS 5
|
||||
@ -172,3 +173,18 @@ _clutter_input_device_xi2_translate_state (ClutterEvent *event,
|
||||
|
||||
_clutter_event_set_state_full (event, button, base, latched, locked, effective);
|
||||
}
|
||||
|
||||
void
|
||||
clutter_input_device_xi2_update_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
|
||||
g_set_object (&device_xi2->current_tool, tool);
|
||||
}
|
||||
|
||||
ClutterInputDeviceTool *
|
||||
clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device)
|
||||
{
|
||||
ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device);
|
||||
return device_xi2->current_tool;
|
||||
}
|
||||
|
@ -41,6 +41,9 @@ void _clutter_input_device_xi2_translate_state (ClutterEvent *event,
|
||||
XIModifierState *modifiers_state,
|
||||
XIButtonState *buttons_state,
|
||||
XIGroupState *group_state);
|
||||
void clutter_input_device_xi2_update_tool (ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool);
|
||||
ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -27,6 +27,9 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "clutter-x11.h"
|
||||
#include "X11/extensions/XTest.h"
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "x11/clutter-virtual-input-device-x11.h"
|
||||
|
||||
@ -61,6 +64,8 @@ clutter_virtual_input_device_x11_notify_button (ClutterVirtualInputDevice *virtu
|
||||
uint32_t button,
|
||||
ClutterButtonState button_state)
|
||||
{
|
||||
XTestFakeButtonEvent (clutter_x11_get_default_display (),
|
||||
button, button_state == CLUTTER_BUTTON_STATE_PRESSED, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -69,6 +74,21 @@ clutter_virtual_input_device_x11_notify_key (ClutterVirtualInputDevice *virtual_
|
||||
uint32_t key,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
XTestFakeKeyEvent (clutter_x11_get_default_display (),
|
||||
key, key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
KeyCode keycode;
|
||||
|
||||
keycode = XKeysymToKeycode (clutter_x11_get_default_display (), keyval);
|
||||
XTestFakeKeyEvent (clutter_x11_get_default_display (),
|
||||
keycode, key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -86,4 +106,5 @@ clutter_virtual_input_device_x11_class_init (ClutterVirtualInputDeviceX11Class *
|
||||
virtual_input_device_class->notify_absolute_motion = clutter_virtual_input_device_x11_notify_absolute_motion;
|
||||
virtual_input_device_class->notify_button = clutter_virtual_input_device_x11_notify_button;
|
||||
virtual_input_device_class->notify_key = clutter_virtual_input_device_x11_notify_key;
|
||||
virtual_input_device_class->notify_keyval = clutter_virtual_input_device_x11_notify_keyval;
|
||||
}
|
||||
|
@ -382,6 +382,22 @@ AS_IF([test "x$SUPPORT_X11" = "x1"],
|
||||
[AC_MSG_ERROR([not found])]
|
||||
)
|
||||
|
||||
# XTEST (required)
|
||||
AC_MSG_CHECKING([for XTest extension])
|
||||
PKG_CHECK_EXISTS([xtst], [have_xtest=yes], [have_xtest=no])
|
||||
AS_IF([test "x$have_xtest" = "xyes"],
|
||||
[
|
||||
AC_DEFINE(HAVE_XTEST, [1], [Define to 1 if we have the XTest X extension])
|
||||
|
||||
X11_LIBS="$X11_LIBS -lXtst"
|
||||
X11_PC_FILES="$X11_PC_FILES xtst"
|
||||
X11_EXTS="$X11_EXTS xtst"
|
||||
|
||||
AC_MSG_RESULT([found])
|
||||
],
|
||||
[AC_MSG_ERROR([Not found])]
|
||||
)
|
||||
|
||||
# X Generic Extensions (optional)
|
||||
clutter_save_CPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $X11_CFLAGS"
|
||||
|
@ -11,6 +11,7 @@ AM_CPPFLAGS = \
|
||||
-DGLIB_DISABLE_DEPRECATION_WARNINGS \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
|
@ -9,6 +9,7 @@ AM_CPPFLAGS = \
|
||||
-DG_LOG_DOMAIN=\"Clutter-Conform\" \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-DCOGL_DISABLE_DEPRECATION_WARNINGS \
|
||||
|
@ -127,6 +127,7 @@ test_interactive_CPPFLAGS = \
|
||||
-DCLUTTER_DISABLE_DEPRECATION_WARNINGS \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
|
@ -20,6 +20,7 @@ AM_CPPFLAGS = \
|
||||
-DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
|
@ -21,6 +21,7 @@ AM_CPPFLAGS = \
|
||||
-DTESTS_DATA_DIR=\""$(top_srcdir)/tests/data/"\" \
|
||||
-I$(top_srcdir)/../cogl \
|
||||
-I$(top_builddir)/../cogl \
|
||||
-I$(top_builddir)/../cogl/cogl \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
|
@ -452,7 +452,7 @@ libmutter_cogl_la_LDFLAGS = \
|
||||
-avoid-version \
|
||||
-export-dynamic \
|
||||
-rpath $(mutterlibdir) \
|
||||
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current).*"
|
||||
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_pixel_format_get_bytes_per_pixel).*"
|
||||
|
||||
libmutter_cogl_la_SOURCES = $(cogl_sources_c)
|
||||
nodist_libmutter_cogl_la_SOURCES = $(BUILT_SOURCES)
|
||||
|
@ -262,6 +262,7 @@ typedef enum _CoglFeatureID
|
||||
COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
|
||||
COGL_FEATURE_ID_TEXTURE_RG,
|
||||
COGL_FEATURE_ID_BUFFER_AGE,
|
||||
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
|
||||
|
||||
/*< private >*/
|
||||
_COGL_N_FEATURE_IDS /*< skip >*/
|
||||
|
@ -152,6 +152,7 @@ typedef long GLsizeiptr;
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
|
||||
#define GL_SAMPLE_COVERAGE 0x80A0
|
||||
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
|
||||
|
||||
/* ErrorCode */
|
||||
#define GL_NO_ERROR 0
|
||||
|
@ -111,6 +111,14 @@ _cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
|
||||
lengths[count++] = sizeof (texture_3d_extension) - 1;
|
||||
}
|
||||
|
||||
if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL))
|
||||
{
|
||||
static const char texture_3d_extension[] =
|
||||
"#extension GL_OES_EGL_image_external : require\n";
|
||||
strings[count] = texture_3d_extension;
|
||||
lengths[count++] = sizeof (texture_3d_extension) - 1;
|
||||
}
|
||||
|
||||
if (shader_gl_type == GL_VERTEX_SHADER)
|
||||
{
|
||||
strings[count] = vertex_boilerplate;
|
||||
|
@ -36,10 +36,6 @@
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-texture-2d.h"
|
||||
|
||||
#ifdef COGL_HAS_EGL_SUPPORT
|
||||
#include "cogl-egl-defines.h"
|
||||
#endif
|
||||
|
||||
struct _CoglTexture2D
|
||||
{
|
||||
CoglTexture _parent;
|
||||
@ -59,30 +55,23 @@ struct _CoglTexture2D
|
||||
GLenum gl_internal_format;
|
||||
/* The texture object number */
|
||||
GLuint gl_texture;
|
||||
GLenum gl_target;
|
||||
GLenum gl_legacy_texobj_min_filter;
|
||||
GLenum gl_legacy_texobj_mag_filter;
|
||||
GLint gl_legacy_texobj_wrap_mode_s;
|
||||
GLint gl_legacy_texobj_wrap_mode_t;
|
||||
CoglTexturePixel first_pixel;
|
||||
|
||||
struct {
|
||||
void *user_data;
|
||||
GDestroyNotify destroy;
|
||||
} egl_image_external;
|
||||
};
|
||||
|
||||
CoglTexture2D *
|
||||
_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
|
||||
CoglBool can_convert_in_place);
|
||||
|
||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
||||
/* NB: The reason we require the width, height and format to be passed
|
||||
* even though they may seem redundant is because GLES 1/2 don't
|
||||
* provide a way to query these properties. */
|
||||
CoglTexture2D *
|
||||
_cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat format,
|
||||
EGLImageKHR image,
|
||||
CoglError **error);
|
||||
#endif
|
||||
|
||||
CoglTexture2D *
|
||||
_cogl_texture_2d_create_base (CoglContext *ctx,
|
||||
int width,
|
||||
|
@ -110,6 +110,8 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
|
||||
tex_2d->mipmaps_dirty = TRUE;
|
||||
tex_2d->auto_mipmap = TRUE;
|
||||
|
||||
tex_2d->gl_target = GL_TEXTURE_2D;
|
||||
|
||||
tex_2d->is_foreign = FALSE;
|
||||
|
||||
ctx->driver_vtable->texture_2d_init (tex_2d);
|
||||
@ -236,12 +238,12 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
|
||||
* even though they may seem redundant is because GLES 1/2 don't
|
||||
* provide a way to query these properties. */
|
||||
CoglTexture2D *
|
||||
_cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat format,
|
||||
EGLImageKHR image,
|
||||
CoglError **error)
|
||||
cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat format,
|
||||
EGLImageKHR image,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglTextureLoader *loader;
|
||||
CoglTexture2D *tex;
|
||||
@ -430,11 +432,11 @@ cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx,
|
||||
EGL_WAYLAND_BUFFER_WL,
|
||||
buffer,
|
||||
NULL);
|
||||
tex = _cogl_egl_texture_2d_new_from_image (ctx,
|
||||
width, height,
|
||||
internal_format,
|
||||
image,
|
||||
error);
|
||||
tex = cogl_egl_texture_2d_new_from_image (ctx,
|
||||
width, height,
|
||||
internal_format,
|
||||
image,
|
||||
error);
|
||||
_cogl_egl_destroy_image (ctx, image);
|
||||
return tex;
|
||||
}
|
||||
@ -557,7 +559,7 @@ _cogl_texture_2d_get_gl_texture (CoglTexture *tex,
|
||||
GLuint handle;
|
||||
|
||||
if (out_gl_target)
|
||||
*out_gl_target = GL_TEXTURE_2D;
|
||||
*out_gl_target = tex_2d->gl_target;
|
||||
|
||||
handle = ctx->driver_vtable->texture_2d_get_gl_handle (tex_2d);
|
||||
|
||||
|
@ -40,6 +40,10 @@
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-bitmap.h"
|
||||
|
||||
#ifdef COGL_HAS_EGL_SUPPORT
|
||||
#include "cogl-egl-defines.h"
|
||||
#endif
|
||||
|
||||
COGL_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
@ -227,6 +231,40 @@ cogl_texture_2d_new_from_data (CoglContext *ctx,
|
||||
CoglTexture2D *
|
||||
cogl_texture_2d_new_from_bitmap (CoglBitmap *bitmap);
|
||||
|
||||
#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base)
|
||||
/* NB: The reason we require the width, height and format to be passed
|
||||
* even though they may seem redundant is because GLES 1/2 don't
|
||||
* provide a way to query these properties. */
|
||||
CoglTexture2D *
|
||||
cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglPixelFormat format,
|
||||
EGLImageKHR image,
|
||||
CoglError **error);
|
||||
|
||||
typedef gboolean (*CoglTexture2DEGLImageExternalAlloc) (CoglTexture2D *tex_2d,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
CoglTexture2D *
|
||||
cogl_texture_2d_new_from_egl_image_external (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglTexture2DEGLImageExternalAlloc alloc,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy,
|
||||
CoglError **error);
|
||||
|
||||
void
|
||||
cogl_texture_2d_egl_image_external_bind (CoglTexture2D *tex_2d);
|
||||
|
||||
void
|
||||
cogl_texture_2d_egl_image_external_alloc_finish (CoglTexture2D *tex_2d,
|
||||
void *user_data,
|
||||
GDestroyNotify destroy);
|
||||
#endif
|
||||
|
||||
COGL_END_DECLS
|
||||
|
||||
#endif /* __COGL_TEXTURE_2D_H */
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "cogl-spans.h"
|
||||
#include "cogl-meta-texture.h"
|
||||
#include "cogl-framebuffer.h"
|
||||
#include "cogl-texture-2d.h"
|
||||
|
||||
#ifdef COGL_HAS_EGL_SUPPORT
|
||||
#include "cogl-egl-defines.h"
|
||||
@ -154,7 +155,8 @@ typedef enum _CoglTextureSoureType {
|
||||
COGL_TEXTURE_SOURCE_TYPE_SIZED = 1,
|
||||
COGL_TEXTURE_SOURCE_TYPE_BITMAP,
|
||||
COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE,
|
||||
COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN
|
||||
COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN,
|
||||
COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL
|
||||
} CoglTextureSourceType;
|
||||
|
||||
typedef struct _CoglTextureLoader
|
||||
@ -179,6 +181,14 @@ typedef struct _CoglTextureLoader
|
||||
int height;
|
||||
CoglPixelFormat format;
|
||||
} egl_image;
|
||||
#endif
|
||||
#if defined (COGL_HAS_EGL_SUPPORT)
|
||||
struct {
|
||||
int width;
|
||||
int height;
|
||||
CoglTexture2DEGLImageExternalAlloc alloc;
|
||||
CoglPixelFormat format;
|
||||
} egl_image_external;
|
||||
#endif
|
||||
struct {
|
||||
int width;
|
||||
|
@ -160,6 +160,7 @@ _cogl_texture_free_loader (CoglTexture *texture)
|
||||
case COGL_TEXTURE_SOURCE_TYPE_SIZED:
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
|
||||
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
|
||||
break;
|
||||
case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
|
||||
cogl_object_unref (loader->src.bitmap.bitmap);
|
||||
|
@ -46,11 +46,21 @@
|
||||
#include "cogl-error-private.h"
|
||||
#include "cogl-util-gl-private.h"
|
||||
|
||||
#if defined (COGL_HAS_EGL_SUPPORT)
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
_cogl_texture_2d_gl_free (CoglTexture2D *tex_2d)
|
||||
{
|
||||
if (!tex_2d->is_foreign && tex_2d->gl_texture)
|
||||
_cogl_delete_gl_texture (tex_2d->gl_texture);
|
||||
|
||||
#if defined (COGL_HAS_EGL_SUPPORT)
|
||||
g_clear_pointer (&tex_2d->egl_image_external.user_data,
|
||||
tex_2d->egl_image_external.destroy);
|
||||
#endif
|
||||
}
|
||||
|
||||
CoglBool
|
||||
@ -101,6 +111,9 @@ _cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
|
||||
/* Wrap mode not yet set */
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
|
||||
tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
|
||||
|
||||
tex_2d->egl_image_external.user_data = NULL;
|
||||
tex_2d->egl_image_external.destroy = NULL;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
@ -439,6 +452,96 @@ allocate_from_gl_foreign (CoglTexture2D *tex_2d,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined (COGL_HAS_EGL_SUPPORT)
|
||||
static CoglBool
|
||||
allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
|
||||
CoglTextureLoader *loader,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||
CoglContext *ctx = tex->context;
|
||||
CoglPixelFormat internal_format = loader->src.egl_image_external.format;
|
||||
|
||||
_cogl_gl_util_clear_gl_errors (ctx);
|
||||
|
||||
GE (ctx, glActiveTexture (GL_TEXTURE0));
|
||||
GE (ctx, glGenTextures (1, &tex_2d->gl_texture));
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES,
|
||||
tex_2d->gl_texture));
|
||||
|
||||
if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
|
||||
{
|
||||
_cogl_set_error (error,
|
||||
COGL_TEXTURE_ERROR,
|
||||
COGL_TEXTURE_ERROR_BAD_PARAMETER,
|
||||
"Could not create a CoglTexture2D from a given "
|
||||
"EGLImage");
|
||||
GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
|
||||
GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
|
||||
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
|
||||
|
||||
if (!loader->src.egl_image_external.alloc (tex_2d,
|
||||
tex_2d->egl_image_external.user_data,
|
||||
error))
|
||||
{
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
GE (ctx, glDeleteTextures (1, &tex_2d->gl_texture));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
|
||||
|
||||
tex_2d->internal_format = internal_format;
|
||||
tex_2d->gl_target = GL_TEXTURE_EXTERNAL_OES;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglTexture2D *
|
||||
cogl_texture_2d_new_from_egl_image_external (CoglContext *ctx,
|
||||
int width,
|
||||
int height,
|
||||
CoglTexture2DEGLImageExternalAlloc alloc,
|
||||
gpointer user_data,
|
||||
GDestroyNotify destroy,
|
||||
CoglError **error)
|
||||
{
|
||||
CoglTextureLoader *loader;
|
||||
CoglTexture2D *tex_2d;
|
||||
CoglPixelFormat internal_format = COGL_PIXEL_FORMAT_ANY;
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints &
|
||||
COGL_RENDERER_CONSTRAINT_USES_EGL,
|
||||
NULL);
|
||||
|
||||
_COGL_RETURN_VAL_IF_FAIL (cogl_has_feature (ctx,
|
||||
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL),
|
||||
NULL);
|
||||
|
||||
loader = _cogl_texture_create_loader ();
|
||||
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL;
|
||||
loader->src.egl_image_external.width = width;
|
||||
loader->src.egl_image_external.height = height;
|
||||
loader->src.egl_image_external.alloc = alloc;
|
||||
loader->src.egl_image_external.format = internal_format;
|
||||
|
||||
tex_2d = _cogl_texture_2d_create_base (ctx, width, height,
|
||||
internal_format, loader);
|
||||
|
||||
|
||||
tex_2d->egl_image_external.user_data = user_data;
|
||||
tex_2d->egl_image_external.destroy = destroy;
|
||||
|
||||
return tex_2d;
|
||||
}
|
||||
#endif /* defined (COGL_HAS_EGL_SUPPORT) */
|
||||
|
||||
CoglBool
|
||||
_cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
||||
CoglError **error)
|
||||
@ -462,6 +565,8 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
|
||||
#endif
|
||||
case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
|
||||
return allocate_from_gl_foreign (tex_2d, loader, error);
|
||||
case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
|
||||
return allocate_custom_egl_image_external (tex_2d, loader, error);
|
||||
}
|
||||
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
@ -48,6 +48,7 @@
|
||||
|
||||
#include "cogl-texture-pixmap-x11-private.h"
|
||||
#include "cogl-texture-2d-private.h"
|
||||
#include "cogl-texture-2d.h"
|
||||
#include "cogl-error-private.h"
|
||||
#include "cogl-poll-private.h"
|
||||
|
||||
@ -290,6 +291,19 @@ error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
_cogl_winsys_egl_add_config_attributes (CoglDisplay *display,
|
||||
CoglFramebufferConfig *config,
|
||||
EGLint *attributes)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
attributes[i++] = EGL_SURFACE_TYPE;
|
||||
attributes[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static CoglBool
|
||||
_cogl_winsys_egl_display_setup (CoglDisplay *display,
|
||||
CoglError **error)
|
||||
@ -728,12 +742,12 @@ _cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
|
||||
COGL_PIXEL_FORMAT_RGB_888);
|
||||
|
||||
egl_tex_pixmap->texture = COGL_TEXTURE (
|
||||
_cogl_egl_texture_2d_new_from_image (ctx,
|
||||
tex->width,
|
||||
tex->height,
|
||||
texture_format,
|
||||
egl_tex_pixmap->image,
|
||||
NULL));
|
||||
cogl_egl_texture_2d_new_from_image (ctx,
|
||||
tex->width,
|
||||
tex->height,
|
||||
texture_format,
|
||||
egl_tex_pixmap->image,
|
||||
NULL));
|
||||
|
||||
tex_pixmap->winsys = egl_tex_pixmap;
|
||||
|
||||
@ -794,6 +808,7 @@ _cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap,
|
||||
static const CoglWinsysEGLVtable
|
||||
_cogl_winsys_egl_vtable =
|
||||
{
|
||||
.add_config_attributes = _cogl_winsys_egl_add_config_attributes,
|
||||
.display_setup = _cogl_winsys_egl_display_setup,
|
||||
.display_destroy = _cogl_winsys_egl_display_destroy,
|
||||
.context_created = _cogl_winsys_egl_context_created,
|
||||
|
@ -233,11 +233,11 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display,
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
int i = 0;
|
||||
|
||||
/* Let the platform add attributes first */
|
||||
if (egl_renderer->platform_vtable->add_config_attributes)
|
||||
i = egl_renderer->platform_vtable->add_config_attributes (display,
|
||||
config,
|
||||
attributes);
|
||||
/* Let the platform add attributes first, including setting the
|
||||
* EGL_SURFACE_TYPE */
|
||||
i = egl_renderer->platform_vtable->add_config_attributes (display,
|
||||
config,
|
||||
attributes);
|
||||
|
||||
if (config->need_stencil)
|
||||
{
|
||||
@ -269,9 +269,6 @@ egl_attributes_from_framebuffer_config (CoglDisplay *display,
|
||||
EGL_OPENGL_ES_BIT :
|
||||
EGL_OPENGL_ES2_BIT);
|
||||
|
||||
attributes[i++] = EGL_SURFACE_TYPE;
|
||||
attributes[i++] = EGL_WINDOW_BIT;
|
||||
|
||||
if (config->samples_per_pixel)
|
||||
{
|
||||
attributes[i++] = EGL_SAMPLE_BUFFERS;
|
||||
|
@ -2,6 +2,7 @@ NULL =
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_builddir)/cogl \
|
||||
-DCOGL_DISABLE_DEPRECATED
|
||||
|
||||
test_conformance_CPPFLAGS = \
|
||||
|
15
configure.ac
15
configure.ac
@ -1,8 +1,8 @@
|
||||
AC_PREREQ(2.62)
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [22])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
m4_define([mutter_minor_version], [23])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -64,6 +64,7 @@ CANBERRA_GTK_VERSION=0.26
|
||||
LIBWACOM_VERSION=0.13
|
||||
|
||||
MUTTER_PC_MODULES="
|
||||
egl
|
||||
gtk+-3.0 >= 3.19.8
|
||||
gio-unix-2.0 >= 2.35.1
|
||||
pango >= 1.2.0
|
||||
@ -256,6 +257,15 @@ AS_IF([test "$have_native_backend" = "yes"], [
|
||||
])
|
||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
|
||||
|
||||
AC_ARG_ENABLE(egl-device,
|
||||
AS_HELP_STRING([--enable-egl-device], [enable support for EGLDevice on top of KMS]),
|
||||
enable_egl_device=yes,
|
||||
enable_egl_device=no
|
||||
)
|
||||
AS_IF([test "$enable_egl_device" = "yes"], [
|
||||
AC_DEFINE([HAVE_EGL_DEVICE],[1], [Defined if EGLDevice support is enabled])
|
||||
])
|
||||
|
||||
MUTTER_WAYLAND_MODULES="wayland-server >= 1.6.90"
|
||||
|
||||
AC_ARG_ENABLE(wayland,
|
||||
@ -483,6 +493,7 @@ mutter-$VERSION
|
||||
Session management: ${found_sm}
|
||||
Wayland: ${have_wayland}
|
||||
Native (KMS) backend: ${have_native_backend}
|
||||
EGLDevice: ${enable_egl_device}
|
||||
"
|
||||
|
||||
|
||||
|
851
po/nb.po
851
po/nb.po
@ -1,13 +1,14 @@
|
||||
# Norwegian bokmål translation of mutter.
|
||||
# Copyright © 2002-2004 Free Software Foundation, Inc.
|
||||
# Kjartan Maraas <kmaraas@gnome.org>, 2002-2015.
|
||||
# Kjartan Maraas <kmaraas@gnome.org>, 2002-2016.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter 3.15.x\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2015-03-19 21:23+0100\n"
|
||||
"PO-Revision-Date: 2015-03-19 21:24+0100\n"
|
||||
"Project-Id-Version: mutter 3.23.x\n"
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2016-11-21 08:47+0100\n"
|
||||
"PO-Revision-Date: 2016-10-15 17:12+0200\n"
|
||||
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
|
||||
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
|
||||
"Language: nb\n"
|
||||
@ -15,469 +16,47 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:1
|
||||
msgid "Navigation"
|
||||
msgstr "Navigering"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:2
|
||||
msgid "Move window to workspace 1"
|
||||
msgstr "Flytt vindu til arbeidsområde 1"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:3
|
||||
msgid "Move window to workspace 2"
|
||||
msgstr "Flytt vindu til arbeidsområde 2"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:4
|
||||
msgid "Move window to workspace 3"
|
||||
msgstr "Flytt vindu til arbeidsområde 3"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:5
|
||||
msgid "Move window to workspace 4"
|
||||
msgstr "Flytt vindu til arbeidsområde 4"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:6
|
||||
msgid "Move window to last workspace"
|
||||
msgstr "Flytt vindu til siste arbeidsområde"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:7
|
||||
msgid "Move window one workspace to the left"
|
||||
msgstr "Flytt vindu ett arbeidsområde til venstre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:8
|
||||
msgid "Move window one workspace to the right"
|
||||
msgstr "Flytt vindu ett arbeidsområde til høyre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:9
|
||||
msgid "Move window one workspace up"
|
||||
msgstr "Flytt vindu ett arbeidsområde opp"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:10
|
||||
msgid "Move window one workspace down"
|
||||
msgstr "Flytt vindu ett arbeidsområde ned"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:11
|
||||
msgid "Move window one monitor to the left"
|
||||
msgstr "Flytt vindu en skjerm til venstre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:12
|
||||
msgid "Move window one monitor to the right"
|
||||
msgstr "Flytt vindu en skjerm til høyre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:13
|
||||
msgid "Move window one monitor up"
|
||||
msgstr "Flytt vindu en skjerm opp"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:14
|
||||
msgid "Move window one monitor down"
|
||||
msgstr "Flytt vindu en skjerm ned"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:15
|
||||
msgid "Switch applications"
|
||||
msgstr "Bytt programmer"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:16
|
||||
msgid "Switch to previous application"
|
||||
msgstr "Bytt til forrige program"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:17
|
||||
msgid "Switch windows"
|
||||
msgstr "Bytt vinduer"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:18
|
||||
msgid "Switch to previous window"
|
||||
msgstr "Bytt forrige vindu"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:19
|
||||
msgid "Switch windows of an application"
|
||||
msgstr "Bytt mellom et programs vinduer"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:20
|
||||
msgid "Switch to previous window of an application"
|
||||
msgstr "Bytt til forrige vindu i et program"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:21
|
||||
msgid "Switch system controls"
|
||||
msgstr "Bytt systemkontroller"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:22
|
||||
msgid "Switch to previous system control"
|
||||
msgstr "Bytt til forrige systemkontroll"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:23
|
||||
msgid "Switch windows directly"
|
||||
msgstr "Bytt vinduer direkte"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:24
|
||||
msgid "Switch directly to previous window"
|
||||
msgstr "Bytt direkte til forrige vindu"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:25
|
||||
msgid "Switch windows of an app directly"
|
||||
msgstr "Bytt mellom et programs vinduer direkte"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:26
|
||||
msgid "Switch directly to previous window of an app"
|
||||
msgstr "Bytt direkte til forrive vindu i et program"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:27
|
||||
msgid "Switch system controls directly"
|
||||
msgstr "Bytt systemkontroller direkte"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:28
|
||||
msgid "Switch directly to previous system control"
|
||||
msgstr "Bytt direkte til forrige systemkontroll"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:29
|
||||
msgid "Hide all normal windows"
|
||||
msgstr "Skjul alle normale vinduer"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:30
|
||||
msgid "Switch to workspace 1"
|
||||
msgstr "Bytt til arbeidsområde 1"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:31
|
||||
msgid "Switch to workspace 2"
|
||||
msgstr "Bytt til arbeidsområde 2"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:32
|
||||
msgid "Switch to workspace 3"
|
||||
msgstr "Bytt til arbeidsområde 3"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:33
|
||||
msgid "Switch to workspace 4"
|
||||
msgstr "Bytt til arbeidsområde 4"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:34
|
||||
msgid "Switch to last workspace"
|
||||
msgstr "Bytt til siste arbeidsområde"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:35
|
||||
msgid "Move to workspace left"
|
||||
msgstr "Flytt til arbeidsområdet til venstre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:36
|
||||
msgid "Move to workspace right"
|
||||
msgstr "Flytt til arbeidsområdet til høyre"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:37
|
||||
msgid "Move to workspace above"
|
||||
msgstr "Flytt til arbeidsområdet over"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:38
|
||||
msgid "Move to workspace below"
|
||||
msgstr "Flytt til arbeidsområdet under"
|
||||
|
||||
#: ../data/50-mutter-system.xml.in.h:1
|
||||
msgid "System"
|
||||
msgstr "System"
|
||||
|
||||
#: ../data/50-mutter-system.xml.in.h:2
|
||||
msgid "Show the run command prompt"
|
||||
msgstr "Vis kommandolinje"
|
||||
|
||||
#: ../data/50-mutter-system.xml.in.h:3
|
||||
msgid "Show the activities overview"
|
||||
msgstr "Vis oversikt over aktiviteter"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:1
|
||||
msgid "Windows"
|
||||
msgstr "Vinduer"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:2
|
||||
msgid "Activate the window menu"
|
||||
msgstr "Aktiver vindumenyen"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:3
|
||||
msgid "Toggle fullscreen mode"
|
||||
msgstr "Slå av/på fullskjermmodus"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:4
|
||||
msgid "Toggle maximization state"
|
||||
msgstr "Endre tilstand for maksimering"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:5
|
||||
msgid "Maximize window"
|
||||
msgstr "Maksimer vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:6
|
||||
msgid "Restore window"
|
||||
msgstr "Gjenopprett vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:7
|
||||
msgid "Toggle shaded state"
|
||||
msgstr "Endre tilstand for skyggelegging"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:8
|
||||
msgid "Close window"
|
||||
msgstr "Lukk vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:9
|
||||
msgid "Hide window"
|
||||
msgstr "Skjul vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:10
|
||||
msgid "Move window"
|
||||
msgstr "Flytt vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:11
|
||||
msgid "Resize window"
|
||||
msgstr "Endre størrelse på vindu"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:12
|
||||
msgid "Toggle window on all workspaces or one"
|
||||
msgstr "Slå av/på om vinduet skal vises på alle arbeidsområder eller bare ett"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:13
|
||||
msgid "Raise window if covered, otherwise lower it"
|
||||
msgstr "Hev vindu hvis skjult av et annet vindu, senk det ellers"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:14
|
||||
msgid "Raise window above other windows"
|
||||
msgstr "Hev vinduet over andre vinduer"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:15
|
||||
msgid "Lower window below other windows"
|
||||
msgstr "Senk vinduet under andre vinduer"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:16
|
||||
msgid "Maximize window vertically"
|
||||
msgstr "Maksimer vinduet vertikalt"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:17
|
||||
msgid "Maximize window horizontally"
|
||||
msgstr "Maksimer vinduet horisontalt"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:18
|
||||
msgid "View split on left"
|
||||
msgstr "Visning delt til venstre"
|
||||
|
||||
#: ../data/50-mutter-windows.xml.in.h:19
|
||||
msgid "View split on right"
|
||||
msgstr "Visning delt til høyre"
|
||||
|
||||
#: ../data/mutter.desktop.in.h:1
|
||||
msgid "Mutter"
|
||||
msgstr "Mutter"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:1
|
||||
msgid "Modifier to use for extended window management operations"
|
||||
msgstr "Endringstast som skal brukes for utvidede vindushåndteringsoperasjoner"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:2
|
||||
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."
|
||||
msgstr ""
|
||||
"Denne tasten vil initiere «overlay», som er en kombinasjon av vindusoversikt "
|
||||
"og et system for å starte programmer. Forvalget er ment å være «Windows-"
|
||||
"tasten» på PC-maskinvare. Det forventes at denne bindingen er satt til "
|
||||
"forvalg eller en tom streng."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:3
|
||||
msgid "Attach modal dialogs"
|
||||
msgstr "Fest modale dialoger"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:4
|
||||
msgid ""
|
||||
"When true, instead of having independent titlebars, modal dialogs appear "
|
||||
"attached to the titlebar of the parent window and are moved together with "
|
||||
"the parent window."
|
||||
msgstr ""
|
||||
"Hvis denne er satt til sann vil modale dialoger vises festet til "
|
||||
"tittellinjen på opphavsvinduet og flyttes sammen med dette i stedet for å ha "
|
||||
"individuelle tittellinjer."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:5
|
||||
msgid "Enable edge tiling when dropping windows on screen edges"
|
||||
msgstr "Slå på kantflising ved slipp av vinduer på skjermkantene"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:6
|
||||
msgid ""
|
||||
"If enabled, dropping windows on vertical screen edges maximizes them "
|
||||
"vertically and resizes them horizontally to cover half of the available "
|
||||
"area. Dropping windows on the top screen edge maximizes them completely."
|
||||
msgstr ""
|
||||
"Maksimerer vinduer vertikalt og endrer størrelse horisontalt slik at de "
|
||||
"dekker halve det tilgjengeligeområdet hvis de slippes på vertikale "
|
||||
"skjermkanter. Hvis vindu slippes på øverste kant av skjermen maksimeres de "
|
||||
"fullstendig."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:7
|
||||
msgid "Workspaces are managed dynamically"
|
||||
msgstr "Arbeidsområder håndteres dynamisk"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:8
|
||||
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)."
|
||||
msgstr ""
|
||||
"Bestemmer om arbeidsområder skal håndteres dynamisk eller om det er et fast "
|
||||
"antall arbeidsområder (bestemt av num-workspaces nøkkelen i org.gnome."
|
||||
"desktop.wm.preferences)."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:9
|
||||
msgid "Workspaces only on primary"
|
||||
msgstr "Arbeidsområder kun på primær skjerm"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:10
|
||||
msgid ""
|
||||
"Determines whether workspace switching should happen for windows on all "
|
||||
"monitors or only for windows on the primary monitor."
|
||||
msgstr ""
|
||||
"Bestemmer om bytting mellom arbeidsområder skal skje for vinduer på alle "
|
||||
"skjermer eller kun på primær skjerm."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:11
|
||||
msgid "No tab popup"
|
||||
msgstr "Ingen tabulatordialog"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:12
|
||||
msgid ""
|
||||
"Determines whether the use of popup and highlight frame should be disabled "
|
||||
"for window cycling."
|
||||
msgstr ""
|
||||
"Bestemmer om bruk av dialog og uthevingsramme skal slås av for bytting "
|
||||
"mellom vinduer."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:13
|
||||
msgid "Delay focus changes until the pointer stops moving"
|
||||
msgstr "Utsett fokusendringer til pekeren slutter å bevege seg"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:14
|
||||
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."
|
||||
msgstr ""
|
||||
"Hvis denne settes til «true» og fokusmodus er enten «sloppy» eller «mouse» "
|
||||
"så vil fokus ikke endres med en gang markøren kommer inn i et vindu, men i "
|
||||
"stedet når markørens bevegelse stopper."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:15
|
||||
msgid "Draggable border width"
|
||||
msgstr "Bredde på drakant"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:16
|
||||
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."
|
||||
msgstr ""
|
||||
"Total mengde med drakant. Hvis temas synlige kanter ikke er nok vil usynlige "
|
||||
"kanter legges til for å imøtekomme denne verdien."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:17
|
||||
msgid "Auto maximize nearly monitor sized windows"
|
||||
msgstr "Maksimer vinduer automatisk hvis de er nesten like store som skjermen"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:18
|
||||
msgid ""
|
||||
"If enabled, new windows that are initially the size of the monitor "
|
||||
"automatically get maximized."
|
||||
msgstr ""
|
||||
"Nye vinduer som i utgangspunktet er samme størrelse som skjermen vil "
|
||||
"automatisk bli maksimert hvis denne slås på."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:19
|
||||
msgid "Place new windows in the center"
|
||||
msgstr "Plasser nye vinduer i senter"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:20
|
||||
msgid ""
|
||||
"When true, the new windows will always be put in the center of the active "
|
||||
"screen of the monitor."
|
||||
msgstr ""
|
||||
"Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt område "
|
||||
"på skjermen."
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:21
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "Fjern vindu fra tabulatordialog"
|
||||
|
||||
#: ../data/org.gnome.mutter.gschema.xml.in.h:22
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Avbryt tabulatordialog"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:1
|
||||
msgid "Switch to VT 1"
|
||||
msgstr "Bytt til VT 1"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:2
|
||||
msgid "Switch to VT 2"
|
||||
msgstr "Bytt til VT 2"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:3
|
||||
msgid "Switch to VT 3"
|
||||
msgstr "Bytt til VT 3"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:4
|
||||
msgid "Switch to VT 4"
|
||||
msgstr "Bytt til VT 4"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:5
|
||||
msgid "Switch to VT 5"
|
||||
msgstr "Bytt til VT 5"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:6
|
||||
msgid "Switch to VT 6"
|
||||
msgstr "Bytt til VT 6"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:7
|
||||
msgid "Switch to VT 7"
|
||||
msgstr "Bytt til VT 7"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:8
|
||||
msgid "Switch to VT 8"
|
||||
msgstr "Bytt til VT 8"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:9
|
||||
msgid "Switch to VT 9"
|
||||
msgstr "Bytt til VT 9"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:10
|
||||
msgid "Switch to VT 10"
|
||||
msgstr "Bytt til VT 10"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:11
|
||||
msgid "Switch to VT 11"
|
||||
msgstr "Bytt til VT 11"
|
||||
|
||||
#: ../data/org.gnome.mutter.wayland.gschema.xml.in.h:12
|
||||
msgid "Switch to VT 12"
|
||||
msgstr "Bytt til VT 12"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:364
|
||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
#. * mapping through the available outputs.
|
||||
#.
|
||||
#: ../src/backends/meta-input-settings.c:1739
|
||||
msgid "Switch monitor"
|
||||
msgstr "Bytt skjerm"
|
||||
|
||||
#: ../src/backends/meta-input-settings.c:1741
|
||||
msgid "Show on-screen help"
|
||||
msgstr "Vis hjelp på skjermen"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:514
|
||||
msgid "Built-in display"
|
||||
msgstr "Innebygget skjerm"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:391
|
||||
#: ../src/backends/meta-monitor-manager.c:537
|
||||
msgid "Unknown"
|
||||
msgstr "Ukjent"
|
||||
|
||||
#: ../src/backends/meta-monitor-manager.c:393
|
||||
#: ../src/backends/meta-monitor-manager.c:539
|
||||
msgid "Unknown Display"
|
||||
msgstr "Ukjent skjerm"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: ../src/backends/meta-monitor-manager.c:401
|
||||
#: ../src/backends/meta-monitor-manager.c:547
|
||||
#, c-format
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: ../src/compositor/compositor.c:456
|
||||
#: ../src/compositor/compositor.c:471
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display \"%s"
|
||||
"\"."
|
||||
msgstr "En annen compositing manager kjører skjerm %i på display «%s»."
|
||||
|
||||
#: ../src/core/bell.c:185
|
||||
#: ../src/core/bell.c:194
|
||||
msgid "Bell event"
|
||||
msgstr "Klokkehendelse"
|
||||
|
||||
@ -498,48 +77,52 @@ msgstr ""
|
||||
"Du kan velge å vente en kort stund for å se om det fortsetter eller tvinge "
|
||||
"programmet til å avslutte helt."
|
||||
|
||||
#: ../src/core/delete.c:141
|
||||
msgid "_Wait"
|
||||
msgstr "_Vent"
|
||||
|
||||
#: ../src/core/delete.c:141
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Tvungen nedstenging"
|
||||
|
||||
#: ../src/core/display.c:562
|
||||
#: ../src/core/delete.c:141
|
||||
msgid "_Wait"
|
||||
msgstr "_Vent"
|
||||
|
||||
#: ../src/core/display.c:590
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
|
||||
|
||||
#: ../src/core/main.c:176
|
||||
#: ../src/core/main.c:182
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "Deaktiver tilkobling til sesjonshåndtereren"
|
||||
|
||||
#: ../src/core/main.c:182
|
||||
#: ../src/core/main.c:188
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "Erstatt kjørende vindushåndterer"
|
||||
|
||||
#: ../src/core/main.c:188
|
||||
#: ../src/core/main.c:194
|
||||
msgid "Specify session management ID"
|
||||
msgstr "Oppgi sesjonshåndterings-ID"
|
||||
|
||||
#: ../src/core/main.c:193
|
||||
#: ../src/core/main.c:199
|
||||
msgid "X Display to use"
|
||||
msgstr "X-skjerm som skal brukes"
|
||||
|
||||
#: ../src/core/main.c:199
|
||||
#: ../src/core/main.c:205
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "Initier sesjonen fra en lagret fil"
|
||||
|
||||
#: ../src/core/main.c:205
|
||||
#: ../src/core/main.c:211
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "Gjør X-kall synkrone"
|
||||
|
||||
#: ../src/core/main.c:212
|
||||
#: ../src/core/main.c:218
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "Kjør som en wayland-kompositør"
|
||||
|
||||
#: ../src/core/main.c:220
|
||||
#: ../src/core/main.c:224
|
||||
msgid "Run as a nested compositor"
|
||||
msgstr "Kjør som en nøstet kompositør"
|
||||
|
||||
#: ../src/core/main.c:232
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Kjør som en full skjermtjener, heller enn nøstet"
|
||||
|
||||
@ -565,27 +148,34 @@ msgstr "Skriv versjonsnummer"
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Mutter-tillegg som skal brukes"
|
||||
|
||||
#: ../src/core/prefs.c:2004
|
||||
#: ../src/core/prefs.c:1997
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Arbeidsområde %d"
|
||||
|
||||
#: ../src/core/screen.c:525
|
||||
#: ../src/core/screen.c:521
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Display \"%s\" already has a window manager; try using the --replace option "
|
||||
"to replace the current window manager."
|
||||
msgstr "Skjerm «%s» har allerede en vindushåndterer; prøv å bruke flagget --replace for å erstatte aktiv vindushåndterer."
|
||||
msgstr ""
|
||||
"Skjerm «%s» har allerede en vindushåndterer; prøv å bruke flagget --replace "
|
||||
"for å erstatte aktiv vindushåndterer."
|
||||
|
||||
#: ../src/core/screen.c:607
|
||||
#: ../src/core/screen.c:606
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Skjerm %d på display «%s» er ugyldig\n"
|
||||
|
||||
#: ../src/core/util.c:118
|
||||
#: ../src/core/util.c:120
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
|
||||
|
||||
#: ../src/wayland/meta-wayland-tablet-pad.c:563
|
||||
#, c-format
|
||||
msgid "Mode Switch: Mode %d"
|
||||
msgstr "Modusbytte: Modus %d"
|
||||
|
||||
#: ../src/x11/session.c:1815
|
||||
msgid ""
|
||||
"These windows do not support "save current setup" and will have to "
|
||||
@ -594,11 +184,346 @@ msgstr ""
|
||||
"Disse vinduene støtter ikke "lagre aktiv konfigurasjon"og vil "
|
||||
"måtte startes på nytt manuelt neste gang du logger inn."
|
||||
|
||||
#: ../src/x11/window-props.c:549
|
||||
#: ../src/x11/window-props.c:559
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (på %s)"
|
||||
|
||||
#~ msgid "Move window to workspace 1"
|
||||
#~ msgstr "Flytt vindu til arbeidsområde 1"
|
||||
|
||||
#~ msgid "Move window to workspace 2"
|
||||
#~ msgstr "Flytt vindu til arbeidsområde 2"
|
||||
|
||||
#~ msgid "Move window to workspace 3"
|
||||
#~ msgstr "Flytt vindu til arbeidsområde 3"
|
||||
|
||||
#~ msgid "Move window to workspace 4"
|
||||
#~ msgstr "Flytt vindu til arbeidsområde 4"
|
||||
|
||||
#~ msgid "Move window to last workspace"
|
||||
#~ msgstr "Flytt vindu til siste arbeidsområde"
|
||||
|
||||
#~ msgid "Move window one workspace to the left"
|
||||
#~ msgstr "Flytt vindu ett arbeidsområde til venstre"
|
||||
|
||||
#~ msgid "Move window one workspace to the right"
|
||||
#~ msgstr "Flytt vindu ett arbeidsområde til høyre"
|
||||
|
||||
#~ msgid "Move window one workspace up"
|
||||
#~ msgstr "Flytt vindu ett arbeidsområde opp"
|
||||
|
||||
#~ msgid "Move window one workspace down"
|
||||
#~ msgstr "Flytt vindu ett arbeidsområde ned"
|
||||
|
||||
#~ msgid "Move window one monitor to the left"
|
||||
#~ msgstr "Flytt vindu en skjerm til venstre"
|
||||
|
||||
#~ msgid "Move window one monitor to the right"
|
||||
#~ msgstr "Flytt vindu en skjerm til høyre"
|
||||
|
||||
#~ msgid "Move window one monitor up"
|
||||
#~ msgstr "Flytt vindu en skjerm opp"
|
||||
|
||||
#~ msgid "Move window one monitor down"
|
||||
#~ msgstr "Flytt vindu en skjerm ned"
|
||||
|
||||
#~ msgid "Switch applications"
|
||||
#~ msgstr "Bytt programmer"
|
||||
|
||||
#~ msgid "Switch to previous application"
|
||||
#~ msgstr "Bytt til forrige program"
|
||||
|
||||
#~ msgid "Switch windows"
|
||||
#~ msgstr "Bytt vinduer"
|
||||
|
||||
#~ msgid "Switch to previous window"
|
||||
#~ msgstr "Bytt forrige vindu"
|
||||
|
||||
#~ msgid "Switch windows of an application"
|
||||
#~ msgstr "Bytt mellom et programs vinduer"
|
||||
|
||||
#~ msgid "Switch to previous window of an application"
|
||||
#~ msgstr "Bytt til forrige vindu i et program"
|
||||
|
||||
#~ msgid "Switch to previous system control"
|
||||
#~ msgstr "Bytt til forrige systemkontroll"
|
||||
|
||||
#~ msgid "Switch windows directly"
|
||||
#~ msgstr "Bytt vinduer direkte"
|
||||
|
||||
#~ msgid "Switch directly to previous window"
|
||||
#~ msgstr "Bytt direkte til forrige vindu"
|
||||
|
||||
#~ msgid "Switch windows of an app directly"
|
||||
#~ msgstr "Bytt mellom et programs vinduer direkte"
|
||||
|
||||
#~ msgid "Switch directly to previous window of an app"
|
||||
#~ msgstr "Bytt direkte til forrive vindu i et program"
|
||||
|
||||
#~ msgid "Switch system controls directly"
|
||||
#~ msgstr "Bytt systemkontroller direkte"
|
||||
|
||||
#~ msgid "Switch directly to previous system control"
|
||||
#~ msgstr "Bytt direkte til forrige systemkontroll"
|
||||
|
||||
#~ msgid "Hide all normal windows"
|
||||
#~ msgstr "Skjul alle normale vinduer"
|
||||
|
||||
#~ msgid "Switch to workspace 1"
|
||||
#~ msgstr "Bytt til arbeidsområde 1"
|
||||
|
||||
#~ msgid "Switch to workspace 2"
|
||||
#~ msgstr "Bytt til arbeidsområde 2"
|
||||
|
||||
#~ msgid "Switch to workspace 3"
|
||||
#~ msgstr "Bytt til arbeidsområde 3"
|
||||
|
||||
#~ msgid "Switch to workspace 4"
|
||||
#~ msgstr "Bytt til arbeidsområde 4"
|
||||
|
||||
#~ msgid "Switch to last workspace"
|
||||
#~ msgstr "Bytt til siste arbeidsområde"
|
||||
|
||||
#~ msgid "Move to workspace left"
|
||||
#~ msgstr "Flytt til arbeidsområdet til venstre"
|
||||
|
||||
#~ msgid "Move to workspace right"
|
||||
#~ msgstr "Flytt til arbeidsområdet til høyre"
|
||||
|
||||
#~ msgid "Move to workspace above"
|
||||
#~ msgstr "Flytt til arbeidsområdet over"
|
||||
|
||||
#~ msgid "Move to workspace below"
|
||||
#~ msgstr "Flytt til arbeidsområdet under"
|
||||
|
||||
#~ msgid "System"
|
||||
#~ msgstr "System"
|
||||
|
||||
#~ msgid "Show the run command prompt"
|
||||
#~ msgstr "Vis kommandolinje"
|
||||
|
||||
#~ msgid "Show the activities overview"
|
||||
#~ msgstr "Vis oversikt over aktiviteter"
|
||||
|
||||
#~ msgid "Windows"
|
||||
#~ msgstr "Vinduer"
|
||||
|
||||
#~ msgid "Activate the window menu"
|
||||
#~ msgstr "Aktiver vindumenyen"
|
||||
|
||||
#~ msgid "Toggle fullscreen mode"
|
||||
#~ msgstr "Slå av/på fullskjermmodus"
|
||||
|
||||
#~ msgid "Toggle maximization state"
|
||||
#~ msgstr "Endre tilstand for maksimering"
|
||||
|
||||
#~ msgid "Maximize window"
|
||||
#~ msgstr "Maksimer vindu"
|
||||
|
||||
#~ msgid "Restore window"
|
||||
#~ msgstr "Gjenopprett vindu"
|
||||
|
||||
#~ msgid "Toggle shaded state"
|
||||
#~ msgstr "Endre tilstand for skyggelegging"
|
||||
|
||||
#~ msgid "Close window"
|
||||
#~ msgstr "Lukk vindu"
|
||||
|
||||
#~ msgid "Hide window"
|
||||
#~ msgstr "Skjul vindu"
|
||||
|
||||
#~ msgid "Move window"
|
||||
#~ msgstr "Flytt vindu"
|
||||
|
||||
#~ msgid "Resize window"
|
||||
#~ msgstr "Endre størrelse på vindu"
|
||||
|
||||
#~ msgid "Toggle window on all workspaces or one"
|
||||
#~ msgstr ""
|
||||
#~ "Slå av/på om vinduet skal vises på alle arbeidsområder eller bare ett"
|
||||
|
||||
#~ msgid "Raise window if covered, otherwise lower it"
|
||||
#~ msgstr "Hev vindu hvis skjult av et annet vindu, senk det ellers"
|
||||
|
||||
#~ msgid "Raise window above other windows"
|
||||
#~ msgstr "Hev vinduet over andre vinduer"
|
||||
|
||||
#~ msgid "Lower window below other windows"
|
||||
#~ msgstr "Senk vinduet under andre vinduer"
|
||||
|
||||
#~ msgid "Maximize window vertically"
|
||||
#~ msgstr "Maksimer vinduet vertikalt"
|
||||
|
||||
#~ msgid "Maximize window horizontally"
|
||||
#~ msgstr "Maksimer vinduet horisontalt"
|
||||
|
||||
#~ msgid "View split on left"
|
||||
#~ msgstr "Visning delt til venstre"
|
||||
|
||||
#~ msgid "View split on right"
|
||||
#~ msgstr "Visning delt til høyre"
|
||||
|
||||
#~ msgid "Mutter"
|
||||
#~ msgstr "Mutter"
|
||||
|
||||
#~ msgid "Modifier to use for extended window management operations"
|
||||
#~ msgstr ""
|
||||
#~ "Endringstast som skal brukes for utvidede vindushåndteringsoperasjoner"
|
||||
|
||||
#~ 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."
|
||||
#~ msgstr ""
|
||||
#~ "Denne tasten vil initiere «overlay», som er en kombinasjon av "
|
||||
#~ "vindusoversikt og et system for å starte programmer. Forvalget er ment å "
|
||||
#~ "være «Windows-tasten» på PC-maskinvare. Det forventes at denne bindingen "
|
||||
#~ "er satt til forvalg eller en tom streng."
|
||||
|
||||
#~ msgid "Attach modal dialogs"
|
||||
#~ msgstr "Fest modale dialoger"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "When true, instead of having independent titlebars, modal dialogs appear "
|
||||
#~ "attached to the titlebar of the parent window and are moved together with "
|
||||
#~ "the parent window."
|
||||
#~ msgstr ""
|
||||
#~ "Hvis denne er satt til sann vil modale dialoger vises festet til "
|
||||
#~ "tittellinjen på opphavsvinduet og flyttes sammen med dette i stedet for å "
|
||||
#~ "ha individuelle tittellinjer."
|
||||
|
||||
#~ msgid "Enable edge tiling when dropping windows on screen edges"
|
||||
#~ msgstr "Slå på kantflising ved slipp av vinduer på skjermkantene"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If enabled, dropping windows on vertical screen edges maximizes them "
|
||||
#~ "vertically and resizes them horizontally to cover half of the available "
|
||||
#~ "area. Dropping windows on the top screen edge maximizes them completely."
|
||||
#~ msgstr ""
|
||||
#~ "Maksimerer vinduer vertikalt og endrer størrelse horisontalt slik at de "
|
||||
#~ "dekker halve det tilgjengeligeområdet hvis de slippes på vertikale "
|
||||
#~ "skjermkanter. Hvis vindu slippes på øverste kant av skjermen maksimeres "
|
||||
#~ "de fullstendig."
|
||||
|
||||
#~ msgid "Workspaces are managed dynamically"
|
||||
#~ msgstr "Arbeidsområder håndteres dynamisk"
|
||||
|
||||
#~ 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)."
|
||||
#~ msgstr ""
|
||||
#~ "Bestemmer om arbeidsområder skal håndteres dynamisk eller om det er et "
|
||||
#~ "fast antall arbeidsområder (bestemt av num-workspaces nøkkelen i org."
|
||||
#~ "gnome.desktop.wm.preferences)."
|
||||
|
||||
#~ msgid "Workspaces only on primary"
|
||||
#~ msgstr "Arbeidsområder kun på primær skjerm"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Determines whether workspace switching should happen for windows on all "
|
||||
#~ "monitors or only for windows on the primary monitor."
|
||||
#~ msgstr ""
|
||||
#~ "Bestemmer om bytting mellom arbeidsområder skal skje for vinduer på alle "
|
||||
#~ "skjermer eller kun på primær skjerm."
|
||||
|
||||
#~ msgid "No tab popup"
|
||||
#~ msgstr "Ingen tabulatordialog"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Determines whether the use of popup and highlight frame should be "
|
||||
#~ "disabled for window cycling."
|
||||
#~ msgstr ""
|
||||
#~ "Bestemmer om bruk av dialog og uthevingsramme skal slås av for bytting "
|
||||
#~ "mellom vinduer."
|
||||
|
||||
#~ msgid "Delay focus changes until the pointer stops moving"
|
||||
#~ msgstr "Utsett fokusendringer til pekeren slutter å bevege seg"
|
||||
|
||||
#~ 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."
|
||||
#~ msgstr ""
|
||||
#~ "Hvis denne settes til «true» og fokusmodus er enten «sloppy» eller "
|
||||
#~ "«mouse» så vil fokus ikke endres med en gang markøren kommer inn i et "
|
||||
#~ "vindu, men i stedet når markørens bevegelse stopper."
|
||||
|
||||
#~ msgid "Draggable border width"
|
||||
#~ msgstr "Bredde på drakant"
|
||||
|
||||
#~ 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."
|
||||
#~ msgstr ""
|
||||
#~ "Total mengde med drakant. Hvis temas synlige kanter ikke er nok vil "
|
||||
#~ "usynlige kanter legges til for å imøtekomme denne verdien."
|
||||
|
||||
#~ msgid "Auto maximize nearly monitor sized windows"
|
||||
#~ msgstr ""
|
||||
#~ "Maksimer vinduer automatisk hvis de er nesten like store som skjermen"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "If enabled, new windows that are initially the size of the monitor "
|
||||
#~ "automatically get maximized."
|
||||
#~ msgstr ""
|
||||
#~ "Nye vinduer som i utgangspunktet er samme størrelse som skjermen vil "
|
||||
#~ "automatisk bli maksimert hvis denne slås på."
|
||||
|
||||
#~ msgid "Place new windows in the center"
|
||||
#~ msgstr "Plasser nye vinduer i senter"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "When true, the new windows will always be put in the center of the active "
|
||||
#~ "screen of the monitor."
|
||||
#~ msgstr ""
|
||||
#~ "Når denne er «true» vil mye vinduer alltid plasseres midt på aktivt "
|
||||
#~ "område på skjermen."
|
||||
|
||||
#~ msgid "Select window from tab popup"
|
||||
#~ msgstr "Fjern vindu fra tabulatordialog"
|
||||
|
||||
#~ msgid "Cancel tab popup"
|
||||
#~ msgstr "Avbryt tabulatordialog"
|
||||
|
||||
#~ msgid "Switch to VT 1"
|
||||
#~ msgstr "Bytt til VT 1"
|
||||
|
||||
#~ msgid "Switch to VT 2"
|
||||
#~ msgstr "Bytt til VT 2"
|
||||
|
||||
#~ msgid "Switch to VT 3"
|
||||
#~ msgstr "Bytt til VT 3"
|
||||
|
||||
#~ msgid "Switch to VT 4"
|
||||
#~ msgstr "Bytt til VT 4"
|
||||
|
||||
#~ msgid "Switch to VT 5"
|
||||
#~ msgstr "Bytt til VT 5"
|
||||
|
||||
#~ msgid "Switch to VT 6"
|
||||
#~ msgstr "Bytt til VT 6"
|
||||
|
||||
#~ msgid "Switch to VT 7"
|
||||
#~ msgstr "Bytt til VT 7"
|
||||
|
||||
#~ msgid "Switch to VT 8"
|
||||
#~ msgstr "Bytt til VT 8"
|
||||
|
||||
#~ msgid "Switch to VT 9"
|
||||
#~ msgstr "Bytt til VT 9"
|
||||
|
||||
#~ msgid "Switch to VT 10"
|
||||
#~ msgstr "Bytt til VT 10"
|
||||
|
||||
#~ msgid "Switch to VT 11"
|
||||
#~ msgstr "Bytt til VT 11"
|
||||
|
||||
#~ msgid "Switch to VT 12"
|
||||
#~ msgstr "Bytt til VT 12"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit "
|
||||
#~ "the format"
|
||||
|
11
po/nl.po
11
po/nl.po
@ -4,13 +4,14 @@
|
||||
# Reinout van Schouwen <reinouts@gnome.org>, 2003–2007, 2013, 2016 (nalezen).
|
||||
# Michiel Sikkes <michiels@gnome.org>, 2005.
|
||||
# Wouter Bolsterlee <wbolster@gnome.org>, 2006–2012.
|
||||
# Hannie Dumoleyn <hannie@ubuntu-nl.org>, 2016.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-03-23 22:41+0100\n"
|
||||
"PO-Revision-Date: 2015-06-20 14:14+0100\n"
|
||||
"Last-Translator: Nathan Follens <nthn@unseen.is>\n"
|
||||
"PO-Revision-Date: 2016-10-17 18:24+0200\n"
|
||||
"Last-Translator: Hannie Dumoleyn <hannie@ubuntu-nl.org>\n"
|
||||
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
|
||||
"Language: nl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -18,7 +19,7 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Project-Style: gnome\n"
|
||||
"X-Generator: Poedit 1.8.1\n"
|
||||
"X-Generator: Lokalize 1.5\n"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:1
|
||||
msgid "Navigation"
|
||||
@ -42,7 +43,7 @@ msgstr "Venster verplaatsen naar werkblad 4"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:6
|
||||
msgid "Move window to last workspace"
|
||||
msgstr "Venster verplaatsen naar laatst gebruikte werkblad"
|
||||
msgstr "Venster verplaatsen naar laatste werkblad"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:7
|
||||
msgid "Move window one workspace to the left"
|
||||
@ -154,7 +155,7 @@ msgstr "Schakelen naar werkblad 4"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:34
|
||||
msgid "Switch to last workspace"
|
||||
msgstr "Schakelen naar laatst gebruikte werkblad"
|
||||
msgstr "Overschakelen naar laatste werkblad"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:35
|
||||
msgid "Move to workspace left"
|
||||
|
10
po/th.po
10
po/th.po
@ -1,11 +1,11 @@
|
||||
# Thai translation for mutter.
|
||||
# Copyright (C) 2003-2015 Free Software Foundation, Inc.
|
||||
# Copyright (C) 2003-2016 Free Software Foundation, Inc.
|
||||
# This file is distributed under the same license as the mutter package.
|
||||
#
|
||||
# Phakhinee Thangnithirat <sc442535@angsila.compsci.buu.ac.th>, 2003
|
||||
# Chanchai Junlouchai <taz@opentle.org>, 2003
|
||||
# Paisa Seeluangsawat <paisa@users.sf.net>, 2004.
|
||||
# Theppitak Karoonboonyanan <theppitak@gmail.com>, 2004-2012.
|
||||
# Theppitak Karoonboonyanan <theppitak@gmail.com>, 2004-2012, 2016.
|
||||
# Akom Chotiphantawanon <knight2000@gmail.com>, 2015.
|
||||
#
|
||||
msgid ""
|
||||
@ -14,8 +14,8 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
|
||||
"product=mutter&keywords=I18N+L10N&component=general\n"
|
||||
"POT-Creation-Date: 2015-07-18 22:50+0000\n"
|
||||
"PO-Revision-Date: 2015-08-01 17:29+0700\n"
|
||||
"Last-Translator: Akom Chotiphantawanon <knight2000@gmail.com>\n"
|
||||
"PO-Revision-Date: 2016-10-13 11:22+0700\n"
|
||||
"Last-Translator: Theppitak Karoonboonyanan <theppitak@gmail.com>\n"
|
||||
"Language-Team: Thai <thai-l10n@googlegroups.com>\n"
|
||||
"Language: th\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
@ -170,7 +170,7 @@ msgstr "ย้ายไปพื้นที่ทำงานขวา"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:37
|
||||
msgid "Move to workspace above"
|
||||
msgstr "ย้ายไปพื้นที่ทำงานซ้าย"
|
||||
msgstr "ย้ายไปพื้นที่ทำงานบน"
|
||||
|
||||
#: ../data/50-mutter-navigation.xml.in.h:38
|
||||
msgid "Move to workspace below"
|
||||
|
1155
po/zh_CN.po
1155
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@ -91,6 +91,9 @@ libmutter_la_SOURCES = \
|
||||
backends/meta-cursor-tracker-private.h \
|
||||
backends/meta-cursor-renderer.c \
|
||||
backends/meta-cursor-renderer.h \
|
||||
backends/meta-egl.c \
|
||||
backends/meta-egl.h \
|
||||
backends/meta-egl-ext.h \
|
||||
backends/meta-display-config-shared.h \
|
||||
backends/meta-idle-monitor.c \
|
||||
backends/meta-idle-monitor-private.h \
|
||||
@ -291,6 +294,8 @@ libmutter_la_SOURCES += \
|
||||
wayland/meta-wayland-data-device.c \
|
||||
wayland/meta-wayland-data-device.h \
|
||||
wayland/meta-wayland-data-device-private.h \
|
||||
wayland/meta-wayland-egl-stream.c \
|
||||
wayland/meta-wayland-egl-stream.h \
|
||||
wayland/meta-wayland-input-device.c \
|
||||
wayland/meta-wayland-input-device.h \
|
||||
wayland/meta-wayland-pointer-gestures.c \
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "meta-cursor-renderer.h"
|
||||
#include "meta-monitor-manager-private.h"
|
||||
#include "meta-input-settings-private.h"
|
||||
#include "backends/meta-egl.h"
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "backends/meta-renderer.h"
|
||||
#include "core/util-private.h"
|
||||
@ -117,6 +118,7 @@ MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
|
||||
MetaMonitorManager * meta_backend_get_monitor_manager (MetaBackend *backend);
|
||||
MetaCursorRenderer * meta_backend_get_cursor_renderer (MetaBackend *backend);
|
||||
MetaRenderer * meta_backend_get_renderer (MetaBackend *backend);
|
||||
MetaEgl * meta_backend_get_egl (MetaBackend *backend);
|
||||
|
||||
gboolean meta_backend_grab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
|
@ -65,6 +65,7 @@ struct _MetaBackendPrivate
|
||||
MetaCursorRenderer *cursor_renderer;
|
||||
MetaInputSettings *input_settings;
|
||||
MetaRenderer *renderer;
|
||||
MetaEgl *egl;
|
||||
|
||||
ClutterBackend *clutter_backend;
|
||||
ClutterActor *stage;
|
||||
@ -411,6 +412,8 @@ meta_backend_initable_init (GInitable *initable,
|
||||
MetaBackend *backend = META_BACKEND (initable);
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
priv->egl = g_object_new (META_TYPE_EGL, NULL);
|
||||
|
||||
priv->renderer = META_BACKEND_GET_CLASS (backend)->create_renderer (backend);
|
||||
if (!priv->renderer)
|
||||
{
|
||||
@ -483,6 +486,16 @@ MetaRenderer * meta_backend_get_renderer (MetaBackend *backend)
|
||||
return priv->renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_get_egl: (skip)
|
||||
*/
|
||||
MetaEgl * meta_backend_get_egl (MetaBackend *backend)
|
||||
{
|
||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||
|
||||
return priv->egl;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_grab_device: (skip)
|
||||
*/
|
||||
|
80
src/backends/meta-egl-ext.h
Normal file
80
src/backends/meta-egl-ext.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_EGL_EXT_H
|
||||
#define META_EGL_EXT_H
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
/*
|
||||
* This is a little different to the tests shipped with EGL implementations,
|
||||
* which wrap the entire thing in #ifndef EGL_WL_bind_wayland_display, then go
|
||||
* on to define both BindWaylandDisplay and QueryWaylandBuffer.
|
||||
*
|
||||
* Unfortunately, some implementations (particularly the version of Mesa shipped
|
||||
* in Ubuntu 12.04) define EGL_WL_bind_wayland_display, but then only provide
|
||||
* prototypes for (Un)BindWaylandDisplay, completely omitting
|
||||
* QueryWaylandBuffer.
|
||||
*
|
||||
* Detect this, and provide our own definitions if necessary.
|
||||
*/
|
||||
#ifndef EGL_WAYLAND_BUFFER_WL
|
||||
#define EGL_WAYLAND_BUFFER_WL 0x31D5 /* eglCreateImageKHR target */
|
||||
#define EGL_WAYLAND_PLANE_WL 0x31D6 /* eglCreateImageKHR target */
|
||||
|
||||
#define EGL_TEXTURE_Y_U_V_WL 0x31D7
|
||||
#define EGL_TEXTURE_Y_UV_WL 0x31D8
|
||||
#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
|
||||
#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
|
||||
|
||||
struct wl_resource;
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FIXME: Remove both EGL_EXT_stream_acquire_mode and
|
||||
* EGL_NV_output_drm_flip_event definitions below once both extensions
|
||||
* get published by Khronos and incorportated into Khronos' header files
|
||||
*/
|
||||
#ifndef EGL_EXT_stream_acquire_mode
|
||||
#define EGL_EXT_stream_acquire_mode 1
|
||||
#define EGL_CONSUMER_AUTO_ACQUIRE_EXT 0x332B
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
|
||||
#ifdef EGL_EGLEXT_PROTOTYPES
|
||||
EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireAttribEXT (EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib *attrib_list);
|
||||
#endif
|
||||
#endif /* EGL_EXT_stream_acquire_mode */
|
||||
|
||||
#ifndef EGL_NV_output_drm_flip_event
|
||||
#define EGL_NV_output_drm_flip_event 1
|
||||
#define EGL_DRM_FLIP_EVENT_DATA_NV 0x333E
|
||||
#endif /* EGL_NV_output_drm_flip_event */
|
||||
|
||||
#endif /* META_EGL_EXT_H */
|
759
src/backends/meta-egl.c
Normal file
759
src/backends/meta-egl.c
Normal file
@ -0,0 +1,759 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat Inc.
|
||||
*
|
||||
* 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 "backends/meta-backend-private.h"
|
||||
#include "backends/meta-egl.h"
|
||||
#include "backends/meta-egl-ext.h"
|
||||
#include "meta/util.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <gio/gio.h>
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
struct _MetaEgl
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
|
||||
|
||||
PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
|
||||
PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
|
||||
|
||||
PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL;
|
||||
|
||||
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
|
||||
|
||||
PFNEGLGETOUTPUTLAYERSEXTPROC eglGetOutputLayersEXT;
|
||||
PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC eglQueryOutputLayerAttribEXT;
|
||||
|
||||
PFNEGLCREATESTREAMKHRPROC eglCreateStreamKHR;
|
||||
PFNEGLDESTROYSTREAMKHRPROC eglDestroyStreamKHR;
|
||||
PFNEGLQUERYSTREAMKHRPROC eglQueryStreamKHR;
|
||||
|
||||
PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC eglCreateStreamProducerSurfaceKHR;
|
||||
|
||||
PFNEGLSTREAMCONSUMEROUTPUTEXTPROC eglStreamConsumerOutputEXT;
|
||||
|
||||
PFNEGLSTREAMCONSUMERACQUIREATTRIBEXTPROC eglStreamConsumerAcquireAttribEXT;
|
||||
|
||||
PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC eglStreamConsumerGLTextureExternalKHR;
|
||||
|
||||
PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquireKHR;
|
||||
|
||||
PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC eglCreateStreamFromFileDescriptorKHR;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaEgl, meta_egl, G_TYPE_OBJECT)
|
||||
|
||||
static const char *
|
||||
get_egl_error_str (void)
|
||||
{
|
||||
EGLint error_number;
|
||||
|
||||
error_number = eglGetError ();
|
||||
|
||||
switch (error_number)
|
||||
{
|
||||
case EGL_SUCCESS:
|
||||
return "The last function succeeded without error.";
|
||||
break;
|
||||
case EGL_NOT_INITIALIZED:
|
||||
return "EGL is not initialized, or could not be initialized, for the specified EGL display connection.";
|
||||
break;
|
||||
case EGL_BAD_ACCESS:
|
||||
return "EGL cannot access a requested resource (for example a context is bound in another thread).";
|
||||
break;
|
||||
case EGL_BAD_ALLOC:
|
||||
return "EGL failed to allocate resources for the requested operation.";
|
||||
break;
|
||||
case EGL_BAD_ATTRIBUTE:
|
||||
return "An unrecognized attribute or attribute value was passed in the attribute list.";
|
||||
break;
|
||||
case EGL_BAD_CONTEXT:
|
||||
return "An EGLContext argument does not name a valid EGL rendering context.";
|
||||
break;
|
||||
case EGL_BAD_CONFIG:
|
||||
return "An EGLConfig argument does not name a valid EGL frame buffer configuration.";
|
||||
break;
|
||||
case EGL_BAD_CURRENT_SURFACE:
|
||||
return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.";
|
||||
break;
|
||||
case EGL_BAD_DISPLAY:
|
||||
return "An EGLDisplay argument does not name a valid EGL display connection.";
|
||||
break;
|
||||
case EGL_BAD_SURFACE:
|
||||
return "An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.";
|
||||
break;
|
||||
case EGL_BAD_MATCH:
|
||||
return "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface).";
|
||||
break;
|
||||
case EGL_BAD_PARAMETER:
|
||||
return "One or more argument values are invalid.";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_PIXMAP:
|
||||
return "A NativePixmapType argument does not refer to a valid native pixmap.";
|
||||
break;
|
||||
case EGL_BAD_NATIVE_WINDOW:
|
||||
return "A NativeWindowType argument does not refer to a valid native window.";
|
||||
break;
|
||||
case EGL_CONTEXT_LOST:
|
||||
return "A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering. ";
|
||||
break;
|
||||
default:
|
||||
return "Unknown error";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_egl_error (GError **error)
|
||||
{
|
||||
const char *error_str;
|
||||
|
||||
if (!error)
|
||||
return;
|
||||
|
||||
error_str = get_egl_error_str ();
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
error_str);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
extensions_string_has_extensions_valist (const char *extensions_str,
|
||||
char ***missing_extensions,
|
||||
char *first_extension,
|
||||
va_list var_args)
|
||||
{
|
||||
char **extensions;
|
||||
char *extension;
|
||||
size_t num_missing_extensions = 0;
|
||||
|
||||
if (missing_extensions)
|
||||
*missing_extensions = NULL;
|
||||
|
||||
extensions = g_strsplit (extensions_str, " ", -1);
|
||||
|
||||
extension = first_extension;
|
||||
while (extension)
|
||||
{
|
||||
if (!g_strv_contains ((const char * const *) extensions, extension))
|
||||
{
|
||||
num_missing_extensions++;
|
||||
if (missing_extensions)
|
||||
{
|
||||
*missing_extensions = g_realloc_n (*missing_extensions,
|
||||
num_missing_extensions + 1,
|
||||
sizeof (const char *));
|
||||
(*missing_extensions)[num_missing_extensions - 1] = extension;
|
||||
(*missing_extensions)[num_missing_extensions] = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
extension = va_arg (var_args, char *);
|
||||
}
|
||||
|
||||
g_strfreev (extensions);
|
||||
|
||||
return num_missing_extensions == 0;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_has_extensions (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
char ***missing_extensions,
|
||||
char *first_extension,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
const char *extensions_str;
|
||||
gboolean has_extensions;
|
||||
|
||||
extensions_str = (const char *) eglQueryString (display, EGL_EXTENSIONS);
|
||||
if (!extensions_str)
|
||||
{
|
||||
g_warning ("Failed to query string: %s", get_egl_error_str ());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
va_start (var_args, first_extension);
|
||||
has_extensions = extensions_string_has_extensions_valist (extensions_str,
|
||||
missing_extensions,
|
||||
first_extension,
|
||||
var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return has_extensions;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_initialize (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
GError **error)
|
||||
{
|
||||
if (!eglInitialize (display, NULL, NULL))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_choose_config (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLint *attrib_list,
|
||||
EGLConfig *chosen_config,
|
||||
GError **error)
|
||||
{
|
||||
EGLint num_configs;
|
||||
EGLConfig *configs;
|
||||
EGLint num_matches;
|
||||
|
||||
if (!eglGetConfigs (display, NULL, 0, &num_configs))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (num_configs < 1)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"No EGL configurations available");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
configs = g_new0 (EGLConfig, num_configs);
|
||||
|
||||
if (!eglChooseConfig (display, attrib_list, configs, num_configs, &num_matches))
|
||||
{
|
||||
g_free (configs);
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have any preference specified yet, so lets choose the first one.
|
||||
*/
|
||||
*chosen_config = configs[0];
|
||||
|
||||
g_free (configs);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
meta_egl_create_pbuffer_surface (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
const EGLint *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
EGLSurface surface;
|
||||
|
||||
surface = eglCreatePbufferSurface (display, config, attrib_list);
|
||||
if (surface == EGL_NO_SURFACE)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_egl_proc_valid_real (void *proc,
|
||||
const char *proc_name,
|
||||
GError **error)
|
||||
{
|
||||
if (!proc)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"EGL proc '%s' not resolved",
|
||||
proc_name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define is_egl_proc_valid(proc, error) \
|
||||
is_egl_proc_valid_real (proc, #proc, error)
|
||||
|
||||
EGLDisplay
|
||||
meta_egl_get_platform_display (MetaEgl *egl,
|
||||
EGLenum platform,
|
||||
void *native_display,
|
||||
const EGLint *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
EGLDisplay display;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglGetPlatformDisplayEXT, error))
|
||||
return EGL_NO_DISPLAY;
|
||||
|
||||
display = egl->eglGetPlatformDisplayEXT (platform,
|
||||
native_display,
|
||||
attrib_list);
|
||||
if (display == EGL_NO_DISPLAY)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_DISPLAY;
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
EGLImageKHR
|
||||
meta_egl_create_image (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLContext context,
|
||||
EGLenum target,
|
||||
EGLClientBuffer buffer,
|
||||
const EGLint *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
EGLImageKHR image;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglCreateImageKHR, error))
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
|
||||
image = egl->eglCreateImageKHR (display, context,
|
||||
target, buffer, attrib_list);
|
||||
if (image == EGL_NO_IMAGE_KHR)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_IMAGE_KHR;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_destroy_image (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLImageKHR image,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglDestroyImageKHR, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglDestroyImageKHR (display, image))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_query_wayland_buffer (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
struct wl_resource *buffer,
|
||||
EGLint attribute,
|
||||
EGLint *value,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglQueryWaylandBufferWL, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglQueryWaylandBufferWL (display, buffer, attribute, value))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_query_devices (MetaEgl *egl,
|
||||
EGLint max_devices,
|
||||
EGLDeviceEXT *devices,
|
||||
EGLint *num_devices,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglQueryDevicesEXT, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglQueryDevicesEXT (max_devices,
|
||||
devices,
|
||||
num_devices))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const char *
|
||||
meta_egl_query_device_string (MetaEgl *egl,
|
||||
EGLDeviceEXT device,
|
||||
EGLint name,
|
||||
GError **error)
|
||||
{
|
||||
const char *device_string;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglQueryDeviceStringEXT, error))
|
||||
return NULL;
|
||||
|
||||
device_string = egl->eglQueryDeviceStringEXT (device, name);
|
||||
if (!device_string)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return device_string;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_egl_device_has_extensions (MetaEgl *egl,
|
||||
EGLDeviceEXT device,
|
||||
char ***missing_extensions,
|
||||
char *first_extension,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
const char *extensions_str;
|
||||
gboolean has_extensions;
|
||||
GError *error = NULL;
|
||||
|
||||
extensions_str = meta_egl_query_device_string (egl, device, EGL_EXTENSIONS,
|
||||
&error);
|
||||
if (!extensions_str)
|
||||
{
|
||||
g_warning ("Failed to query device string: %s", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
va_start (var_args, first_extension);
|
||||
has_extensions = extensions_string_has_extensions_valist (extensions_str,
|
||||
missing_extensions,
|
||||
first_extension,
|
||||
var_args);
|
||||
va_end (var_args);
|
||||
|
||||
return has_extensions;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_get_output_layers (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLAttrib *attrib_list,
|
||||
EGLOutputLayerEXT *layers,
|
||||
EGLint max_layers,
|
||||
EGLint *num_layers,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglGetOutputLayersEXT, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglGetOutputLayersEXT (display,
|
||||
attrib_list,
|
||||
layers,
|
||||
max_layers,
|
||||
num_layers))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_query_output_layer_attrib (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLOutputLayerEXT layer,
|
||||
EGLint attribute,
|
||||
EGLAttrib *value,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglQueryOutputLayerAttribEXT, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglQueryOutputLayerAttribEXT (display, layer,
|
||||
attribute, value))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EGLStreamKHR
|
||||
meta_egl_create_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLint *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
EGLStreamKHR stream;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglCreateStreamKHR, error))
|
||||
return EGL_NO_STREAM_KHR;
|
||||
|
||||
stream = egl->eglCreateStreamKHR (display, attrib_list);
|
||||
if (stream == EGL_NO_STREAM_KHR)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_STREAM_KHR;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_destroy_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglDestroyStreamKHR, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglDestroyStreamKHR (display, stream))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_query_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLenum attribute,
|
||||
EGLint *value,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglQueryStreamKHR, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglQueryStreamKHR (display, stream, attribute, value))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EGLSurface
|
||||
meta_egl_create_stream_producer_surface (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
EGLStreamKHR stream,
|
||||
const EGLint *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
EGLSurface surface;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglCreateStreamProducerSurfaceKHR, error))
|
||||
return EGL_NO_SURFACE;
|
||||
|
||||
surface = egl->eglCreateStreamProducerSurfaceKHR (display,
|
||||
config,
|
||||
stream,
|
||||
attrib_list);
|
||||
if (surface == EGL_NO_SURFACE)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_stream_consumer_output (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLOutputLayerEXT layer,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglStreamConsumerOutputEXT, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglStreamConsumerOutputEXT (display, stream, layer))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLAttrib *attrib_list,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglStreamConsumerAcquireAttribEXT, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglStreamConsumerAcquireAttribEXT (display, stream, attrib_list))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglStreamConsumerGLTextureExternalKHR, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglStreamConsumerGLTextureExternalKHR (display, stream))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_egl_stream_consumer_acquire (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error)
|
||||
{
|
||||
if (!is_egl_proc_valid (egl->eglStreamConsumerAcquireKHR, error))
|
||||
return FALSE;
|
||||
|
||||
if (!egl->eglStreamConsumerAcquireKHR (display, stream))
|
||||
{
|
||||
set_egl_error (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
EGLStreamKHR
|
||||
meta_egl_create_stream_from_file_descriptor (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLNativeFileDescriptorKHR file_descriptor,
|
||||
GError **error)
|
||||
{
|
||||
EGLStreamKHR stream;
|
||||
|
||||
if (!is_egl_proc_valid (egl->eglCreateStreamFromFileDescriptorKHR, error))
|
||||
return EGL_NO_STREAM_KHR;
|
||||
|
||||
stream = egl->eglCreateStreamFromFileDescriptorKHR (display, file_descriptor);
|
||||
if (stream == EGL_NO_STREAM_KHR)
|
||||
{
|
||||
set_egl_error (error);
|
||||
return EGL_NO_STREAM_KHR;
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
#define GET_EGL_PROC_ADDR(proc) \
|
||||
egl->proc = (void *) eglGetProcAddress (#proc);
|
||||
|
||||
#define GET_EGL_PROC_ADDR_REQUIRED(proc) \
|
||||
GET_EGL_PROC_ADDR(proc) \
|
||||
if (!egl->proc) \
|
||||
{ \
|
||||
meta_fatal ("Failed to get proc address for '%s'\n", #proc); \
|
||||
}
|
||||
|
||||
static void
|
||||
meta_egl_constructed (GObject *object)
|
||||
{
|
||||
MetaEgl *egl = META_EGL (object);
|
||||
|
||||
GET_EGL_PROC_ADDR_REQUIRED (eglGetPlatformDisplayEXT);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglCreateImageKHR);
|
||||
GET_EGL_PROC_ADDR (eglDestroyImageKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglQueryWaylandBufferWL);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglQueryDevicesEXT);
|
||||
GET_EGL_PROC_ADDR (eglQueryDeviceStringEXT);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglGetOutputLayersEXT);
|
||||
GET_EGL_PROC_ADDR (eglQueryOutputLayerAttribEXT);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglCreateStreamKHR);
|
||||
GET_EGL_PROC_ADDR (eglDestroyStreamKHR);
|
||||
GET_EGL_PROC_ADDR (eglQueryStreamKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglCreateStreamProducerSurfaceKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglStreamConsumerOutputEXT);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglStreamConsumerAcquireAttribEXT);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglStreamConsumerGLTextureExternalKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglStreamConsumerAcquireKHR);
|
||||
|
||||
GET_EGL_PROC_ADDR (eglCreateStreamFromFileDescriptorKHR);
|
||||
}
|
||||
|
||||
#undef GET_EGL_PROC_ADDR
|
||||
|
||||
static void
|
||||
meta_egl_init (MetaEgl *egl)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_egl_class_init (MetaEglClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_egl_constructed;
|
||||
}
|
166
src/backends/meta-egl.h
Normal file
166
src/backends/meta-egl.h
Normal file
@ -0,0 +1,166 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat Inc.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef META_EGL_H
|
||||
#define META_EGL_H
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#define META_TYPE_EGL (meta_egl_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaEgl, meta_egl, META, EGL, GObject)
|
||||
|
||||
gboolean meta_egl_has_extensions (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
char ***missing_extensions,
|
||||
char *first_extension,
|
||||
...);
|
||||
|
||||
gboolean meta_egl_initialize (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_choose_config (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLint *attrib_list,
|
||||
EGLConfig *chosen_config,
|
||||
GError **error);
|
||||
|
||||
EGLImageKHR meta_egl_create_image (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLContext context,
|
||||
EGLenum target,
|
||||
EGLClientBuffer buffer,
|
||||
const EGLint *attrib_list,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_destroy_image (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLImageKHR image,
|
||||
GError **error);
|
||||
|
||||
EGLSurface meta_egl_create_pbuffer_surface (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
const EGLint *attrib_list,
|
||||
GError **error);
|
||||
|
||||
EGLDisplay meta_egl_get_platform_display (MetaEgl *egl,
|
||||
EGLenum platform,
|
||||
void *native_display,
|
||||
const EGLint *attrib_list,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_query_wayland_buffer (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
struct wl_resource *buffer,
|
||||
EGLint attribute,
|
||||
EGLint *value,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_query_devices (MetaEgl *egl,
|
||||
EGLint max_devices,
|
||||
EGLDeviceEXT *devices,
|
||||
EGLint *num_devices,
|
||||
GError **error);
|
||||
|
||||
const char * meta_egl_query_device_string (MetaEgl *egl,
|
||||
EGLDeviceEXT device,
|
||||
EGLint name,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_egl_device_has_extensions (MetaEgl *egl,
|
||||
EGLDeviceEXT device,
|
||||
char ***missing_extensions,
|
||||
char *first_extension,
|
||||
...);
|
||||
|
||||
gboolean meta_egl_get_output_layers (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLAttrib *attrib_list,
|
||||
EGLOutputLayerEXT *layers,
|
||||
EGLint max_layers,
|
||||
EGLint *num_layers,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_query_output_layer_attrib (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLOutputLayerEXT layer,
|
||||
EGLint attribute,
|
||||
EGLAttrib *value,
|
||||
GError **error);
|
||||
|
||||
EGLStreamKHR meta_egl_create_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
const EGLint *attrib_list,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_destroy_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_query_stream (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLenum attribute,
|
||||
EGLint *value,
|
||||
GError **error);
|
||||
|
||||
EGLSurface meta_egl_create_stream_producer_surface (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLConfig config,
|
||||
EGLStreamKHR stream,
|
||||
const EGLint *attrib_list,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_stream_consumer_output (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLOutputLayerEXT layer,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_stream_consumer_acquire_attrib (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
EGLAttrib *attrib_list,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_stream_consumer_acquire (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_egl_stream_consumer_gl_texture_external (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLStreamKHR stream,
|
||||
GError **error);
|
||||
|
||||
EGLStreamKHR meta_egl_create_stream_from_file_descriptor (MetaEgl *egl,
|
||||
EGLDisplay display,
|
||||
EGLNativeFileDescriptorKHR file_descriptor,
|
||||
GError **error);
|
||||
|
||||
#endif /* META_EGL_H */
|
@ -107,6 +107,16 @@ struct _MetaInputSettingsClass
|
||||
void (* set_trackball_accel_profile) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopPointerAccelProfile profile);
|
||||
|
||||
void (* set_stylus_pressure) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
const gint32 curve[4]);
|
||||
void (* set_stylus_button_map) (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
GDesktopStylusButtonAction primary,
|
||||
GDesktopStylusButtonAction secondary);
|
||||
};
|
||||
|
||||
GType meta_input_settings_get_type (void) G_GNUC_CONST;
|
||||
@ -121,15 +131,6 @@ MetaMonitorInfo * meta_input_settings_get_tablet_monitor_info (MetaInputSett
|
||||
GDesktopTabletMapping meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device);
|
||||
|
||||
GDesktopStylusButtonAction meta_input_settings_get_stylus_button_action (MetaInputSettings *settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_device,
|
||||
guint button);
|
||||
gdouble meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
gdouble pressure);
|
||||
|
||||
gboolean meta_input_settings_is_pad_button_grabbed (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button);
|
||||
|
@ -45,28 +45,17 @@ static GQuark quark_tool_settings = 0;
|
||||
|
||||
typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate;
|
||||
typedef struct _DeviceMappingInfo DeviceMappingInfo;
|
||||
typedef struct _ToolSettings ToolSettings;
|
||||
|
||||
struct _DeviceMappingInfo
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
GSettings *settings;
|
||||
GSettings *gsd_settings;
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct _ToolSettings
|
||||
{
|
||||
GSettings *settings;
|
||||
ClutterInputDeviceTool *tool;
|
||||
GDesktopStylusButtonAction button_action;
|
||||
GDesktopStylusButtonAction secondary_button_action;
|
||||
gdouble curve[4];
|
||||
};
|
||||
|
||||
struct _MetaInputSettingsPrivate
|
||||
{
|
||||
ClutterDeviceManager *device_manager;
|
||||
@ -80,6 +69,8 @@ struct _MetaInputSettingsPrivate
|
||||
|
||||
GHashTable *mappable_devices;
|
||||
|
||||
ClutterVirtualInputDevice *virtual_pad_keyboard;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
WacomDeviceDatabase *wacom_db;
|
||||
#endif
|
||||
@ -128,6 +119,8 @@ meta_input_settings_dispose (GObject *object)
|
||||
MetaInputSettings *settings = META_INPUT_SETTINGS (object);
|
||||
MetaInputSettingsPrivate *priv = meta_input_settings_get_instance_private (settings);
|
||||
|
||||
g_clear_object (&priv->virtual_pad_keyboard);
|
||||
|
||||
g_clear_object (&priv->mouse_settings);
|
||||
g_clear_object (&priv->touchpad_settings);
|
||||
g_clear_object (&priv->trackball_settings);
|
||||
@ -483,6 +476,7 @@ update_touchpad_edge_scroll (MetaInputSettings *input_settings,
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
gboolean edge_scroll_enabled;
|
||||
gboolean two_finger_scroll_enabled;
|
||||
MetaInputSettingsPrivate *priv;
|
||||
|
||||
if (device &&
|
||||
@ -492,6 +486,11 @@ update_touchpad_edge_scroll (MetaInputSettings *input_settings,
|
||||
priv = meta_input_settings_get_instance_private (input_settings);
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
edge_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "edge-scrolling-enabled");
|
||||
two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
|
||||
|
||||
/* If both are enabled we prefer two finger. */
|
||||
if (edge_scroll_enabled && two_finger_scroll_enabled)
|
||||
edge_scroll_enabled = FALSE;
|
||||
|
||||
if (device)
|
||||
{
|
||||
@ -523,6 +522,10 @@ update_touchpad_two_finger_scroll (MetaInputSettings *input_settings,
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
two_finger_scroll_enabled = g_settings_get_boolean (priv->touchpad_settings, "two-finger-scrolling-enabled");
|
||||
|
||||
/* Disable edge since they can't both be set. */
|
||||
if (two_finger_scroll_enabled)
|
||||
update_touchpad_edge_scroll (input_settings, device);
|
||||
|
||||
if (device)
|
||||
{
|
||||
settings_device_set_bool_setting (input_settings, device,
|
||||
@ -535,6 +538,10 @@ update_touchpad_two_finger_scroll (MetaInputSettings *input_settings,
|
||||
(ConfigBoolFunc) input_settings_class->set_two_finger_scroll,
|
||||
two_finger_scroll_enabled);
|
||||
}
|
||||
|
||||
/* Edge might have been disabled because two finger was on. */
|
||||
if (!two_finger_scroll_enabled)
|
||||
update_touchpad_edge_scroll (input_settings, device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -708,19 +715,6 @@ meta_input_settings_find_output (MetaInputSettings *input_settings,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DeviceMappingInfo *
|
||||
lookup_mapping_info (ClutterInputDevice *device)
|
||||
{
|
||||
MetaInputSettings *settings;
|
||||
MetaInputSettingsPrivate *priv;
|
||||
|
||||
settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
if (!settings)
|
||||
return NULL;
|
||||
priv = meta_input_settings_get_instance_private (settings);
|
||||
return g_hash_table_lookup (priv->mappable_devices, device);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tablet_keep_aspect (MetaInputSettings *input_settings,
|
||||
GSettings *settings,
|
||||
@ -730,7 +724,9 @@ update_tablet_keep_aspect (MetaInputSettings *input_settings,
|
||||
MetaOutput *output = NULL;
|
||||
gboolean keep_aspect;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
@ -751,12 +747,8 @@ update_tablet_keep_aspect (MetaInputSettings *input_settings,
|
||||
if (clutter_input_device_get_mapping_mode (device) ==
|
||||
CLUTTER_INPUT_DEVICE_MAPPING_ABSOLUTE)
|
||||
{
|
||||
DeviceMappingInfo *info = NULL;
|
||||
|
||||
keep_aspect = g_settings_get_boolean (settings, "keep-aspect");
|
||||
info = lookup_mapping_info (device);
|
||||
if (info)
|
||||
output = meta_input_settings_find_output (input_settings, info->settings, device);
|
||||
output = meta_input_settings_find_output (input_settings, settings, device);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -778,6 +770,8 @@ update_device_display (MetaInputSettings *input_settings,
|
||||
MetaOutput *output;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_TOUCHSCREEN_DEVICE)
|
||||
return;
|
||||
|
||||
@ -809,9 +803,10 @@ update_tablet_mapping (MetaInputSettings *input_settings,
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GDesktopTabletMapping mapping;
|
||||
DeviceMappingInfo *info;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
@ -828,8 +823,7 @@ update_tablet_mapping (MetaInputSettings *input_settings,
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
mapping = g_settings_get_boolean (settings, "is-absolute") ?
|
||||
G_DESKTOP_TABLET_MAPPING_ABSOLUTE : G_DESKTOP_TABLET_MAPPING_RELATIVE;
|
||||
mapping = g_settings_get_enum (settings, "mapping");
|
||||
|
||||
settings_device_set_uint_setting (input_settings, device,
|
||||
input_settings_class->set_tablet_mapping,
|
||||
@ -837,9 +831,7 @@ update_tablet_mapping (MetaInputSettings *input_settings,
|
||||
|
||||
/* Relative mapping disables keep-aspect/display */
|
||||
update_tablet_keep_aspect (input_settings, settings, device);
|
||||
info = lookup_mapping_info (device);
|
||||
if (info)
|
||||
update_device_display (input_settings, info->settings, device);
|
||||
update_device_display (input_settings, settings, device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -849,10 +841,12 @@ update_tablet_area (MetaInputSettings *input_settings,
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GVariant *variant;
|
||||
const guint32 *area;
|
||||
const gdouble *area;
|
||||
gsize n_elems;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
@ -872,7 +866,7 @@ update_tablet_area (MetaInputSettings *input_settings,
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
variant = g_settings_get_value (settings, "area");
|
||||
|
||||
area = g_variant_get_fixed_array (variant, &n_elems, sizeof (guint32));
|
||||
area = g_variant_get_fixed_array (variant, &n_elems, sizeof (gdouble));
|
||||
if (n_elems == 4)
|
||||
{
|
||||
input_settings_class->set_tablet_area (input_settings, device,
|
||||
@ -891,7 +885,10 @@ update_tablet_left_handed (MetaInputSettings *input_settings,
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
gboolean enabled;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE)
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PAD_DEVICE)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
@ -908,7 +905,7 @@ update_tablet_left_handed (MetaInputSettings *input_settings,
|
||||
#endif
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
enabled = g_settings_get_enum (settings, "rotation") != 0;
|
||||
enabled = g_settings_get_boolean (settings, "left-handed");
|
||||
|
||||
settings_device_set_bool_setting (input_settings, device,
|
||||
input_settings_class->set_left_handed,
|
||||
@ -976,20 +973,13 @@ mapped_device_changed_cb (GSettings *settings,
|
||||
{
|
||||
if (strcmp (key, "display") == 0)
|
||||
update_device_display (info->input_settings, settings, info->device);
|
||||
}
|
||||
|
||||
static void
|
||||
mapped_device_gsd_setting_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
if (strcmp (key, "is-absolute") == 0)
|
||||
else if (strcmp (key, "mapping") == 0)
|
||||
update_tablet_mapping (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "area") == 0)
|
||||
update_tablet_area (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "keep-aspect") == 0)
|
||||
update_tablet_keep_aspect (info->input_settings, settings, info->device);
|
||||
else if (strcmp (key, "rotation") == 0)
|
||||
else if (strcmp (key, "left-handed") == 0)
|
||||
update_tablet_left_handed (info->input_settings, settings, info->device);
|
||||
}
|
||||
|
||||
@ -999,14 +989,13 @@ apply_mappable_device_settings (MetaInputSettings *input_settings,
|
||||
{
|
||||
update_device_display (input_settings, info->settings, info->device);
|
||||
|
||||
if (info->gsd_settings &&
|
||||
(clutter_input_device_get_device_type (info->device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (info->device) == CLUTTER_PAD_DEVICE))
|
||||
if (clutter_input_device_get_device_type (info->device) == CLUTTER_TABLET_DEVICE ||
|
||||
clutter_input_device_get_device_type (info->device) == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
update_tablet_mapping (input_settings, info->gsd_settings, info->device);
|
||||
update_tablet_area (input_settings, info->gsd_settings, info->device);
|
||||
update_tablet_keep_aspect (input_settings, info->gsd_settings, info->device);
|
||||
update_tablet_left_handed (input_settings, info->gsd_settings, info->device);
|
||||
update_tablet_mapping (input_settings, info->settings, info->device);
|
||||
update_tablet_area (input_settings, info->settings, info->device);
|
||||
update_tablet_keep_aspect (input_settings, info->settings, info->device);
|
||||
update_tablet_left_handed (input_settings, info->settings, info->device);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1048,205 +1037,36 @@ lookup_device_settings (ClutterInputDevice *device)
|
||||
return settings;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_tablet_settings_id (ClutterInputDevice *device,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
gchar *id = NULL, *machine_id;
|
||||
gsize length;
|
||||
|
||||
if (!g_file_get_contents ("/etc/machine-id", &machine_id, &length, NULL))
|
||||
return NULL;
|
||||
|
||||
machine_id = g_strstrip (machine_id);
|
||||
#ifdef HAVE_LIBWACOM
|
||||
if (info->wacom_device)
|
||||
id = g_strdup_printf ("%s-%s", machine_id, libwacom_get_match (info->wacom_device));
|
||||
#endif
|
||||
|
||||
if (!id)
|
||||
id = g_strdup_printf ("%s-%s:%s", machine_id,
|
||||
clutter_input_device_get_vendor_id (device),
|
||||
clutter_input_device_get_product_id (device));
|
||||
|
||||
g_free (machine_id);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
has_gsd_schemas (void)
|
||||
{
|
||||
GSettingsSchema *schema;
|
||||
|
||||
schema = g_settings_schema_source_lookup (g_settings_schema_source_get_default (),
|
||||
"org.gnome.settings-daemon.peripherals.wacom",
|
||||
TRUE);
|
||||
if (!schema)
|
||||
return FALSE;
|
||||
|
||||
g_settings_schema_unref (schema);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GSettings *
|
||||
lookup_device_gsd_settings (ClutterInputDevice *device,
|
||||
DeviceMappingInfo *info)
|
||||
{
|
||||
ClutterInputDeviceType type;
|
||||
GSettings *settings = NULL;
|
||||
|
||||
type = clutter_input_device_get_device_type (device);
|
||||
|
||||
if (type == CLUTTER_TABLET_DEVICE ||
|
||||
type == CLUTTER_PEN_DEVICE ||
|
||||
type == CLUTTER_ERASER_DEVICE ||
|
||||
type == CLUTTER_CURSOR_DEVICE ||
|
||||
type == CLUTTER_PAD_DEVICE)
|
||||
{
|
||||
gchar *device_id, *path;
|
||||
|
||||
if (!has_gsd_schemas ())
|
||||
return NULL;
|
||||
|
||||
device_id = get_tablet_settings_id (device, info);
|
||||
path = g_strdup_printf ("/org/gnome/settings-daemon/peripherals/wacom/%s/",
|
||||
device_id);
|
||||
settings = g_settings_new_with_path ("org.gnome.settings-daemon.peripherals.wacom",
|
||||
path);
|
||||
g_free (device_id);
|
||||
g_free (path);
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static void
|
||||
tool_settings_cache_pressure_curve (ToolSettings *tool_settings)
|
||||
{
|
||||
GVariant *variant;
|
||||
const gint32 *curve;
|
||||
gsize n_elems;
|
||||
|
||||
variant = g_settings_get_value (tool_settings->settings, "pressurecurve");
|
||||
|
||||
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
||||
if (n_elems == 4)
|
||||
{
|
||||
tool_settings->curve[0] = (gdouble) curve[0] / 100;
|
||||
tool_settings->curve[1] = (gdouble) curve[1] / 100;
|
||||
tool_settings->curve[2] = (gdouble) curve[2] / 100;
|
||||
tool_settings->curve[3] = (gdouble) curve[3] / 100;
|
||||
}
|
||||
else
|
||||
{
|
||||
tool_settings->curve[0] = tool_settings->curve[1] = 0;
|
||||
tool_settings->curve[2] = tool_settings->curve[3] = 1;
|
||||
}
|
||||
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
static GDesktopStylusButtonAction
|
||||
translate_stylus_button_action (guint32 button_number)
|
||||
{
|
||||
switch (button_number)
|
||||
{
|
||||
case 2:
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE;
|
||||
case 3:
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT;
|
||||
case 8:
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_BACK;
|
||||
case 9:
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD;
|
||||
default:
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
tool_settings_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
ToolSettings *tool_settings)
|
||||
{
|
||||
if (strcmp (key, "buttonmapping") == 0)
|
||||
{
|
||||
GVariant *variant = g_settings_get_value (settings, "buttonmapping");
|
||||
const guint32 *mapping;
|
||||
gsize n_elems;
|
||||
|
||||
mapping = g_variant_get_fixed_array (variant, &n_elems, sizeof (guint32));
|
||||
tool_settings->button_action = translate_stylus_button_action (mapping[2]);
|
||||
tool_settings->secondary_button_action = translate_stylus_button_action (mapping[3]);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
else if (strcmp (key, "pressurecurve") == 0)
|
||||
tool_settings_cache_pressure_curve (tool_settings);
|
||||
}
|
||||
|
||||
static ToolSettings *
|
||||
tool_settings_new (ClutterInputDeviceTool *tool,
|
||||
const gchar *schema_path)
|
||||
{
|
||||
ToolSettings *tool_settings;
|
||||
GVariant *variant;
|
||||
const guint32 *mapping;
|
||||
gsize n_elems;
|
||||
|
||||
tool_settings = g_new0 (ToolSettings, 1);
|
||||
tool_settings->tool = tool;
|
||||
tool_settings->curve[0] = tool_settings->curve[1] = 0;
|
||||
tool_settings->curve[2] = tool_settings->curve[3] = 1;
|
||||
|
||||
if (has_gsd_schemas ())
|
||||
{
|
||||
tool_settings->settings =
|
||||
g_settings_new_with_path ("org.gnome.settings-daemon.peripherals.wacom.stylus",
|
||||
schema_path);
|
||||
|
||||
g_signal_connect (tool_settings->settings, "changed",
|
||||
G_CALLBACK (tool_settings_changed_cb), tool_settings);
|
||||
|
||||
/* Initialize values */
|
||||
variant = g_settings_get_value (tool_settings->settings, "buttonmapping");
|
||||
mapping = g_variant_get_fixed_array (variant, &n_elems, sizeof (guint32));
|
||||
tool_settings->button_action = translate_stylus_button_action (mapping[2]);
|
||||
tool_settings->secondary_button_action = translate_stylus_button_action (mapping[3]);
|
||||
tool_settings_cache_pressure_curve (tool_settings);
|
||||
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
return tool_settings;
|
||||
}
|
||||
|
||||
static void
|
||||
tool_settings_free (ToolSettings *tool_settings)
|
||||
{
|
||||
g_object_unref (tool_settings->settings);
|
||||
g_free (tool_settings);
|
||||
}
|
||||
|
||||
static ToolSettings *
|
||||
lookup_tool_settings (ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *device)
|
||||
{
|
||||
ToolSettings *tool_settings;
|
||||
guint64 tool_id;
|
||||
gchar *device_id, *path;
|
||||
GSettings *tool_settings;
|
||||
guint64 serial;
|
||||
gchar *path;
|
||||
|
||||
tool_settings = g_object_get_qdata (G_OBJECT (tool), quark_tool_settings);
|
||||
if (tool_settings)
|
||||
return tool_settings;
|
||||
|
||||
tool_id = clutter_input_device_tool_get_id (tool);
|
||||
device_id = get_tablet_settings_id (device, lookup_mapping_info (device));
|
||||
path = g_strdup_printf ("/org/gnome/settings-daemon/peripherals/wacom/%s/%" G_GUINT64_FORMAT "/",
|
||||
device_id, tool_id);
|
||||
tool_settings = tool_settings_new (tool, path);
|
||||
serial = clutter_input_device_tool_get_serial (tool);
|
||||
|
||||
if (serial == 0)
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/default-%s:%s/",
|
||||
clutter_input_device_get_vendor_id (device),
|
||||
clutter_input_device_get_product_id (device));
|
||||
}
|
||||
else
|
||||
{
|
||||
path = g_strdup_printf ("/org/gnome/desktop/peripherals/stylus/%lx/", serial);
|
||||
}
|
||||
|
||||
tool_settings =
|
||||
g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.stylus",
|
||||
path);
|
||||
g_object_set_qdata_full (G_OBJECT (tool), quark_tool_settings, tool_settings,
|
||||
(GDestroyNotify) tool_settings_free);
|
||||
(GDestroyNotify) g_object_unref);
|
||||
g_free (path);
|
||||
|
||||
return tool_settings;
|
||||
@ -1256,15 +1076,16 @@ static GSettings *
|
||||
lookup_pad_button_settings (ClutterInputDevice *device,
|
||||
guint button)
|
||||
{
|
||||
const gchar *vendor, *product;
|
||||
GSettings *settings;
|
||||
gchar *device_id, *path;
|
||||
gchar *path;
|
||||
|
||||
device_id = get_tablet_settings_id (device, lookup_mapping_info (device));
|
||||
path = g_strdup_printf ("/org/gnome/settings-daemon/peripherals/wacom/%s/button%c/",
|
||||
device_id, 'A' + button);
|
||||
settings = g_settings_new_with_path ("org.gnome.settings-daemon.peripherals.wacom.tablet-button",
|
||||
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);
|
||||
settings = g_settings_new_with_path ("org.gnome.desktop.peripherals.tablet.pad-button",
|
||||
path);
|
||||
g_free (device_id);
|
||||
g_free (path);
|
||||
|
||||
return settings;
|
||||
@ -1295,7 +1116,6 @@ device_mapping_info_free (DeviceMappingInfo *info)
|
||||
libwacom_destroy (info->wacom_device);
|
||||
#endif
|
||||
g_object_unref (info->settings);
|
||||
g_clear_object (&info->gsd_settings);
|
||||
g_slice_free (DeviceMappingInfo, info);
|
||||
}
|
||||
|
||||
@ -1344,13 +1164,6 @@ check_add_mappable_device (MetaInputSettings *input_settings,
|
||||
|
||||
g_hash_table_insert (priv->mappable_devices, device, info);
|
||||
|
||||
info->gsd_settings = lookup_device_gsd_settings (device, info);
|
||||
if (info->gsd_settings)
|
||||
{
|
||||
g_signal_connect (info->gsd_settings, "changed",
|
||||
G_CALLBACK (mapped_device_gsd_setting_changed_cb), info);
|
||||
}
|
||||
|
||||
apply_mappable_device_settings (input_settings, info);
|
||||
|
||||
return TRUE;
|
||||
@ -1384,6 +1197,77 @@ apply_device_settings (MetaInputSettings *input_settings,
|
||||
device);
|
||||
}
|
||||
|
||||
static void
|
||||
update_stylus_pressure (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GSettings *tool_settings;
|
||||
const gint32 *curve;
|
||||
GVariant *variant;
|
||||
gsize n_elems;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
||||
return;
|
||||
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
tool_settings = lookup_tool_settings (tool, device);
|
||||
|
||||
if (clutter_input_device_tool_get_tool_type (tool) ==
|
||||
CLUTTER_INPUT_DEVICE_TOOL_ERASER)
|
||||
variant = g_settings_get_value (tool_settings, "eraser-pressure-curve");
|
||||
else
|
||||
variant = g_settings_get_value (tool_settings, "pressure-curve");
|
||||
|
||||
curve = g_variant_get_fixed_array (variant, &n_elems, sizeof (gint32));
|
||||
if (n_elems != 4)
|
||||
return;
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
input_settings_class->set_stylus_pressure (input_settings, device, tool, curve);
|
||||
}
|
||||
|
||||
static void
|
||||
update_stylus_buttonmap (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
MetaInputSettingsClass *input_settings_class;
|
||||
GDesktopStylusButtonAction primary, secondary;
|
||||
GSettings *tool_settings;
|
||||
|
||||
if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_PEN_DEVICE &&
|
||||
clutter_input_device_get_device_type (device) != CLUTTER_ERASER_DEVICE)
|
||||
return;
|
||||
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
tool_settings = lookup_tool_settings (tool, device);
|
||||
|
||||
primary = g_settings_get_enum (tool_settings, "button-action");
|
||||
secondary = g_settings_get_enum (tool_settings, "secondary-button-action");
|
||||
|
||||
input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings);
|
||||
input_settings_class->set_stylus_button_map (input_settings, device, tool,
|
||||
primary, secondary);
|
||||
}
|
||||
|
||||
static void
|
||||
apply_stylus_settings (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool)
|
||||
{
|
||||
update_stylus_pressure (input_settings, device, tool);
|
||||
update_stylus_buttonmap (input_settings, device, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_device_added (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
@ -1407,6 +1291,18 @@ meta_input_settings_device_removed (ClutterDeviceManager *device_manager,
|
||||
g_hash_table_remove (priv->mappable_devices, device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_tool_changed (ClutterDeviceManager *device_manager,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
MetaInputSettings *input_settings)
|
||||
{
|
||||
if (!tool)
|
||||
return;
|
||||
|
||||
apply_stylus_settings (input_settings, device, tool);
|
||||
}
|
||||
|
||||
static void
|
||||
check_mappable_devices (MetaInputSettings *input_settings)
|
||||
{
|
||||
@ -1460,6 +1356,8 @@ meta_input_settings_init (MetaInputSettings *settings)
|
||||
G_CALLBACK (meta_input_settings_device_added), settings);
|
||||
g_signal_connect (priv->device_manager, "device-removed",
|
||||
G_CALLBACK (meta_input_settings_device_removed), settings);
|
||||
g_signal_connect (priv->device_manager, "tool-changed",
|
||||
G_CALLBACK (meta_input_settings_tool_changed), settings);
|
||||
|
||||
priv->mouse_settings = g_settings_new ("org.gnome.desktop.peripherals.mouse");
|
||||
g_signal_connect (priv->mouse_settings, "changed",
|
||||
@ -1570,46 +1468,13 @@ meta_input_settings_get_tablet_mapping (MetaInputSettings *settings,
|
||||
return g_settings_get_enum (info->settings, "mapping");
|
||||
}
|
||||
|
||||
GDesktopStylusButtonAction
|
||||
meta_input_settings_get_stylus_button_action (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
guint button)
|
||||
{
|
||||
ToolSettings *tool_settings;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool),
|
||||
G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT);
|
||||
|
||||
tool_settings = lookup_tool_settings (tool, current_tablet);
|
||||
|
||||
if (button == 2)
|
||||
return tool_settings->button_action;
|
||||
else if (button == 3)
|
||||
return tool_settings->secondary_button_action;
|
||||
else
|
||||
return G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
|
||||
static GDesktopPadButtonAction
|
||||
meta_input_settings_get_pad_button_action (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button)
|
||||
{
|
||||
/* GsdWacomActionType to GDesktopPadButtonAction map */
|
||||
GDesktopPadButtonAction action_map[4] = {
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE,
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_KEYBINDING,
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_SWITCH_MONITOR,
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_HELP
|
||||
};
|
||||
GDesktopPadButtonAction action;
|
||||
GSettings *settings;
|
||||
guint32 action;
|
||||
|
||||
if (!has_gsd_schemas ())
|
||||
return G_DESKTOP_PAD_BUTTON_ACTION_NONE;
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings),
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
@ -1617,10 +1482,10 @@ meta_input_settings_get_pad_button_action (MetaInputSettings *input_settings,
|
||||
G_DESKTOP_PAD_BUTTON_ACTION_NONE);
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
action = g_settings_get_enum (settings, "action-type");
|
||||
action = g_settings_get_enum (settings, "action");
|
||||
g_object_unref (settings);
|
||||
|
||||
return action_map[action];
|
||||
return action;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBWACOM
|
||||
@ -1723,48 +1588,72 @@ meta_input_settings_cycle_tablet_output (MetaInputSettings *input_settings,
|
||||
g_settings_set_strv (info->settings, "display", edid);
|
||||
}
|
||||
|
||||
static gdouble
|
||||
calculate_bezier_position (gdouble pos,
|
||||
gdouble x1,
|
||||
gdouble y1,
|
||||
gdouble x2,
|
||||
gdouble y2)
|
||||
static void
|
||||
emulate_modifiers (ClutterVirtualInputDevice *device,
|
||||
ClutterModifierType mods,
|
||||
ClutterKeyState state)
|
||||
{
|
||||
gdouble int1_y, int2_y;
|
||||
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 }
|
||||
};
|
||||
|
||||
pos = CLAMP (pos, 0, 1);
|
||||
for (i = 0; i < G_N_ELEMENTS (mod_map); i++)
|
||||
{
|
||||
if ((mods & mod_map[i].mod) == 0)
|
||||
continue;
|
||||
|
||||
/* Intersection between 0,0 and x1,y1 */
|
||||
int1_y = pos * y1;
|
||||
|
||||
/* Intersection between x2,y2 and 1,1 */
|
||||
int2_y = (pos * (1 - y2)) + y2;
|
||||
|
||||
/* Find the new position in the line traced by the previous points */
|
||||
return (pos * (int2_y - int1_y)) + int1_y;
|
||||
clutter_virtual_input_device_notify_keyval (device,
|
||||
clutter_get_current_event_time (),
|
||||
mod_map[i].keyval, state);
|
||||
}
|
||||
}
|
||||
|
||||
gdouble
|
||||
meta_input_settings_translate_tablet_tool_pressure (MetaInputSettings *input_settings,
|
||||
ClutterInputDeviceTool *tool,
|
||||
ClutterInputDevice *current_tablet,
|
||||
gdouble pressure)
|
||||
static void
|
||||
meta_input_settings_emulate_keybinding (MetaInputSettings *input_settings,
|
||||
ClutterInputDevice *pad,
|
||||
guint button,
|
||||
gboolean is_press)
|
||||
{
|
||||
ToolSettings *tool_settings;
|
||||
MetaInputSettingsPrivate *priv;
|
||||
ClutterKeyState state;
|
||||
GSettings *settings;
|
||||
guint key, mods;
|
||||
gchar *accel;
|
||||
|
||||
pressure = CLAMP (pressure, 0, 1);
|
||||
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);
|
||||
|
||||
g_return_val_if_fail (META_IS_INPUT_SETTINGS (input_settings), pressure);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE_TOOL (tool), pressure);
|
||||
g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (current_tablet), pressure);
|
||||
/* FIXME: This is appalling */
|
||||
gtk_accelerator_parse (accel, &key, &mods);
|
||||
g_free (accel);
|
||||
|
||||
tool_settings = lookup_tool_settings (tool, current_tablet);
|
||||
pressure = calculate_bezier_position (pressure,
|
||||
tool_settings->curve[0],
|
||||
tool_settings->curve[1],
|
||||
tool_settings->curve[2],
|
||||
tool_settings->curve[3]);
|
||||
return pressure;
|
||||
if (!priv->virtual_pad_keyboard)
|
||||
{
|
||||
ClutterDeviceManager *manager = clutter_device_manager_get_default ();
|
||||
|
||||
priv->virtual_pad_keyboard =
|
||||
clutter_device_manager_create_virtual_device (manager,
|
||||
CLUTTER_KEYBOARD_DEVICE);
|
||||
}
|
||||
|
||||
state = is_press ? CLUTTER_KEY_STATE_PRESSED : CLUTTER_KEY_STATE_RELEASED;
|
||||
|
||||
if (is_press)
|
||||
emulate_modifiers (priv->virtual_pad_keyboard, mods, state);
|
||||
|
||||
clutter_virtual_input_device_notify_keyval (priv->virtual_pad_keyboard,
|
||||
clutter_get_current_event_time (),
|
||||
key, state);
|
||||
if (!is_press)
|
||||
emulate_modifiers (priv->virtual_pad_keyboard, mods, state);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1807,6 +1696,9 @@ meta_input_settings_handle_pad_button (MetaInputSettings *input_settings,
|
||||
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);
|
||||
return TRUE;
|
||||
case G_DESKTOP_PAD_BUTTON_ACTION_NONE:
|
||||
default:
|
||||
return FALSE;
|
||||
@ -1835,7 +1727,7 @@ meta_input_settings_get_pad_button_action_label (MetaInputSettings *input_setti
|
||||
gchar *accel;
|
||||
|
||||
settings = lookup_pad_button_settings (pad, button);
|
||||
accel = g_settings_get_string (settings, "custom-action");
|
||||
accel = g_settings_get_string (settings, "keybinding");
|
||||
g_object_unref (settings);
|
||||
|
||||
return accel;
|
||||
|
@ -454,7 +454,7 @@ handle_end_element (GMarkupParseContext *context,
|
||||
{
|
||||
if (strcmp (element_name, "configuration") == 0 && parser->unknown_count == 0)
|
||||
{
|
||||
MetaConfiguration *config = g_slice_new (MetaConfiguration);
|
||||
MetaConfiguration *config = config_new ();
|
||||
|
||||
g_assert (parser->key_array->len == parser->output_array->len);
|
||||
|
||||
|
@ -290,11 +290,13 @@ meta_backend_native_create_renderer (MetaBackend *backend)
|
||||
MetaBackendNativePrivate *priv =
|
||||
meta_backend_native_get_instance_private (native);
|
||||
int kms_fd;
|
||||
GError *error;
|
||||
const char *kms_file_path;
|
||||
GError *error = NULL;
|
||||
MetaRendererNative *renderer_native;
|
||||
|
||||
kms_fd = meta_launcher_get_kms_fd (priv->launcher);
|
||||
renderer_native = meta_renderer_native_new (kms_fd, &error);
|
||||
kms_file_path = meta_launcher_get_kms_file_path (priv->launcher);
|
||||
renderer_native = meta_renderer_native_new (kms_fd, kms_file_path, &error);
|
||||
if (!renderer_native)
|
||||
{
|
||||
meta_warning ("Failed to create renderer: %s\n", error->message);
|
||||
|
@ -527,6 +527,9 @@ meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *r
|
||||
CoglTexture *texture;
|
||||
uint width, height;
|
||||
|
||||
if (!priv->gbm)
|
||||
return;
|
||||
|
||||
/* Destroy any previous pending cursor buffer; we'll always either fail (which
|
||||
* should unset, or succeed, which will set new buffer.
|
||||
*/
|
||||
@ -614,6 +617,11 @@ meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *ren
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
MetaCursorRendererNativePrivate *priv =
|
||||
meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
if (!priv->gbm)
|
||||
return;
|
||||
|
||||
invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite);
|
||||
|
||||
|
@ -162,6 +162,7 @@ meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
|
||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
|
||||
|
||||
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
|
||||
monitor_native->last_event_time = g_get_monotonic_time ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <clutter/evdev/clutter-evdev.h>
|
||||
#include <linux/input-event-codes.h>
|
||||
#include <libinput.h>
|
||||
|
||||
#include "meta-input-settings-native.h"
|
||||
@ -141,28 +142,18 @@ static gboolean
|
||||
device_set_scroll_method (struct libinput_device *libinput_device,
|
||||
enum libinput_config_scroll_method method)
|
||||
{
|
||||
enum libinput_config_scroll_method supported;
|
||||
|
||||
supported = libinput_device_config_scroll_get_methods (libinput_device);
|
||||
|
||||
if (method & supported)
|
||||
enum libinput_config_status status =
|
||||
libinput_device_config_scroll_set_method (libinput_device, method);
|
||||
|
||||
return (method & supported) != 0;
|
||||
return status == LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_set_click_method (struct libinput_device *libinput_device,
|
||||
enum libinput_config_click_method method)
|
||||
{
|
||||
enum libinput_config_click_method supported;
|
||||
|
||||
supported = libinput_device_config_click_get_methods (libinput_device);
|
||||
|
||||
if (method & supported)
|
||||
enum libinput_config_status status =
|
||||
libinput_device_config_click_set_method (libinput_device, method);
|
||||
|
||||
return (method & supported) != 0;
|
||||
return status == LIBINPUT_CONFIG_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -170,32 +161,16 @@ meta_input_settings_native_set_edge_scroll (MetaInputSettings *settin
|
||||
ClutterInputDevice *device,
|
||||
gboolean edge_scrolling_enabled)
|
||||
{
|
||||
enum libinput_config_scroll_method scroll_method = 0;
|
||||
struct libinput_device *libinput_device;
|
||||
enum libinput_config_scroll_method supported;
|
||||
enum libinput_config_scroll_method current;
|
||||
enum libinput_config_scroll_method current, method;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
if (!libinput_device)
|
||||
return;
|
||||
supported = libinput_device_config_scroll_get_methods (libinput_device);
|
||||
|
||||
method = edge_scrolling_enabled ? LIBINPUT_CONFIG_SCROLL_EDGE : LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
current = libinput_device_config_scroll_get_method (libinput_device);
|
||||
current &= ~LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
|
||||
/* Don't set edge scrolling if two-finger scrolling is enabled and available */
|
||||
if (current == LIBINPUT_CONFIG_SCROLL_2FG)
|
||||
return;
|
||||
|
||||
if (supported & LIBINPUT_CONFIG_SCROLL_EDGE &&
|
||||
edge_scrolling_enabled)
|
||||
{
|
||||
scroll_method = LIBINPUT_CONFIG_SCROLL_EDGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
}
|
||||
|
||||
device_set_scroll_method (libinput_device, scroll_method);
|
||||
device_set_scroll_method (libinput_device, current | method);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -203,31 +178,16 @@ meta_input_settings_native_set_two_finger_scroll (MetaInputSettings *
|
||||
ClutterInputDevice *device,
|
||||
gboolean two_finger_scroll_enabled)
|
||||
{
|
||||
enum libinput_config_scroll_method scroll_method = 0;
|
||||
struct libinput_device *libinput_device;
|
||||
enum libinput_config_scroll_method supported;
|
||||
enum libinput_config_scroll_method current;
|
||||
enum libinput_config_scroll_method current, method;
|
||||
|
||||
libinput_device = clutter_evdev_input_device_get_libinput_device (device);
|
||||
supported = libinput_device_config_scroll_get_methods (libinput_device);
|
||||
|
||||
method = two_finger_scroll_enabled ? LIBINPUT_CONFIG_SCROLL_2FG : LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
current = libinput_device_config_scroll_get_method (libinput_device);
|
||||
current &= ~LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
|
||||
if (two_finger_scroll_enabled &&
|
||||
!(supported & LIBINPUT_CONFIG_SCROLL_2FG))
|
||||
return;
|
||||
|
||||
if (two_finger_scroll_enabled)
|
||||
{
|
||||
scroll_method = LIBINPUT_CONFIG_SCROLL_2FG;
|
||||
}
|
||||
else if (current != LIBINPUT_CONFIG_SCROLL_EDGE)
|
||||
{
|
||||
scroll_method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
device_set_scroll_method (libinput_device, scroll_method);
|
||||
device_set_scroll_method (libinput_device, current | method);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -436,6 +396,54 @@ meta_input_settings_native_set_tablet_area (MetaInputSettings *settings,
|
||||
/* FIXME: Implement */
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_stylus_pressure (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
const gint curve[4])
|
||||
{
|
||||
gdouble pressure_curve[4];
|
||||
|
||||
pressure_curve[0] = (gdouble) curve[0] / 100;
|
||||
pressure_curve[1] = (gdouble) curve[1] / 100;
|
||||
pressure_curve[2] = (gdouble) curve[2] / 100;
|
||||
pressure_curve[3] = (gdouble) curve[3] / 100;
|
||||
|
||||
clutter_evdev_input_device_tool_set_pressure_curve (tool, pressure_curve);
|
||||
}
|
||||
|
||||
static guint
|
||||
action_to_evcode (GDesktopStylusButtonAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE:
|
||||
return BTN_STYLUS;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT:
|
||||
return BTN_STYLUS2;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK:
|
||||
return BTN_BACK;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD:
|
||||
return BTN_FORWARD;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_set_stylus_button_map (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
GDesktopStylusButtonAction primary,
|
||||
GDesktopStylusButtonAction secondary)
|
||||
{
|
||||
clutter_evdev_input_device_tool_set_button_code (tool, CLUTTER_BUTTON_MIDDLE,
|
||||
action_to_evcode (primary));
|
||||
clutter_evdev_input_device_tool_set_button_code (tool, CLUTTER_BUTTON_SECONDARY,
|
||||
action_to_evcode (secondary));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
{
|
||||
@ -459,6 +467,9 @@ meta_input_settings_native_class_init (MetaInputSettingsNativeClass *klass)
|
||||
|
||||
input_settings_class->set_mouse_accel_profile = meta_input_settings_native_set_mouse_accel_profile;
|
||||
input_settings_class->set_trackball_accel_profile = meta_input_settings_native_set_trackball_accel_profile;
|
||||
|
||||
input_settings_class->set_stylus_pressure = meta_input_settings_native_set_stylus_pressure;
|
||||
input_settings_class->set_stylus_button_map = meta_input_settings_native_set_stylus_button_map;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -47,6 +47,8 @@
|
||||
#include "meta-idle-monitor-native.h"
|
||||
#include "meta-renderer-native.h"
|
||||
|
||||
#define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor"
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevDevice, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref)
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevEnumerator, g_object_unref)
|
||||
@ -59,6 +61,7 @@ struct _MetaLauncher
|
||||
gboolean session_active;
|
||||
|
||||
int kms_fd;
|
||||
char *kms_file_path;
|
||||
};
|
||||
|
||||
static Login1Session *
|
||||
@ -282,6 +285,55 @@ on_active_changed (Login1Session *session,
|
||||
sync_active (self);
|
||||
}
|
||||
|
||||
static guint
|
||||
count_devices_with_connectors (const gchar *seat_name,
|
||||
GList *devices)
|
||||
{
|
||||
g_autoptr (GHashTable) cards = NULL;
|
||||
GList *tmp;
|
||||
|
||||
cards = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
|
||||
for (tmp = devices; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
GUdevDevice *device = tmp->data;
|
||||
g_autoptr (GUdevDevice) parent_device = NULL;
|
||||
const gchar *parent_device_type = NULL;
|
||||
const gchar *parent_device_name = NULL;
|
||||
const gchar *card_seat;
|
||||
|
||||
/* filter out the real card devices, we only care about the connectors */
|
||||
if (g_udev_device_get_device_type (device) != G_UDEV_DEVICE_TYPE_NONE)
|
||||
continue;
|
||||
|
||||
/* only connectors have a modes attribute */
|
||||
if (!g_udev_device_has_sysfs_attr (device, "modes"))
|
||||
continue;
|
||||
|
||||
parent_device = g_udev_device_get_parent (device);
|
||||
|
||||
if (g_udev_device_get_device_type (parent_device) == G_UDEV_DEVICE_TYPE_CHAR)
|
||||
parent_device_type = g_udev_device_get_property (parent_device, "DEVTYPE");
|
||||
|
||||
if (g_strcmp0 (parent_device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0)
|
||||
continue;
|
||||
|
||||
card_seat = g_udev_device_get_property (parent_device, "ID_SEAT");
|
||||
|
||||
if (!card_seat)
|
||||
card_seat = "seat0";
|
||||
|
||||
if (g_strcmp0 (seat_name, card_seat) != 0)
|
||||
continue;
|
||||
|
||||
parent_device_name = g_udev_device_get_name (parent_device);
|
||||
g_hash_table_insert (cards,
|
||||
(gpointer) parent_device_name ,
|
||||
g_steal_pointer (&parent_device));
|
||||
}
|
||||
|
||||
return g_hash_table_size (cards);
|
||||
}
|
||||
|
||||
static gchar *
|
||||
get_primary_gpu_path (const gchar *seat_name)
|
||||
{
|
||||
@ -295,22 +347,46 @@ get_primary_gpu_path (const gchar *seat_name)
|
||||
g_udev_enumerator_add_match_name (enumerator, "card*");
|
||||
g_udev_enumerator_add_match_tag (enumerator, "seat");
|
||||
|
||||
/* We need to explicitly match the subsystem for now.
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=773224
|
||||
*/
|
||||
g_udev_enumerator_add_match_subsystem (enumerator, "drm");
|
||||
|
||||
devices = g_udev_enumerator_execute (enumerator);
|
||||
if (!devices)
|
||||
goto out;
|
||||
|
||||
/* For now, fail on systems where some of the connectors
|
||||
* are connected to secondary gpus.
|
||||
*
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=771442
|
||||
*/
|
||||
if (g_getenv ("MUTTER_ALLOW_HYBRID_GPUS") == NULL)
|
||||
{
|
||||
guint num_devices;
|
||||
|
||||
num_devices = count_devices_with_connectors (seat_name, devices);
|
||||
if (num_devices != 1)
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (tmp = devices; tmp != NULL; tmp = tmp->next)
|
||||
{
|
||||
g_autoptr (GUdevDevice) platform_device = NULL;
|
||||
g_autoptr (GUdevDevice) pci_device = NULL;
|
||||
GUdevDevice *dev = tmp->data;
|
||||
gint boot_vga;
|
||||
const gchar *device_type;
|
||||
const gchar *device_seat;
|
||||
|
||||
/* filter out devices that are not character device, like card0-VGA-1 */
|
||||
if (g_udev_device_get_device_type (dev) != G_UDEV_DEVICE_TYPE_CHAR)
|
||||
continue;
|
||||
|
||||
device_type = g_udev_device_get_property (dev, "DEVTYPE");
|
||||
if (g_strcmp0 (device_type, DRM_CARD_UDEV_DEVICE_TYPE) != 0)
|
||||
continue;
|
||||
|
||||
device_seat = g_udev_device_get_property (dev, "ID_SEAT");
|
||||
if (!device_seat)
|
||||
{
|
||||
@ -350,9 +426,9 @@ get_primary_gpu_path (const gchar *seat_name)
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
g_list_free_full (devices, g_object_unref);
|
||||
|
||||
out:
|
||||
return path;
|
||||
}
|
||||
|
||||
@ -360,6 +436,7 @@ static gboolean
|
||||
get_kms_fd (Login1Session *session_proxy,
|
||||
const gchar *seat_id,
|
||||
int *fd_out,
|
||||
char **kms_file_path_out,
|
||||
GError **error)
|
||||
{
|
||||
int major, minor;
|
||||
@ -391,6 +468,7 @@ get_kms_fd (Login1Session *session_proxy,
|
||||
}
|
||||
|
||||
*fd_out = fd;
|
||||
*kms_file_path_out = g_steal_pointer (&path);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -434,6 +512,7 @@ meta_launcher_new (GError **error)
|
||||
g_autofree char *seat_id = NULL;
|
||||
gboolean have_control = FALSE;
|
||||
int kms_fd;
|
||||
char *kms_file_path;
|
||||
|
||||
session_proxy = get_session_proxy (NULL, error);
|
||||
if (!session_proxy)
|
||||
@ -455,7 +534,7 @@ meta_launcher_new (GError **error)
|
||||
if (!seat_proxy)
|
||||
goto fail;
|
||||
|
||||
if (!get_kms_fd (session_proxy, seat_id, &kms_fd, error))
|
||||
if (!get_kms_fd (session_proxy, seat_id, &kms_fd, &kms_file_path, error))
|
||||
goto fail;
|
||||
|
||||
self = g_slice_new0 (MetaLauncher);
|
||||
@ -464,6 +543,7 @@ meta_launcher_new (GError **error)
|
||||
|
||||
self->session_active = TRUE;
|
||||
self->kms_fd = kms_fd;
|
||||
self->kms_file_path = kms_file_path;
|
||||
|
||||
clutter_evdev_set_device_callbacks (on_evdev_device_open,
|
||||
on_evdev_device_close,
|
||||
@ -483,6 +563,7 @@ meta_launcher_free (MetaLauncher *self)
|
||||
{
|
||||
g_object_unref (self->seat_proxy);
|
||||
g_object_unref (self->session_proxy);
|
||||
g_free (self->kms_file_path);
|
||||
g_slice_free (MetaLauncher, self);
|
||||
}
|
||||
|
||||
@ -510,3 +591,9 @@ meta_launcher_get_kms_fd (MetaLauncher *self)
|
||||
{
|
||||
return self->kms_fd;
|
||||
}
|
||||
|
||||
const char *
|
||||
meta_launcher_get_kms_file_path (MetaLauncher *self)
|
||||
{
|
||||
return self->kms_file_path;
|
||||
}
|
||||
|
@ -36,4 +36,6 @@ gboolean meta_launcher_activate_vt (MetaLauncher *self,
|
||||
|
||||
int meta_launcher_get_kms_fd (MetaLauncher *self);
|
||||
|
||||
const char * meta_launcher_get_kms_file_path (MetaLauncher *self);
|
||||
|
||||
#endif /* META_LAUNCHER_H */
|
||||
|
@ -1531,34 +1531,22 @@ get_crtc_connectors (MetaMonitorManager *manager,
|
||||
uint32_t **connectors,
|
||||
unsigned int *n_connectors)
|
||||
{
|
||||
GArray *connectors_array = NULL;
|
||||
unsigned int i;
|
||||
GArray *connectors_array = g_array_new (FALSE, FALSE, sizeof (uint32_t));
|
||||
|
||||
for (i = 0; i < manager->n_outputs; i++)
|
||||
{
|
||||
MetaOutput *output = &manager->outputs[i];
|
||||
|
||||
if (output->crtc == crtc)
|
||||
{
|
||||
if (!connectors_array)
|
||||
connectors_array = g_array_new (FALSE, FALSE, sizeof (uint32_t));
|
||||
g_array_append_val (connectors_array, output->winsys_id);
|
||||
}
|
||||
g_array_append_val (connectors_array, output->winsys_id);
|
||||
}
|
||||
|
||||
if (connectors_array)
|
||||
{
|
||||
*connectors = (uint32_t *) connectors_array->data;
|
||||
*n_connectors = connectors_array->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*connectors = NULL;
|
||||
*n_connectors = 0;
|
||||
}
|
||||
*n_connectors = connectors_array->len;
|
||||
*connectors = (uint32_t *) g_array_free (connectors_array, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
gboolean
|
||||
meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||
MetaCRTC *crtc,
|
||||
int x,
|
||||
@ -1583,9 +1571,14 @@ meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||
x, y,
|
||||
connectors, n_connectors,
|
||||
mode) != 0)
|
||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||
{
|
||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (connectors);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1634,7 +1627,8 @@ meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t fb_id,
|
||||
GClosure *flip_closure)
|
||||
GClosure *flip_closure,
|
||||
gboolean *fb_in_use)
|
||||
{
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||
uint32_t *connectors;
|
||||
@ -1661,14 +1655,21 @@ meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||
}
|
||||
|
||||
if (manager_kms->page_flips_not_supported)
|
||||
meta_monitor_manager_kms_apply_crtc_mode (manager_kms,
|
||||
crtc,
|
||||
x, y,
|
||||
fb_id);
|
||||
{
|
||||
if (meta_monitor_manager_kms_apply_crtc_mode (manager_kms,
|
||||
crtc,
|
||||
x, y,
|
||||
fb_id))
|
||||
{
|
||||
*fb_in_use = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
return FALSE;
|
||||
|
||||
*fb_in_use = TRUE;
|
||||
g_closure_ref (flip_closure);
|
||||
|
||||
return TRUE;
|
||||
|
@ -39,11 +39,11 @@ GType meta_monitor_manager_kms_get_type (void);
|
||||
|
||||
typedef void (*MetaKmsFlipCallback) (void *user_data);
|
||||
|
||||
void meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||
MetaCRTC *crtc,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t fb_id);
|
||||
gboolean meta_monitor_manager_kms_apply_crtc_mode (MetaMonitorManagerKms *manager_kms,
|
||||
MetaCRTC *crtc,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t fb_id);
|
||||
|
||||
gboolean meta_monitor_manager_kms_is_crtc_active (MetaMonitorManagerKms *manager_kms,
|
||||
MetaCRTC *crtc);
|
||||
@ -53,7 +53,8 @@ gboolean meta_monitor_manager_kms_flip_crtc (MetaMonitorManagerKms *manager_kms,
|
||||
int x,
|
||||
int y,
|
||||
uint32_t fb_id,
|
||||
GClosure *flip_closure);
|
||||
GClosure *flip_closure,
|
||||
gboolean *fb_in_use);
|
||||
|
||||
void meta_monitor_manager_kms_wait_for_flip (MetaMonitorManagerKms *manager_kms);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,8 +35,19 @@ G_DECLARE_FINAL_TYPE (MetaRendererNative, meta_renderer_native,
|
||||
META, RENDERER_NATIVE,
|
||||
MetaRenderer)
|
||||
|
||||
MetaRendererNative *meta_renderer_native_new (int kms_fd,
|
||||
GError **error);
|
||||
typedef enum _MetaRendererNativeMode
|
||||
{
|
||||
META_RENDERER_NATIVE_MODE_GBM,
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
META_RENDERER_NATIVE_MODE_EGL_DEVICE
|
||||
#endif
|
||||
} MetaRendererNativeMode;
|
||||
|
||||
MetaRendererNative *meta_renderer_native_new (int kms_fd,
|
||||
const char *kms_file_path,
|
||||
GError **error);
|
||||
|
||||
MetaRendererNativeMode meta_renderer_native_get_mode (MetaRendererNative *renderer_native);
|
||||
|
||||
struct gbm_device * meta_renderer_native_get_gbm (MetaRendererNative *renderer_native);
|
||||
|
||||
|
@ -188,10 +188,20 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gboolean enabled)
|
||||
{
|
||||
guchar value = (enabled) ? 1 : 0;
|
||||
guchar value;
|
||||
|
||||
change_property (device, "libinput Left Handed Enabled",
|
||||
XA_INTEGER, 8, &value, 1);
|
||||
if (clutter_input_device_get_device_type (device) == CLUTTER_TABLET_DEVICE)
|
||||
{
|
||||
value = enabled ? 3 : 0;
|
||||
change_property (device, "Wacom Rotation",
|
||||
XA_INTEGER, 8, &value, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = enabled ? 1 : 0;
|
||||
change_property (device, "libinput Left Handed Enabled",
|
||||
XA_INTEGER, 8, &value, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -222,32 +232,27 @@ meta_input_settings_x11_set_edge_scroll (MetaInputSettings *settings,
|
||||
gboolean edge_scroll_enabled)
|
||||
{
|
||||
guchar values[SCROLL_METHOD_NUM_FIELDS] = { 0 }; /* 2fg, edge, button. The last value is unused */
|
||||
guchar *defaults;
|
||||
guchar *available;
|
||||
guchar *current = NULL;
|
||||
guchar *available = NULL;
|
||||
|
||||
available = get_property (device, "libinput Scroll Methods Available",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
defaults = get_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
if (!available || !defaults)
|
||||
if (!available || !available[SCROLL_METHOD_FIELD_EDGE])
|
||||
goto out;
|
||||
|
||||
memcpy (values, defaults, SCROLL_METHOD_NUM_FIELDS);
|
||||
current = get_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
if (!current)
|
||||
goto out;
|
||||
|
||||
/* Don't set edge scrolling if two-finger scrolling is enabled and available */
|
||||
if (available[SCROLL_METHOD_FIELD_EDGE] &&
|
||||
!(available[SCROLL_METHOD_FIELD_2FG] && values[SCROLL_METHOD_FIELD_2FG]))
|
||||
{
|
||||
values[1] = !!edge_scroll_enabled;
|
||||
change_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, &values, SCROLL_METHOD_NUM_FIELDS);
|
||||
}
|
||||
memcpy (values, current, SCROLL_METHOD_NUM_FIELDS);
|
||||
|
||||
out:
|
||||
if (available)
|
||||
meta_XFree (available);
|
||||
if (defaults)
|
||||
meta_XFree (defaults);
|
||||
values[SCROLL_METHOD_FIELD_EDGE] = !!edge_scroll_enabled;
|
||||
change_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, &values, SCROLL_METHOD_NUM_FIELDS);
|
||||
out:
|
||||
meta_XFree (current);
|
||||
meta_XFree (available);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -256,44 +261,27 @@ meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings *set
|
||||
gboolean two_finger_scroll_enabled)
|
||||
{
|
||||
guchar values[SCROLL_METHOD_NUM_FIELDS] = { 0 }; /* 2fg, edge, button. The last value is unused */
|
||||
guchar *defaults;
|
||||
guchar *available;
|
||||
gboolean changed;
|
||||
guchar *current = NULL;
|
||||
guchar *available = NULL;
|
||||
|
||||
available = get_property (device, "libinput Scroll Methods Available",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
defaults = get_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
if (!available || !defaults)
|
||||
if (!available || !available[SCROLL_METHOD_FIELD_2FG])
|
||||
goto out;
|
||||
|
||||
memcpy (values, defaults, SCROLL_METHOD_NUM_FIELDS);
|
||||
changed = FALSE;
|
||||
current = get_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS);
|
||||
if (!current)
|
||||
goto out;
|
||||
|
||||
if (available[SCROLL_METHOD_FIELD_2FG])
|
||||
{
|
||||
values[SCROLL_METHOD_FIELD_2FG] = !!two_finger_scroll_enabled;
|
||||
changed = TRUE;
|
||||
}
|
||||
memcpy (values, current, SCROLL_METHOD_NUM_FIELDS);
|
||||
|
||||
/* Disable edge scrolling when two-finger scrolling is enabled */
|
||||
if (values[SCROLL_METHOD_FIELD_2FG] && values[SCROLL_METHOD_FIELD_EDGE])
|
||||
{
|
||||
values[SCROLL_METHOD_FIELD_EDGE] = 0;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
change_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, &values, SCROLL_METHOD_NUM_FIELDS);
|
||||
}
|
||||
|
||||
out:
|
||||
if (available)
|
||||
meta_XFree (available);
|
||||
if (defaults)
|
||||
meta_XFree (defaults);
|
||||
values[SCROLL_METHOD_FIELD_2FG] = !!two_finger_scroll_enabled;
|
||||
change_property (device, "libinput Scroll Method Enabled",
|
||||
XA_INTEGER, 8, &values, SCROLL_METHOD_NUM_FIELDS);
|
||||
out:
|
||||
meta_XFree (current);
|
||||
meta_XFree (available);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -505,14 +493,76 @@ meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
GDesktopTabletMapping mapping)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
int device_id = clutter_input_device_get_device_id (device);
|
||||
XDevice *xdev;
|
||||
|
||||
if (!display)
|
||||
return;
|
||||
|
||||
/* Grab the puke bucket! */
|
||||
meta_error_trap_push (display);
|
||||
xdev = XOpenDevice (xdisplay, device_id);
|
||||
if (xdev)
|
||||
{
|
||||
XSetDeviceMode (xdisplay, xdev,
|
||||
mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE ?
|
||||
Absolute : Relative);
|
||||
XCloseDevice (xdisplay, xdev);
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display))
|
||||
{
|
||||
g_warning ("Could not set tablet mapping for %s",
|
||||
clutter_input_device_get_device_name (device));
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
device_query_area (ClutterInputDevice *device,
|
||||
gint *width,
|
||||
gint *height)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
gint device_id, n_devices, i;
|
||||
XIDeviceInfo *info;
|
||||
Atom abs_x, abs_y;
|
||||
|
||||
*width = *height = 0;
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
info = XIQueryDevice (xdisplay, device_id, &n_devices);
|
||||
if (n_devices == 0)
|
||||
return FALSE;
|
||||
|
||||
abs_x = XInternAtom (xdisplay, "Abs X", True);
|
||||
abs_y = XInternAtom (xdisplay, "Abs Y", True);
|
||||
|
||||
for (i = 0; i < info->num_classes; i++)
|
||||
{
|
||||
XIValuatorClassInfo *valuator = (XIValuatorClassInfo *) info->classes[i];
|
||||
|
||||
if (valuator->type != XIValuatorClass)
|
||||
continue;
|
||||
if (valuator->label == abs_x)
|
||||
*width = valuator->max - valuator->min;
|
||||
else if (valuator->label == abs_y)
|
||||
*height = valuator->max - valuator->min;
|
||||
}
|
||||
|
||||
XIFreeDeviceInfo (info);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaOutput *output,
|
||||
gboolean keep_aspect)
|
||||
update_tablet_area (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
gint32 *area)
|
||||
{
|
||||
change_property (device, "Wacom Tablet Area",
|
||||
XA_INTEGER, 32, area, 4);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -523,6 +573,61 @@ meta_input_settings_x11_set_tablet_area (MetaInputSettings *settings,
|
||||
gdouble padding_top,
|
||||
gdouble padding_bottom)
|
||||
{
|
||||
gint32 width, height, area[4] = { 0 };
|
||||
|
||||
if (!device_query_area (device, &width, &height))
|
||||
return;
|
||||
|
||||
area[0] = width * padding_left;
|
||||
area[1] = height * padding_top;
|
||||
area[2] = width - (width * padding_right);
|
||||
area[2] = height - (height * padding_bottom);
|
||||
update_tablet_area (settings, device, area);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_tablet_keep_aspect (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
MetaOutput *output,
|
||||
gboolean keep_aspect)
|
||||
{
|
||||
gint32 width, height, dev_width, dev_height, area[4] = { 0 };
|
||||
|
||||
if (!device_query_area (device, &dev_width, &dev_height))
|
||||
return;
|
||||
|
||||
if (keep_aspect)
|
||||
{
|
||||
gdouble output_aspect, dev_aspect;
|
||||
|
||||
if (output && output->crtc)
|
||||
{
|
||||
width = output->crtc->rect.width;
|
||||
height = output->crtc->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_limits (monitor_manager,
|
||||
&width, &height);
|
||||
}
|
||||
|
||||
output_aspect = (gdouble) width / height;
|
||||
dev_aspect = (gdouble) dev_width / dev_height;
|
||||
|
||||
if (dev_aspect > output_aspect)
|
||||
dev_width = dev_height * output_aspect;
|
||||
else if (dev_aspect < output_aspect)
|
||||
dev_height = dev_width / output_aspect;
|
||||
}
|
||||
|
||||
area[2] = dev_width;
|
||||
area[3] = dev_height;
|
||||
update_tablet_area (settings, device, area);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -539,6 +644,76 @@ meta_input_settings_x11_dispose (GObject *object)
|
||||
G_OBJECT_CLASS (meta_input_settings_x11_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static guint
|
||||
action_to_button (GDesktopStylusButtonAction action,
|
||||
guint button)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE:
|
||||
return CLUTTER_BUTTON_MIDDLE;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT:
|
||||
return CLUTTER_BUTTON_SECONDARY;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK:
|
||||
return 8;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD:
|
||||
return 9;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT:
|
||||
default:
|
||||
return button;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
GDesktopStylusButtonAction primary,
|
||||
GDesktopStylusButtonAction secondary)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));
|
||||
int device_id = clutter_input_device_get_device_id (device);
|
||||
XDevice *xdev;
|
||||
|
||||
if (!display)
|
||||
return;
|
||||
|
||||
/* Grab the puke bucket! */
|
||||
meta_error_trap_push (display);
|
||||
xdev = XOpenDevice (xdisplay, device_id);
|
||||
if (xdev)
|
||||
{
|
||||
guchar map[3] = {
|
||||
CLUTTER_BUTTON_PRIMARY,
|
||||
action_to_button (primary, CLUTTER_BUTTON_MIDDLE),
|
||||
action_to_button (secondary, CLUTTER_BUTTON_SECONDARY),
|
||||
};
|
||||
|
||||
XSetDeviceButtonMapping (xdisplay, xdev, map, G_N_ELEMENTS (map));
|
||||
XCloseDevice (xdisplay, xdev);
|
||||
}
|
||||
|
||||
if (meta_error_trap_pop_with_return (display))
|
||||
{
|
||||
g_warning ("Could not set stylus button map for %s",
|
||||
clutter_input_device_get_device_name (device));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_set_stylus_pressure (MetaInputSettings *settings,
|
||||
ClutterInputDevice *device,
|
||||
ClutterInputDeviceTool *tool,
|
||||
const gint32 pressure[4])
|
||||
{
|
||||
guchar values[4] = { pressure[0], pressure[1], pressure[2], pressure[3] };
|
||||
|
||||
change_property (device, "Wacom Pressurecurve", XA_INTEGER, 8,
|
||||
&values, G_N_ELEMENTS (values));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
|
||||
{
|
||||
@ -565,6 +740,9 @@ meta_input_settings_x11_class_init (MetaInputSettingsX11Class *klass)
|
||||
|
||||
input_settings_class->set_mouse_accel_profile = meta_input_settings_x11_set_mouse_accel_profile;
|
||||
input_settings_class->set_trackball_accel_profile = meta_input_settings_x11_set_trackball_accel_profile;
|
||||
|
||||
input_settings_class->set_stylus_pressure = meta_input_settings_x11_set_stylus_pressure;
|
||||
input_settings_class->set_stylus_button_map = meta_input_settings_x11_set_stylus_button_map;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -352,6 +352,14 @@ meta_begin_modal_for_plugin (MetaCompositor *compositor,
|
||||
*/
|
||||
MetaDisplay *display = compositor->display;
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
if (display->grab_op == META_GRAB_OP_WAYLAND_POPUP)
|
||||
{
|
||||
MetaWaylandSeat *seat = meta_wayland_compositor_get_default ()->seat;
|
||||
meta_wayland_pointer_end_popup_grab (seat->pointer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (is_modal (display) || display->grab_op != META_GRAB_OP_NONE)
|
||||
return FALSE;
|
||||
|
||||
@ -1005,6 +1013,7 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_sync_actor_geometry (window_actor, did_placement);
|
||||
meta_plugin_manager_event_size_changed (compositor->plugin_mgr, window_actor);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -202,6 +202,17 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
meta_plugin_manager_event_size_changed (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor)
|
||||
{
|
||||
MetaPlugin *plugin = plugin_mgr->plugin;
|
||||
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
|
||||
|
||||
if (klass->size_changed)
|
||||
klass->size_changed (plugin, actor);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_plugin_manager_event_size_change (MetaPluginManager *plugin_mgr,
|
||||
MetaWindowActor *actor,
|
||||
|
@ -50,6 +50,9 @@ gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
MetaPluginEffect event);
|
||||
|
||||
void meta_plugin_manager_event_size_changed (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
gboolean meta_plugin_manager_event_size_change (MetaPluginManager *mgr,
|
||||
MetaWindowActor *actor,
|
||||
MetaSizeChange which_change,
|
||||
|
@ -32,6 +32,10 @@
|
||||
ClutterActor *meta_shaped_texture_new (void);
|
||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *texture);
|
||||
void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
|
||||
gboolean is_y_inverted);
|
||||
void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
|
||||
CoglSnippet *snippet);
|
||||
void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
|
||||
guint fallback_width,
|
||||
guint fallback_height);
|
||||
|
@ -77,6 +77,13 @@ struct _MetaShapedTexturePrivate
|
||||
|
||||
CoglTexture *texture;
|
||||
CoglTexture *mask_texture;
|
||||
CoglSnippet *snippet;
|
||||
|
||||
CoglPipeline *base_pipeline;
|
||||
CoglPipeline *masked_pipeline;
|
||||
CoglPipeline *unblended_pipeline;
|
||||
|
||||
gboolean is_y_inverted;
|
||||
|
||||
/* The region containing only fully opaque pixels */
|
||||
cairo_region_t *opaque_region;
|
||||
@ -126,6 +133,7 @@ meta_shaped_texture_init (MetaShapedTexture *self)
|
||||
priv->texture = NULL;
|
||||
priv->mask_texture = NULL;
|
||||
priv->create_mipmaps = TRUE;
|
||||
priv->is_y_inverted = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -167,6 +175,16 @@ set_clip_region (MetaShapedTexture *self,
|
||||
priv->clip_region = cairo_region_copy (clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
g_clear_pointer (&priv->base_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->masked_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->unblended_pipeline, cogl_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_dispose (GObject *object)
|
||||
{
|
||||
@ -184,61 +202,98 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
set_unobscured_region (self, NULL);
|
||||
set_clip_region (self, NULL);
|
||||
|
||||
meta_shaped_texture_reset_pipelines (self);
|
||||
|
||||
g_clear_pointer (&priv->snippet, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_base_pipeline (CoglContext *ctx)
|
||||
get_base_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
static CoglPipeline *template = NULL;
|
||||
if (G_UNLIKELY (template == NULL))
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
if (priv->base_pipeline)
|
||||
return priv->base_pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
if (!priv->is_y_inverted)
|
||||
{
|
||||
template = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (template, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_s (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
cogl_pipeline_set_layer_wrap_mode_t (template, 1, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
CoglMatrix matrix;
|
||||
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
cogl_matrix_scale (&matrix, 1, -1, 1);
|
||||
cogl_matrix_translate (&matrix, 0, -1, 0);
|
||||
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||
}
|
||||
return template;
|
||||
|
||||
if (priv->snippet)
|
||||
cogl_pipeline_add_layer_snippet (pipeline, 0, priv->snippet);
|
||||
|
||||
priv->base_pipeline = pipeline;
|
||||
|
||||
return priv->base_pipeline;
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_unmasked_pipeline (CoglContext *ctx)
|
||||
get_unmasked_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
return get_base_pipeline (ctx);
|
||||
return get_base_pipeline (stex, ctx);
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_masked_pipeline (CoglContext *ctx)
|
||||
get_masked_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
static CoglPipeline *template = NULL;
|
||||
if (G_UNLIKELY (template == NULL))
|
||||
{
|
||||
template = cogl_pipeline_copy (get_base_pipeline (ctx));
|
||||
cogl_pipeline_set_layer_combine (template, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
}
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
return template;
|
||||
if (priv->masked_pipeline)
|
||||
return priv->masked_pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
|
||||
cogl_pipeline_set_layer_combine (pipeline, 1,
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
|
||||
priv->masked_pipeline = pipeline;
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
get_unblended_pipeline (CoglContext *ctx)
|
||||
get_unblended_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
static CoglPipeline *template = NULL;
|
||||
if (G_UNLIKELY (template == NULL))
|
||||
{
|
||||
CoglColor color;
|
||||
template = cogl_pipeline_copy (get_base_pipeline (ctx));
|
||||
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
|
||||
cogl_pipeline_set_blend (template,
|
||||
"RGBA = ADD (SRC_COLOR, 0)",
|
||||
NULL);
|
||||
cogl_pipeline_set_color (template, &color);
|
||||
}
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
CoglPipeline *pipeline;
|
||||
CoglColor color;
|
||||
|
||||
return template;
|
||||
if (priv->unblended_pipeline)
|
||||
return priv->unblended_pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
|
||||
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
|
||||
cogl_pipeline_set_blend (pipeline,
|
||||
"RGBA = ADD (SRC_COLOR, 0)",
|
||||
NULL);
|
||||
cogl_pipeline_set_color (pipeline, &color);
|
||||
|
||||
priv->unblended_pipeline = pipeline;
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -439,7 +494,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
|
||||
if (!cairo_region_is_empty (region))
|
||||
{
|
||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||
opaque_pipeline = get_unblended_pipeline (stex, ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
@ -471,11 +526,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
|
||||
if (priv->mask_texture == NULL)
|
||||
{
|
||||
blended_pipeline = get_unmasked_pipeline (ctx);
|
||||
blended_pipeline = get_unmasked_pipeline (stex, ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
blended_pipeline = get_masked_pipeline (ctx);
|
||||
blended_pipeline = get_masked_pipeline (stex, ctx);
|
||||
cogl_pipeline_set_layer_texture (blended_pipeline, 1, priv->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter);
|
||||
}
|
||||
@ -747,6 +802,42 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
set_cogl_texture (stex, texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_is_y_inverted: (skip)
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
|
||||
gboolean is_y_inverted)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->is_y_inverted == is_y_inverted)
|
||||
return;
|
||||
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
priv->is_y_inverted = is_y_inverted;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_snippet: (skip)
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
|
||||
CoglSnippet *snippet)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (priv->snippet == snippet)
|
||||
return;
|
||||
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
g_clear_pointer (&priv->snippet, cogl_object_unref);
|
||||
if (snippet)
|
||||
priv->snippet = cogl_object_ref (snippet);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_get_texture:
|
||||
* @stex: The #MetaShapedTexture
|
||||
|
@ -405,8 +405,10 @@ meta_surface_actor_wayland_dispose (GObject *object)
|
||||
MetaSurfaceActorWaylandPrivate *priv =
|
||||
meta_surface_actor_wayland_get_instance_private (self);
|
||||
MetaWaylandFrameCallback *cb, *next;
|
||||
MetaShapedTexture *stex =
|
||||
meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
|
||||
meta_surface_actor_wayland_set_texture (self, NULL);
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
if (priv->surface)
|
||||
{
|
||||
g_object_remove_weak_pointer (G_OBJECT (priv->surface),
|
||||
@ -472,14 +474,6 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
|
||||
return META_SURFACE_ACTOR (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
|
||||
CoglTexture *texture)
|
||||
{
|
||||
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
}
|
||||
|
||||
MetaWaylandSurface *
|
||||
meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
|
||||
{
|
||||
|
@ -62,9 +62,6 @@ MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
|
||||
MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self);
|
||||
void meta_surface_actor_wayland_surface_destroyed (MetaSurfaceActorWayland *self);
|
||||
|
||||
void meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
|
||||
CoglTexture *texture);
|
||||
|
||||
double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
|
||||
|
||||
void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
|
||||
|
@ -7,6 +7,7 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_srcdir)/cogl \
|
||||
-I$(top_builddir)/cogl \
|
||||
-I$(top_builddir)/cogl/cogl \
|
||||
-I$(top_srcdir)/clutter \
|
||||
-I$(top_builddir)/clutter \
|
||||
-I$(top_builddir)/clutter/clutter \
|
||||
|
@ -465,7 +465,12 @@ place_window_if_needed(MetaWindow *window,
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
placed_rect = (MetaRectangle) {
|
||||
.x = window->rect.x,
|
||||
.y = window->rect.y,
|
||||
.width = info->current.width,
|
||||
.height = info->current.height
|
||||
};
|
||||
|
||||
orig_rect = info->orig;
|
||||
|
||||
@ -779,10 +784,6 @@ constrain_custom_rule (MetaWindow *window,
|
||||
if (!placement_rule)
|
||||
return TRUE;
|
||||
|
||||
if (!meta_rectangle_could_fit_rect (&info->work_area_monitor,
|
||||
&info->current))
|
||||
return TRUE;
|
||||
|
||||
meta_rectangle_intersect (&info->current, &info->work_area_monitor,
|
||||
&intersection);
|
||||
|
||||
|
@ -44,8 +44,8 @@ dialog_exited (GPid pid, int status, gpointer user_data)
|
||||
|
||||
window->dialog_pid = -1;
|
||||
|
||||
/* exit status of 1 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
|
||||
/* exit status of 0 means the user pressed "Force Quit" */
|
||||
if (WIFEXITED (status) && WEXITSTATUS (status) == 0)
|
||||
meta_window_kill (window);
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ show_delete_dialog (MetaWindow *window,
|
||||
meta_show_dialog ("--question",
|
||||
window_content, NULL,
|
||||
window->screen->screen_name,
|
||||
_("_Wait"), _("_Force Quit"),
|
||||
_("_Force Quit"), _("_Wait"),
|
||||
"face-sad-symbolic", window->xwindow,
|
||||
NULL, NULL);
|
||||
|
||||
|
@ -2719,22 +2719,7 @@ prefs_changed_callback (MetaPreference pref,
|
||||
{
|
||||
MetaDisplay *display = data;
|
||||
|
||||
if (pref == META_PREF_FOCUS_MODE)
|
||||
{
|
||||
GSList *windows, *l;
|
||||
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
|
||||
|
||||
for (l = windows; l; l = l->next)
|
||||
{
|
||||
MetaWindow *w = l->data;
|
||||
meta_display_ungrab_focus_window_button (display, w);
|
||||
if (w->type != META_WINDOW_DOCK)
|
||||
meta_display_grab_focus_window_button (display, w);
|
||||
}
|
||||
|
||||
g_slist_free (windows);
|
||||
}
|
||||
else if (pref == META_PREF_AUDIBLE_BELL)
|
||||
if (pref == META_PREF_AUDIBLE_BELL)
|
||||
{
|
||||
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
|
||||
}
|
||||
@ -3110,13 +3095,14 @@ meta_display_request_pad_osd (MetaDisplay *display,
|
||||
WacomDevice *wacom_device;
|
||||
#endif
|
||||
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
/* Avoid emitting the signal while there is an OSD being currently
|
||||
* displayed, the first OSD will have to be dismissed before showing
|
||||
* any other one.
|
||||
*/
|
||||
if (display->current_pad_osd)
|
||||
{
|
||||
clutter_actor_destroy (display->current_pad_osd);
|
||||
display->current_pad_osd = NULL;
|
||||
}
|
||||
return;
|
||||
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
|
@ -217,6 +217,22 @@ meta_display_handle_event (MetaDisplay *display,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!display->current_pad_osd &&
|
||||
(event->type == CLUTTER_PAD_BUTTON_PRESS ||
|
||||
event->type == CLUTTER_PAD_BUTTON_RELEASE))
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
|
||||
if (meta_input_settings_handle_pad_button (meta_backend_get_input_settings (backend),
|
||||
clutter_event_get_source_device (event),
|
||||
event->type == CLUTTER_PAD_BUTTON_PRESS,
|
||||
event->pad_button.button))
|
||||
{
|
||||
bypass_wayland = bypass_clutter = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
source = clutter_event_get_source_device (event);
|
||||
|
||||
if (source)
|
||||
|
@ -894,6 +894,41 @@ on_keymap_changed (MetaBackend *backend,
|
||||
grab_key_bindings (display);
|
||||
}
|
||||
|
||||
static GArray *
|
||||
calc_grab_modifiers (MetaKeyBindingManager *keys,
|
||||
unsigned int modmask)
|
||||
{
|
||||
unsigned int ignored_mask;
|
||||
XIGrabModifiers mods;
|
||||
GArray *mods_array = g_array_new (FALSE, TRUE, sizeof (XIGrabModifiers));
|
||||
|
||||
/* The X server crashes if XIAnyModifier gets passed in with any
|
||||
other bits. It doesn't make sense to ask for a grab of
|
||||
XIAnyModifier plus other bits anyway so we avoid that. */
|
||||
if (modmask & XIAnyModifier)
|
||||
{
|
||||
mods = (XIGrabModifiers) { XIAnyModifier, 0 };
|
||||
g_array_append_val (mods_array, mods);
|
||||
return mods_array;
|
||||
}
|
||||
|
||||
mods = (XIGrabModifiers) { modmask, 0 };
|
||||
g_array_append_val (mods_array, mods);
|
||||
|
||||
for (ignored_mask = 1;
|
||||
ignored_mask <= keys->ignored_modifier_mask;
|
||||
++ignored_mask)
|
||||
{
|
||||
if (ignored_mask & keys->ignored_modifier_mask)
|
||||
{
|
||||
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
|
||||
g_array_append_val (mods_array, mods);
|
||||
}
|
||||
}
|
||||
|
||||
return mods_array;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_change_button_grab (MetaKeyBindingManager *keys,
|
||||
Window xwindow,
|
||||
@ -908,46 +943,30 @@ meta_change_button_grab (MetaKeyBindingManager *keys,
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
|
||||
unsigned int ignored_mask;
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
GArray *mods;
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
XISetMask (mask.mask, XI_Motion);
|
||||
|
||||
ignored_mask = 0;
|
||||
while (ignored_mask <= keys->ignored_modifier_mask)
|
||||
{
|
||||
XIGrabModifiers mods;
|
||||
mods = calc_grab_modifiers (keys, modmask);
|
||||
|
||||
if (ignored_mask & ~(keys->ignored_modifier_mask))
|
||||
{
|
||||
/* Not a combination of ignored modifiers
|
||||
* (it contains some non-ignored modifiers)
|
||||
*/
|
||||
++ignored_mask;
|
||||
continue;
|
||||
}
|
||||
/* GrabModeSync means freeze until XAllowEvents */
|
||||
if (grab)
|
||||
XIGrabButton (xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, None,
|
||||
sync ? XIGrabModeSync : XIGrabModeAsync,
|
||||
XIGrabModeAsync, False,
|
||||
&mask, mods->len, (XIGrabModifiers *)mods->data);
|
||||
else
|
||||
XIUngrabButton (xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, mods->len, (XIGrabModifiers *)mods->data);
|
||||
|
||||
mods = (XIGrabModifiers) { modmask | ignored_mask, 0 };
|
||||
|
||||
/* GrabModeSync means freeze until XAllowEvents */
|
||||
|
||||
if (grab)
|
||||
XIGrabButton (xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, None,
|
||||
sync ? XIGrabModeSync : XIGrabModeAsync,
|
||||
XIGrabModeAsync, False,
|
||||
&mask, 1, &mods);
|
||||
else
|
||||
XIUngrabButton (xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
button, xwindow, 1, &mods);
|
||||
|
||||
++ignored_mask;
|
||||
}
|
||||
g_array_free (mods, TRUE);
|
||||
}
|
||||
|
||||
ClutterModifierType
|
||||
@ -1032,7 +1051,6 @@ update_window_grab_modifiers (MetaKeyBindingManager *keys)
|
||||
keys->window_grab_modifiers = mods;
|
||||
}
|
||||
|
||||
/* Grab buttons we only grab while unfocused in click-to-focus mode */
|
||||
void
|
||||
meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
@ -1042,21 +1060,6 @@ meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
/* Grab button 1 for activating unfocused windows */
|
||||
meta_verbose ("Grabbing unfocused window buttons for %s\n", window->desc);
|
||||
|
||||
#if 0
|
||||
/* FIXME:115072 */
|
||||
/* Don't grab at all unless in click to focus mode. In click to
|
||||
* focus, we may sometimes be clever about intercepting and eating
|
||||
* the focus click. But in mouse focus, we never do that since the
|
||||
* focus window may not be raised, and who wants to think about
|
||||
* mouse focus anyway.
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode () != G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
{
|
||||
meta_verbose (" (well, not grabbing since not in click to focus mode)\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (window->have_focus_click_grab)
|
||||
{
|
||||
meta_verbose (" (well, not grabbing since we already have the grab)\n");
|
||||
@ -1068,7 +1071,7 @@ meta_display_grab_focus_window_button (MetaDisplay *display,
|
||||
* XSync()
|
||||
*/
|
||||
|
||||
meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, 0);
|
||||
meta_change_buttons_grab (keys, window->xwindow, TRUE, TRUE, XIAnyModifier);
|
||||
window->have_focus_click_grab = TRUE;
|
||||
}
|
||||
|
||||
@ -1083,7 +1086,7 @@ meta_display_ungrab_focus_window_button (MetaDisplay *display,
|
||||
if (!window->have_focus_click_grab)
|
||||
return;
|
||||
|
||||
meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, 0);
|
||||
meta_change_buttons_grab (keys, window->xwindow, FALSE, FALSE, XIAnyModifier);
|
||||
window->have_focus_click_grab = FALSE;
|
||||
}
|
||||
|
||||
@ -1149,8 +1152,6 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
|
||||
gboolean grab,
|
||||
MetaResolvedKeyCombo *resolved_combo)
|
||||
{
|
||||
unsigned int ignored_mask;
|
||||
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
|
||||
@ -1162,6 +1163,7 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
|
||||
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend);
|
||||
GArray *mods;
|
||||
|
||||
/* Grab keycode/modmask, together with
|
||||
* all combinations of ignored modifiers.
|
||||
@ -1173,35 +1175,21 @@ meta_change_keygrab (MetaKeyBindingManager *keys,
|
||||
grab ? "Grabbing" : "Ungrabbing",
|
||||
resolved_combo->keycode, resolved_combo->mask, xwindow);
|
||||
|
||||
ignored_mask = 0;
|
||||
while (ignored_mask <= keys->ignored_modifier_mask)
|
||||
{
|
||||
XIGrabModifiers mods;
|
||||
mods = calc_grab_modifiers (keys, resolved_combo->mask);
|
||||
|
||||
if (ignored_mask & ~(keys->ignored_modifier_mask))
|
||||
{
|
||||
/* Not a combination of ignored modifiers
|
||||
* (it contains some non-ignored modifiers)
|
||||
*/
|
||||
++ignored_mask;
|
||||
continue;
|
||||
}
|
||||
if (grab)
|
||||
XIGrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow,
|
||||
XIGrabModeSync, XIGrabModeAsync,
|
||||
False, &mask, mods->len, (XIGrabModifiers *)mods->data);
|
||||
else
|
||||
XIUngrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow,
|
||||
mods->len, (XIGrabModifiers *)mods->data);
|
||||
|
||||
mods = (XIGrabModifiers) { resolved_combo->mask | ignored_mask, 0 };
|
||||
|
||||
if (grab)
|
||||
XIGrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow,
|
||||
XIGrabModeSync, XIGrabModeAsync,
|
||||
False, &mask, 1, &mods);
|
||||
else
|
||||
XIUngrabKeycode (xdisplay,
|
||||
META_VIRTUAL_CORE_KEYBOARD_ID,
|
||||
resolved_combo->keycode, xwindow, 1, &mods);
|
||||
|
||||
++ignored_mask;
|
||||
}
|
||||
g_array_free (mods, TRUE);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -2888,7 +2888,15 @@ check_fullscreen_func (gpointer data)
|
||||
g_slist_free (fullscreen_monitors);
|
||||
|
||||
if (in_fullscreen_changed)
|
||||
g_signal_emit (screen, screen_signals[IN_FULLSCREEN_CHANGED], 0, NULL);
|
||||
{
|
||||
/* DOCK window stacking depends on the monitor's fullscreen
|
||||
status so we need to trigger a re-layering. */
|
||||
MetaWindow *window = meta_stack_get_top (screen->stack);
|
||||
if (window)
|
||||
meta_stack_update_layer (screen->stack, window);
|
||||
|
||||
g_signal_emit (screen, screen_signals[IN_FULLSCREEN_CHANGED], 0, NULL);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -286,8 +286,8 @@ get_standalone_layer (MetaWindow *window)
|
||||
break;
|
||||
|
||||
case META_WINDOW_DOCK:
|
||||
/* still experimenting here */
|
||||
if (window->wm_state_below)
|
||||
if (window->wm_state_below ||
|
||||
(window->monitor && window->monitor->in_fullscreen))
|
||||
layer = META_LAYER_BOTTOM;
|
||||
else
|
||||
layer = META_LAYER_DOCK;
|
||||
|
@ -78,7 +78,6 @@ typedef enum
|
||||
META_MOVE_RESIZE_RESIZE_ACTION = 1 << 3,
|
||||
META_MOVE_RESIZE_WAYLAND_RESIZE = 1 << 4,
|
||||
META_MOVE_RESIZE_STATE_CHANGED = 1 << 5,
|
||||
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR = 1 << 6,
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
|
@ -2267,27 +2267,7 @@ meta_window_show (MetaWindow *window)
|
||||
( (!place_on_top_on_map && !takes_focus_on_map) ||
|
||||
window_would_be_covered (window) )
|
||||
) {
|
||||
if (meta_window_is_ancestor_of_transient (focus_window, window))
|
||||
{
|
||||
guint32 timestamp;
|
||||
|
||||
timestamp = meta_display_get_current_time_roundtrip (window->display);
|
||||
|
||||
/* This happens for error dialogs or alerts; these need to remain on
|
||||
* top, but it would be confusing to have its ancestor remain
|
||||
* focused.
|
||||
*/
|
||||
meta_topic (META_DEBUG_STARTUP,
|
||||
"The focus window %s is an ancestor of the newly mapped "
|
||||
"window %s which isn't being focused. Unfocusing the "
|
||||
"ancestor.\n",
|
||||
focus_window->desc, window->desc);
|
||||
|
||||
meta_display_focus_the_no_focus_window (window->display,
|
||||
window->screen,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
if (!meta_window_is_ancestor_of_transient (focus_window, window))
|
||||
{
|
||||
needs_stacking_adjustment = TRUE;
|
||||
if (!window->placed)
|
||||
@ -2761,23 +2741,21 @@ meta_window_maximize (MetaWindow *window,
|
||||
directions,
|
||||
saved_rect);
|
||||
|
||||
MetaRectangle old_frame_rect, old_buffer_rect, new_rect;
|
||||
MetaRectangle old_frame_rect, old_buffer_rect;
|
||||
|
||||
meta_window_get_frame_rect (window, &old_frame_rect);
|
||||
meta_window_get_buffer_rect (window, &old_buffer_rect);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED |
|
||||
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
|
||||
NorthWestGravity,
|
||||
window->unconstrained_rect);
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
|
||||
meta_compositor_size_change_window (window->display->compositor, window,
|
||||
META_SIZE_CHANGE_MAXIMIZE,
|
||||
&old_frame_rect, &old_buffer_rect);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED),
|
||||
NorthWestGravity,
|
||||
window->unconstrained_rect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3024,7 +3002,6 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
MetaMaximizeFlags directions)
|
||||
{
|
||||
gboolean unmaximize_horizontally, unmaximize_vertically;
|
||||
MetaRectangle new_rect;
|
||||
|
||||
g_return_if_fail (!window->override_redirect);
|
||||
|
||||
@ -3115,30 +3092,26 @@ meta_window_unmaximize (MetaWindow *window,
|
||||
ensure_size_hints_satisfied (&target_rect, &window->size_hints);
|
||||
meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED |
|
||||
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
|
||||
NorthWestGravity,
|
||||
target_rect);
|
||||
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
meta_compositor_size_change_window (window->display->compositor, window,
|
||||
META_SIZE_CHANGE_UNMAXIMIZE,
|
||||
&old_frame_rect, &old_buffer_rect);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED),
|
||||
NorthWestGravity,
|
||||
target_rect);
|
||||
|
||||
/* When we unmaximize, if we're doing a mouse move also we could
|
||||
* get the window suddenly jumping to the upper left corner of
|
||||
* the workspace, since that's where it was when the grab op
|
||||
* started. So we need to update the grab state. We have to do
|
||||
* it after the actual operation, as the window may have been moved
|
||||
* by constraints.
|
||||
* started. So we need to update the grab anchor position.
|
||||
*/
|
||||
if (meta_grab_op_is_moving (window->display->grab_op) &&
|
||||
window->display->grab_window == window)
|
||||
{
|
||||
window->display->grab_anchor_window_pos = window->unconstrained_rect;
|
||||
window->display->grab_anchor_window_pos = target_rect;
|
||||
}
|
||||
|
||||
meta_window_recalc_features (window);
|
||||
@ -3235,18 +3208,17 @@ meta_window_make_fullscreen (MetaWindow *window)
|
||||
meta_window_get_frame_rect (window, &old_frame_rect);
|
||||
meta_window_get_buffer_rect (window, &old_buffer_rect);
|
||||
|
||||
meta_compositor_size_change_window (window->display->compositor,
|
||||
window, META_SIZE_CHANGE_FULLSCREEN,
|
||||
&old_frame_rect, &old_buffer_rect);
|
||||
|
||||
meta_window_make_fullscreen_internal (window);
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED |
|
||||
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
|
||||
META_MOVE_RESIZE_STATE_CHANGED),
|
||||
NorthWestGravity,
|
||||
window->unconstrained_rect);
|
||||
|
||||
meta_compositor_size_change_window (window->display->compositor,
|
||||
window, META_SIZE_CHANGE_FULLSCREEN,
|
||||
&old_frame_rect, &old_buffer_rect);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3281,18 +3253,17 @@ meta_window_unmake_fullscreen (MetaWindow *window)
|
||||
meta_window_recalc_features (window);
|
||||
set_net_wm_state (window);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED |
|
||||
META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR),
|
||||
NorthWestGravity,
|
||||
target_rect);
|
||||
|
||||
meta_compositor_size_change_window (window->display->compositor,
|
||||
window, META_SIZE_CHANGE_UNFULLSCREEN,
|
||||
&old_frame_rect, &old_buffer_rect);
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
(META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION |
|
||||
META_MOVE_RESIZE_STATE_CHANGED),
|
||||
NorthWestGravity,
|
||||
target_rect);
|
||||
|
||||
meta_screen_queue_check_fullscreen (window->screen);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (window), obj_props[PROP_FULLSCREEN]);
|
||||
@ -3751,7 +3722,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
{
|
||||
window->unconstrained_rect = unconstrained_rect;
|
||||
|
||||
if (window->known_to_compositor && !(flags & META_MOVE_RESIZE_DONT_SYNC_COMPOSITOR))
|
||||
if (window->known_to_compositor)
|
||||
meta_compositor_sync_window_geometry (window->display->compositor,
|
||||
window,
|
||||
did_placement);
|
||||
@ -4845,7 +4816,12 @@ meta_window_set_focused_internal (MetaWindow *window,
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
|
||||
!meta_prefs_get_raise_on_click())
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
{
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
/* Since we ungrab with XIAnyModifier above, all button
|
||||
grabs go way so we need to re-grab the window buttons. */
|
||||
meta_display_grab_window_buttons (window->display, window->xwindow);
|
||||
}
|
||||
|
||||
g_signal_emit (window, window_signals[FOCUS], 0);
|
||||
|
||||
|
@ -102,6 +102,9 @@ struct _MetaPluginClass
|
||||
void (*unminimize) (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
void (*size_changed) (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor);
|
||||
|
||||
void (*size_change) (MetaPlugin *plugin,
|
||||
MetaWindowActor *actor,
|
||||
MetaSizeChange which_change,
|
||||
|
@ -27,9 +27,11 @@
|
||||
#include "meta-wayland-buffer.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
#include <cogl/cogl-wayland-server.h>
|
||||
#include <cogl/cogl-egl.h>
|
||||
#include <meta/util.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
|
||||
enum
|
||||
{
|
||||
RESOURCE_DESTROYED,
|
||||
@ -79,79 +81,364 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer)
|
||||
typedef enum _MetaWaylandBufferType
|
||||
{
|
||||
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
CoglError *catch_error = NULL;
|
||||
CoglTexture *texture;
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
META_WAYLAND_BUFFER_TYPE_UNKNOWN,
|
||||
META_WAYLAND_BUFFER_TYPE_SHM,
|
||||
META_WAYLAND_BUFFER_TYPE_EGL_IMAGE,
|
||||
META_WAYLAND_BUFFER_TYPE_EGL_STREAM,
|
||||
} MetaWaylandBufferType;
|
||||
|
||||
g_return_val_if_fail (buffer->resource, NULL);
|
||||
static MetaWaylandBufferType
|
||||
determine_buffer_type (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
EGLint format;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
|
||||
if (buffer->texture)
|
||||
goto out;
|
||||
if (wl_shm_buffer_get (buffer->resource) != NULL)
|
||||
return META_WAYLAND_BUFFER_TYPE_SHM;
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
|
||||
if (shm_buffer)
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
if (meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_TEXTURE_FORMAT, &format,
|
||||
NULL))
|
||||
return META_WAYLAND_BUFFER_TYPE_EGL_IMAGE;
|
||||
|
||||
texture = COGL_TEXTURE (cogl_wayland_texture_2d_new_from_buffer (ctx,
|
||||
buffer->resource,
|
||||
&catch_error));
|
||||
if (meta_wayland_is_egl_stream_buffer (buffer))
|
||||
return META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
|
||||
|
||||
if (shm_buffer)
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
return META_WAYLAND_BUFFER_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!texture)
|
||||
static void
|
||||
shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
|
||||
CoglPixelFormat *format_out,
|
||||
CoglTextureComponents *components_out)
|
||||
{
|
||||
CoglPixelFormat format;
|
||||
CoglTextureComponents components = COGL_TEXTURE_COMPONENTS_RGBA;
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
meta_warning ("Could not import pending buffer, ignoring commit: %s\n",
|
||||
catch_error->message);
|
||||
cogl_error_free (catch_error);
|
||||
goto out;
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
format = COGL_PIXEL_FORMAT_BGRA_8888;
|
||||
components = COGL_TEXTURE_COMPONENTS_RGB;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
format = COGL_PIXEL_FORMAT_ARGB_8888;
|
||||
}
|
||||
|
||||
buffer->texture = texture;
|
||||
if (format_out)
|
||||
*format_out = format;
|
||||
if (components_out)
|
||||
*components_out = components;
|
||||
}
|
||||
|
||||
out:
|
||||
static gboolean
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int stride, width, height;
|
||||
CoglPixelFormat format;
|
||||
CoglTextureComponents components;
|
||||
CoglBitmap *bitmap;
|
||||
CoglTexture *texture;
|
||||
|
||||
if (buffer->texture)
|
||||
return TRUE;
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
width = wl_shm_buffer_get_width (shm_buffer);
|
||||
height = wl_shm_buffer_get_height (shm_buffer);
|
||||
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components);
|
||||
|
||||
bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||
width, height,
|
||||
format,
|
||||
stride,
|
||||
wl_shm_buffer_get_data (shm_buffer));
|
||||
|
||||
texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap));
|
||||
cogl_texture_set_components (COGL_TEXTURE (texture), components);
|
||||
|
||||
cogl_object_unref (bitmap);
|
||||
|
||||
if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
|
||||
g_clear_pointer (&texture, cogl_object_unref);
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
|
||||
buffer->texture = texture;
|
||||
buffer->is_y_inverted = TRUE;
|
||||
|
||||
if (!buffer->texture)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
EGLContext egl_context = cogl_egl_context_get_egl_context (cogl_context);
|
||||
int format, width, height, y_inverted;
|
||||
CoglPixelFormat cogl_format;
|
||||
EGLImageKHR egl_image;
|
||||
CoglTexture2D *texture;
|
||||
|
||||
if (buffer->texture)
|
||||
return TRUE;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_TEXTURE_FORMAT, &format,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_WIDTH, &width,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_HEIGHT, &height,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_WAYLAND_Y_INVERTED_WL, &y_inverted,
|
||||
NULL))
|
||||
y_inverted = EGL_TRUE;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case EGL_TEXTURE_RGB:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
break;
|
||||
case EGL_TEXTURE_RGBA:
|
||||
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
|
||||
break;
|
||||
default:
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unsupported buffer format %d", format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
egl_image = meta_egl_create_image (egl, egl_display, egl_context,
|
||||
EGL_WAYLAND_BUFFER_WL, buffer->resource,
|
||||
NULL,
|
||||
error);
|
||||
if (egl_image == EGL_NO_IMAGE_KHR)
|
||||
return FALSE;
|
||||
|
||||
texture = cogl_egl_texture_2d_new_from_image (cogl_context,
|
||||
width, height,
|
||||
cogl_format,
|
||||
egl_image,
|
||||
error);
|
||||
|
||||
meta_egl_destroy_image (egl, egl_display, egl_image, NULL);
|
||||
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
|
||||
buffer->texture = COGL_TEXTURE (texture);
|
||||
buffer->is_y_inverted = !!y_inverted;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandEglStream *stream;
|
||||
|
||||
stream = buffer->egl_stream.stream;
|
||||
if (!stream)
|
||||
stream = meta_wayland_egl_stream_new (buffer, error);
|
||||
|
||||
if (!stream)
|
||||
return FALSE;
|
||||
|
||||
buffer->egl_stream.stream = stream;
|
||||
|
||||
if (!buffer->texture)
|
||||
{
|
||||
CoglTexture2D *texture;
|
||||
|
||||
texture = meta_wayland_egl_stream_create_texture (stream, error);
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
|
||||
buffer->texture = COGL_TEXTURE (texture);
|
||||
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
|
||||
}
|
||||
|
||||
if (!meta_wayland_egl_stream_attach (stream, error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandBufferType buffer_type;
|
||||
|
||||
g_return_val_if_fail (buffer->resource, FALSE);
|
||||
|
||||
buffer_type = determine_buffer_type (buffer);
|
||||
|
||||
switch (buffer_type)
|
||||
{
|
||||
case META_WAYLAND_BUFFER_TYPE_SHM:
|
||||
return shm_buffer_attach (buffer, error);
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
|
||||
return egl_image_buffer_attach (buffer, error);
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
|
||||
return egl_stream_buffer_attach (buffer, error);
|
||||
break;
|
||||
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unknown buffer type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
CoglTexture *
|
||||
meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
return buffer->texture;
|
||||
}
|
||||
|
||||
CoglSnippet *
|
||||
meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
if (!buffer->egl_stream.stream)
|
||||
return NULL;
|
||||
|
||||
return meta_wayland_egl_stream_create_snippet ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
return buffer->is_y_inverted;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_shm_buffer_damage (MetaWaylandBuffer *buffer,
|
||||
cairo_region_t *region,
|
||||
GError **error)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
int i, n_rectangles;
|
||||
gboolean set_texture_failed = FALSE;
|
||||
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
{
|
||||
const uint8_t *data = wl_shm_buffer_get_data (shm_buffer);
|
||||
int32_t stride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
CoglPixelFormat format;
|
||||
int bpp;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL);
|
||||
bpp = _cogl_pixel_format_get_bytes_per_pixel (format);
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
if (!_cogl_texture_set_region (buffer->texture,
|
||||
rect.width, rect.height,
|
||||
format,
|
||||
stride,
|
||||
data + rect.x * bpp + rect.y * stride,
|
||||
rect.x, rect.y,
|
||||
0,
|
||||
error))
|
||||
{
|
||||
set_texture_failed = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
|
||||
return !set_texture_failed;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
struct wl_shm_buffer *shm_buffer;
|
||||
MetaWaylandBufferType buffer_type;
|
||||
gboolean res = FALSE;
|
||||
GError *error = NULL;
|
||||
|
||||
shm_buffer = wl_shm_buffer_get (buffer->resource);
|
||||
g_return_if_fail (buffer->resource);
|
||||
|
||||
if (shm_buffer)
|
||||
buffer_type = determine_buffer_type (buffer);
|
||||
|
||||
switch (buffer_type)
|
||||
{
|
||||
int i, n_rectangles;
|
||||
case META_WAYLAND_BUFFER_TYPE_SHM:
|
||||
res = process_shm_buffer_damage (buffer, region, &error);
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
|
||||
res = TRUE;
|
||||
break;
|
||||
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
|
||||
g_set_error (&error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unknown buffer type");
|
||||
res = FALSE;
|
||||
}
|
||||
|
||||
n_rectangles = cairo_region_num_rectangles (region);
|
||||
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
|
||||
for (i = 0; i < n_rectangles; i++)
|
||||
{
|
||||
CoglError *error = NULL;
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
cogl_wayland_texture_set_region_from_shm_buffer (buffer->texture,
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
shm_buffer,
|
||||
rect.x, rect.y, 0, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
meta_warning ("Failed to set texture region: %s\n", error->message);
|
||||
cogl_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
if (!res)
|
||||
{
|
||||
g_warning ("Failed to process Wayland buffer damage: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +448,7 @@ meta_wayland_buffer_finalize (GObject *object)
|
||||
MetaWaylandBuffer *buffer = META_WAYLAND_BUFFER (object);
|
||||
|
||||
g_clear_pointer (&buffer->texture, cogl_object_unref);
|
||||
g_clear_object (&buffer->egl_stream.stream);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_buffer_parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "meta-wayland-types.h"
|
||||
#include "meta-wayland-egl-stream.h"
|
||||
|
||||
struct _MetaWaylandBuffer
|
||||
{
|
||||
@ -39,6 +40,11 @@ struct _MetaWaylandBuffer
|
||||
struct wl_listener destroy_listener;
|
||||
|
||||
CoglTexture *texture;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
struct {
|
||||
MetaWaylandEglStream *stream;
|
||||
} egl_stream;
|
||||
};
|
||||
|
||||
#define META_TYPE_WAYLAND_BUFFER (meta_wayland_buffer_get_type ())
|
||||
@ -46,7 +52,11 @@ G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer,
|
||||
META, WAYLAND_BUFFER, GObject);
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
CoglTexture * meta_wayland_buffer_ensure_texture (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error);
|
||||
CoglTexture * meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer);
|
||||
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
|
||||
void meta_wayland_buffer_process_damage (MetaWaylandBuffer *buffer,
|
||||
cairo_region_t *region);
|
||||
|
||||
|
@ -89,7 +89,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
|
||||
@ -1195,9 +1195,12 @@ data_device_start_drag (struct wl_client *client,
|
||||
&drag_grab_interface,
|
||||
surface, drag_source, icon_surface);
|
||||
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, NULL);
|
||||
meta_wayland_keyboard_start_grab (seat->keyboard,
|
||||
&seat->data_device.current_grab->keyboard_grab);
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, NULL);
|
||||
meta_wayland_keyboard_start_grab (seat->keyboard,
|
||||
&seat->data_device.current_grab->keyboard_grab);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
279
src/wayland/meta-wayland-egl-stream.c
Normal file
279
src/wayland/meta-wayland-egl-stream.c
Normal file
@ -0,0 +1,279 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat Inc.
|
||||
*
|
||||
* 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 "wayland/meta-wayland-egl-stream.h"
|
||||
|
||||
#include "cogl/cogl-egl.h"
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-egl.h"
|
||||
#include "meta/meta-backend.h"
|
||||
#include "wayland/meta-wayland-buffer.h"
|
||||
|
||||
struct _MetaWaylandEglStream
|
||||
{
|
||||
GObject parent;
|
||||
|
||||
EGLStreamKHR egl_stream;
|
||||
MetaWaylandBuffer *buffer;
|
||||
CoglTexture2D *texture;
|
||||
gboolean is_y_inverted;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream,
|
||||
G_TYPE_OBJECT)
|
||||
|
||||
MetaWaylandEglStream *
|
||||
meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
g_autoptr (MetaWaylandEglStream) stream = NULL;
|
||||
int stream_fd;
|
||||
EGLStreamKHR egl_stream;
|
||||
|
||||
stream = g_object_new (META_TYPE_WAYLAND_EGL_STREAM, NULL);
|
||||
|
||||
/*
|
||||
* HACK: Use a (as far as I can tell) undocumented hack by passing
|
||||
* EGL_WAYLAND_BUFFER_WL to eglQueryWaylandBufferWL. If it happens to be a
|
||||
* dummy EGLStream buffer, we'll get a EGLStream file descriptor.
|
||||
*
|
||||
* FIXME: At some point, replace this with the EGL_WL_wayland_eglstream
|
||||
* extension.
|
||||
*/
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_WAYLAND_BUFFER_WL, &stream_fd,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if (stream_fd == EGL_NO_FILE_DESCRIPTOR_KHR)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Stream already used with other wl_buffer");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
egl_stream = meta_egl_create_stream_from_file_descriptor (egl, egl_display, stream_fd,
|
||||
error);
|
||||
close (stream_fd);
|
||||
if (egl_stream == EGL_NO_STREAM_KHR)
|
||||
return NULL;
|
||||
|
||||
stream->egl_stream = egl_stream;
|
||||
stream->buffer = buffer;
|
||||
|
||||
return g_steal_pointer (&stream);
|
||||
}
|
||||
|
||||
static void
|
||||
stream_texture_destroyed (gpointer data)
|
||||
{
|
||||
MetaWaylandEglStream *stream = data;
|
||||
|
||||
stream->texture = NULL;
|
||||
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
alloc_egl_stream_texture (CoglTexture2D *texture,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
MetaWaylandEglStream *stream = user_data;
|
||||
|
||||
return meta_egl_stream_consumer_gl_texture_external (egl, egl_display,
|
||||
stream->egl_stream,
|
||||
error);
|
||||
}
|
||||
|
||||
CoglTexture2D *
|
||||
meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
CoglTexture2D *texture;
|
||||
int width, height;
|
||||
int y_inverted;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display,
|
||||
stream->buffer->resource,
|
||||
EGL_WIDTH, &width,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display,
|
||||
stream->buffer->resource,
|
||||
EGL_HEIGHT, &height,
|
||||
error))
|
||||
return NULL;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display,
|
||||
stream->buffer->resource,
|
||||
EGL_WAYLAND_Y_INVERTED_WL, &y_inverted,
|
||||
NULL))
|
||||
y_inverted = EGL_TRUE;
|
||||
|
||||
texture =
|
||||
cogl_texture_2d_new_from_egl_image_external (cogl_context,
|
||||
width, height,
|
||||
alloc_egl_stream_texture,
|
||||
g_object_ref (stream),
|
||||
stream_texture_destroyed,
|
||||
error);
|
||||
if (!texture)
|
||||
{
|
||||
g_object_unref (stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
|
||||
{
|
||||
cogl_object_unref (texture);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
stream->texture = texture;
|
||||
stream->is_y_inverted = !!y_inverted;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
EGLint stream_state;
|
||||
|
||||
if (!meta_egl_query_stream (egl, egl_display, stream->egl_stream,
|
||||
EGL_STREAM_STATE_KHR, &stream_state,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR)
|
||||
{
|
||||
if (!meta_egl_stream_consumer_acquire (egl, egl_display,
|
||||
stream->egl_stream,
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream)
|
||||
{
|
||||
return stream->is_y_inverted;
|
||||
}
|
||||
|
||||
CoglSnippet *
|
||||
meta_wayland_egl_stream_create_snippet (void)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
"uniform samplerExternalOES tex_external;",
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet,
|
||||
"cogl_texel = texture2D (tex_external,\n"
|
||||
" cogl_tex_coord.xy);");
|
||||
|
||||
return snippet;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_is_egl_stream_buffer (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
int stream_fd;
|
||||
|
||||
if (!meta_egl_has_extensions (egl, egl_display, NULL,
|
||||
"EGL_KHR_stream_consumer_gltexture",
|
||||
"EGL_KHR_stream_cross_process_fd",
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
|
||||
EGL_WAYLAND_BUFFER_WL, &stream_fd,
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_egl_stream_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandEglStream *stream = META_WAYLAND_EGL_STREAM (object);
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||
EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
|
||||
|
||||
g_assert (!stream->texture);
|
||||
|
||||
meta_egl_destroy_stream (egl, egl_display, stream->egl_stream, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_egl_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_egl_stream_init (MetaWaylandEglStream *stream)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_egl_stream_class_init (MetaWaylandEglStreamClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_egl_stream_finalize;
|
||||
}
|
52
src/wayland/meta-wayland-egl-stream.h
Normal file
52
src/wayland/meta-wayland-egl-stream.h
Normal file
@ -0,0 +1,52 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 Red Hat Inc.
|
||||
*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_EGL_STREAM_H
|
||||
#define META_WAYLAND_EGL_STREAM_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "cogl/cogl.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_EGL_STREAM (meta_wayland_egl_stream_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream,
|
||||
META, WAYLAND_EGL_STREAM, GObject);
|
||||
|
||||
gboolean meta_wayland_is_egl_stream_buffer (MetaWaylandBuffer *buffer);
|
||||
|
||||
MetaWaylandEglStream * meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
|
||||
GError **error);
|
||||
|
||||
CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_egl_stream_create_snippet (void);
|
||||
|
||||
gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream);
|
||||
|
||||
#endif /* META_WAYLAND_EGL_STREAM_H */
|
@ -26,6 +26,10 @@
|
||||
|
||||
#include "wayland/meta-wayland-input-device.h"
|
||||
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
@ -51,6 +55,14 @@ meta_wayland_input_device_get_seat (MetaWaylandInputDevice *input_device)
|
||||
return priv->seat;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
meta_wayland_input_device_next_serial (MetaWaylandInputDevice *input_device)
|
||||
{
|
||||
MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device);
|
||||
|
||||
return wl_display_next_serial (seat->wl_display);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_input_device_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define META_WAYLAND_INPUT_DEVICE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
@ -42,4 +43,6 @@ struct _MetaWaylandInputDeviceClass
|
||||
|
||||
MetaWaylandSeat * meta_wayland_input_device_get_seat (MetaWaylandInputDevice *input_device);
|
||||
|
||||
uint32_t meta_wayland_input_device_next_serial (MetaWaylandInputDevice *input_device);
|
||||
|
||||
#endif /* META_WAYLAND_INPUT_DEVICE_H */
|
||||
|
@ -252,7 +252,8 @@ on_keymap_layout_group_changed (MetaBackend *backend,
|
||||
static void
|
||||
keyboard_handle_focus_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard, focus_surface_listener);
|
||||
MetaWaylandKeyboard *keyboard = wl_container_of (listener, keyboard,
|
||||
focus_surface_listener);
|
||||
|
||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||
}
|
||||
@ -264,17 +265,16 @@ meta_wayland_keyboard_broadcast_key (MetaWaylandKeyboard *keyboard,
|
||||
uint32_t state)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
l = &keyboard->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&keyboard->focus_resource_list))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
MetaWaylandInputDevice *input_device =
|
||||
META_WAYLAND_INPUT_DEVICE (keyboard);
|
||||
|
||||
keyboard->key_serial = wl_display_next_serial (display);
|
||||
keyboard->key_serial =
|
||||
meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, &keyboard->focus_resource_list)
|
||||
{
|
||||
wl_keyboard_send_key (resource, keyboard->key_serial, time, key, state);
|
||||
}
|
||||
@ -349,19 +349,16 @@ static void
|
||||
meta_wayland_keyboard_broadcast_modifiers (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
l = &keyboard->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&keyboard->focus_resource_list))
|
||||
{
|
||||
MetaWaylandInputDevice *input_device =
|
||||
META_WAYLAND_INPUT_DEVICE (keyboard);
|
||||
MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device);
|
||||
uint32_t serial;
|
||||
|
||||
serial = wl_display_next_serial (seat->wl_display);
|
||||
serial = meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
wl_resource_for_each (resource, &keyboard->focus_resource_list)
|
||||
keyboard_send_modifiers (keyboard, resource, serial);
|
||||
}
|
||||
}
|
||||
@ -611,17 +608,6 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
GSettingsSchema *schema;
|
||||
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->focus_resource_list);
|
||||
|
||||
keyboard->focus_surface_listener.notify = keyboard_handle_focus_surface_destroy;
|
||||
|
||||
keyboard->xkb_info.keymap_fd = -1;
|
||||
|
||||
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
|
||||
keyboard->settings = g_settings_new ("org.gnome.desktop.peripherals.keyboard");
|
||||
g_signal_connect (keyboard->settings, "changed",
|
||||
G_CALLBACK (settings_changed), keyboard);
|
||||
@ -647,6 +633,12 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
|
||||
maybe_restore_numlock_state (keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xkb_info_init (MetaWaylandXkbInfo *xkb_info)
|
||||
{
|
||||
xkb_info->keymap_fd = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
{
|
||||
@ -659,7 +651,10 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
xkb_info->keymap_area = NULL;
|
||||
}
|
||||
if (xkb_info->keymap_fd >= 0)
|
||||
close (xkb_info->keymap_fd);
|
||||
{
|
||||
close (xkb_info->keymap_fd);
|
||||
xkb_info->keymap_fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -670,10 +665,14 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
|
||||
g_signal_handlers_disconnect_by_func (backend, on_keymap_changed, keyboard);
|
||||
g_signal_handlers_disconnect_by_func (backend, on_keymap_layout_group_changed, keyboard);
|
||||
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
|
||||
/* XXX: What about keyboard->resource_list? */
|
||||
wl_list_remove (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_list_remove (&keyboard->focus_resource_list);
|
||||
wl_list_init (&keyboard->focus_resource_list);
|
||||
|
||||
g_clear_object (&keyboard->settings);
|
||||
if (keyboard->gsd_settings)
|
||||
@ -826,32 +825,27 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (keyboard);
|
||||
MetaWaylandSeat *seat = meta_wayland_input_device_get_seat (input_device);
|
||||
|
||||
if (!meta_wayland_seat_has_keyboard (seat))
|
||||
return;
|
||||
|
||||
if (keyboard->focus_surface == surface)
|
||||
return;
|
||||
|
||||
if (keyboard->focus_surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
|
||||
l = &keyboard->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&keyboard->focus_resource_list))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial = wl_display_next_serial (display);
|
||||
struct wl_resource *resource;
|
||||
uint32_t serial;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
serial = meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
wl_resource_for_each (resource, &keyboard->focus_resource_list)
|
||||
{
|
||||
wl_keyboard_send_leave (resource, serial, keyboard->focus_surface->resource);
|
||||
wl_keyboard_send_leave (resource, serial,
|
||||
keyboard->focus_surface->resource);
|
||||
}
|
||||
|
||||
move_resources (&keyboard->resource_list, &keyboard->focus_resource_list);
|
||||
move_resources (&keyboard->resource_list,
|
||||
&keyboard->focus_resource_list);
|
||||
}
|
||||
|
||||
wl_list_remove (&keyboard->focus_surface_listener.link);
|
||||
@ -860,24 +854,25 @@ meta_wayland_keyboard_set_focus (MetaWaylandKeyboard *keyboard,
|
||||
|
||||
if (surface != NULL)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
struct wl_list *l;
|
||||
struct wl_resource *focus_surface_resource;
|
||||
|
||||
keyboard->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (keyboard->focus_surface->resource, &keyboard->focus_surface_listener);
|
||||
focus_surface_resource = keyboard->focus_surface->resource;
|
||||
wl_resource_add_destroy_listener (focus_surface_resource,
|
||||
&keyboard->focus_surface_listener);
|
||||
|
||||
move_resources_for_client (&keyboard->focus_resource_list,
|
||||
&keyboard->resource_list,
|
||||
wl_resource_get_client (keyboard->focus_surface->resource));
|
||||
wl_resource_get_client (focus_surface_resource));
|
||||
|
||||
l = &keyboard->focus_resource_list;
|
||||
if (!wl_list_empty (l))
|
||||
if (!wl_list_empty (&keyboard->focus_resource_list))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (keyboard->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
keyboard->focus_serial = wl_display_next_serial (display);
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each (resource, l)
|
||||
keyboard->focus_serial =
|
||||
meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
wl_resource_for_each (resource, &keyboard->focus_resource_list)
|
||||
{
|
||||
broadcast_focus (keyboard, resource);
|
||||
}
|
||||
@ -911,26 +906,31 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *cr;
|
||||
struct wl_resource *resource;
|
||||
|
||||
cr = wl_resource_create (client, &wl_keyboard_interface, wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (cr, &keyboard_interface, keyboard, unbind_resource);
|
||||
resource = wl_resource_create (client, &wl_keyboard_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &keyboard_interface,
|
||||
keyboard, unbind_resource);
|
||||
|
||||
wl_keyboard_send_keymap (cr,
|
||||
wl_keyboard_send_keymap (resource,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
keyboard->xkb_info.keymap_fd,
|
||||
keyboard->xkb_info.keymap_size);
|
||||
|
||||
notify_key_repeat_for_resource (keyboard, cr);
|
||||
notify_key_repeat_for_resource (keyboard, resource);
|
||||
|
||||
if (keyboard->focus_surface && wl_resource_get_client (keyboard->focus_surface->resource) == client)
|
||||
if (keyboard->focus_surface &&
|
||||
wl_resource_get_client (keyboard->focus_surface->resource) == client)
|
||||
{
|
||||
wl_list_insert (&keyboard->focus_resource_list, wl_resource_get_link (cr));
|
||||
broadcast_focus (keyboard, cr);
|
||||
wl_list_insert (&keyboard->focus_resource_list,
|
||||
wl_resource_get_link (resource));
|
||||
broadcast_focus (keyboard, resource);
|
||||
}
|
||||
else
|
||||
{
|
||||
wl_list_insert (&keyboard->resource_list, wl_resource_get_link (cr));
|
||||
wl_list_insert (&keyboard->resource_list,
|
||||
wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
|
||||
@ -959,6 +959,17 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
|
||||
static void
|
||||
meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->focus_resource_list);
|
||||
|
||||
meta_wayland_xkb_info_init (&keyboard->xkb_info);
|
||||
|
||||
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
|
||||
keyboard->focus_surface_listener.notify =
|
||||
keyboard_handle_focus_surface_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/native/meta-backend-native.h"
|
||||
#include "backends/meta-pointer-constraint.h"
|
||||
#include "core/frame.h"
|
||||
|
||||
#include "pointer-constraints-unstable-v1-server-protocol.h"
|
||||
|
||||
@ -447,17 +448,10 @@ is_within_constraint_region (MetaWaylandPointerConstraint *constraint,
|
||||
return is_within;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint)
|
||||
static gboolean
|
||||
should_constraint_be_enabled (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
MetaWindow *window;
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
if (constraint->is_enabled)
|
||||
return;
|
||||
|
||||
if (constraint->seat->pointer->focus_surface != constraint->surface)
|
||||
return;
|
||||
|
||||
window = constraint->surface->window;
|
||||
if (!window)
|
||||
@ -467,11 +461,14 @@ meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *cons
|
||||
* associate the X11 Window with the wl_surface.
|
||||
*/
|
||||
g_warn_if_fail (meta_xwayland_is_xwayland_surface (constraint->surface));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (window->unmanaging)
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
if (constraint->seat->pointer->focus_surface != constraint->surface)
|
||||
return FALSE;
|
||||
|
||||
if (meta_xwayland_is_xwayland_surface (constraint->surface))
|
||||
{
|
||||
@ -493,14 +490,30 @@ meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *cons
|
||||
|
||||
if (display->focus_window &&
|
||||
display->focus_window->client_type != META_WINDOW_CLIENT_TYPE_X11)
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaWindow *window = constraint->surface->window;
|
||||
|
||||
if (!meta_window_appears_focused (window))
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_constraint_maybe_enable (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
wl_fixed_t sx, sy;
|
||||
|
||||
if (constraint->is_enabled)
|
||||
return;
|
||||
|
||||
if (!should_constraint_be_enabled (constraint))
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (constraint->seat->pointer,
|
||||
constraint->surface,
|
||||
&sx, &sy);
|
||||
@ -519,26 +532,9 @@ meta_wayland_pointer_constraint_remove (MetaWaylandPointerConstraint *constraint
|
||||
meta_wayland_pointer_constraint_destroy (constraint);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat,
|
||||
MetaWindow *window)
|
||||
static void
|
||||
meta_wayland_pointer_constraint_deactivate (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
MetaWaylandPointer *pointer = seat->pointer;
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
|
||||
if ((pointer->grab->interface != &confined_pointer_grab_interface &&
|
||||
pointer->grab->interface != &locked_pointer_grab_interface))
|
||||
return;
|
||||
|
||||
constraint = wl_container_of (pointer->grab, constraint, grab);
|
||||
|
||||
if (constraint->surface != window->surface)
|
||||
return;
|
||||
|
||||
if (meta_window_appears_focused (window) &&
|
||||
pointer->focus_surface == window->surface)
|
||||
return;
|
||||
|
||||
switch (constraint->lifetime)
|
||||
{
|
||||
case ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT:
|
||||
@ -554,6 +550,25 @@ meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_constraint_maybe_remove_for_seat (MetaWaylandSeat *seat,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWaylandPointer *pointer = seat->pointer;
|
||||
MetaWaylandPointerConstraint *constraint;
|
||||
|
||||
if ((pointer->grab->interface != &confined_pointer_grab_interface &&
|
||||
pointer->grab->interface != &locked_pointer_grab_interface))
|
||||
return;
|
||||
|
||||
constraint = wl_container_of (pointer->grab, constraint, grab);
|
||||
|
||||
if (should_constraint_be_enabled (constraint))
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_constraint_deactivate (constraint);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_constraint_maybe_enable_for_window (MetaWindow *window)
|
||||
{
|
||||
@ -589,11 +604,32 @@ cairo_region_t *
|
||||
meta_wayland_pointer_constraint_calculate_effective_region (MetaWaylandPointerConstraint *constraint)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
MetaWindow *window;
|
||||
|
||||
region = meta_wayland_surface_calculate_input_region (constraint->surface);
|
||||
if (constraint->region)
|
||||
cairo_region_intersect (region, constraint->region);
|
||||
|
||||
window = constraint->surface->window;
|
||||
if (window && window->frame)
|
||||
{
|
||||
MetaFrame *frame = window->frame;
|
||||
int actual_width, actual_height;
|
||||
|
||||
g_assert (meta_xwayland_is_xwayland_surface (constraint->surface));
|
||||
|
||||
actual_width = window->buffer_rect.width - (frame->child_x +
|
||||
frame->right_width);
|
||||
actual_height = window->buffer_rect.height - (frame->child_y +
|
||||
frame->bottom_height);
|
||||
cairo_region_intersect_rectangle (region, &(cairo_rectangle_int_t) {
|
||||
.x = frame->child_x,
|
||||
.y = frame->child_y,
|
||||
.width = actual_width,
|
||||
.height = actual_height
|
||||
});
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
@ -938,10 +974,20 @@ locked_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab,
|
||||
meta_wayland_pointer_send_button (grab->pointer, event);
|
||||
}
|
||||
|
||||
static void
|
||||
locked_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab)
|
||||
{
|
||||
MetaWaylandPointerConstraint *constraint =
|
||||
wl_container_of (grab, constraint, grab);
|
||||
|
||||
meta_wayland_pointer_constraint_deactivate (constraint);
|
||||
}
|
||||
|
||||
static const MetaWaylandPointerGrabInterface locked_pointer_grab_interface = {
|
||||
locked_pointer_grab_pointer_focus,
|
||||
locked_pointer_grab_pointer_motion,
|
||||
locked_pointer_grab_pointer_button,
|
||||
locked_pointer_grab_pointer_cancel,
|
||||
};
|
||||
|
||||
static void
|
||||
@ -999,10 +1045,20 @@ confined_pointer_grab_pointer_button (MetaWaylandPointerGrab *grab,
|
||||
meta_wayland_pointer_send_button (grab->pointer, event);
|
||||
}
|
||||
|
||||
static void
|
||||
confined_pointer_grab_pointer_cancel (MetaWaylandPointerGrab *grab)
|
||||
{
|
||||
MetaWaylandPointerConstraint *constraint =
|
||||
wl_container_of (grab, constraint, grab);
|
||||
|
||||
meta_wayland_pointer_constraint_deactivate (constraint);
|
||||
}
|
||||
|
||||
static const MetaWaylandPointerGrabInterface confined_pointer_grab_interface = {
|
||||
confined_pointer_grab_pointer_focus,
|
||||
confined_pointer_grab_pointer_motion,
|
||||
confined_pointer_grab_pointer_button,
|
||||
confined_pointer_grab_pointer_cancel,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -38,18 +38,19 @@ handle_pinch_begin (MetaWaylandPointer *pointer,
|
||||
MetaWaylandPointerClient *pointer_client;
|
||||
MetaWaylandSeat *seat;
|
||||
struct wl_resource *resource;
|
||||
uint32_t serial;
|
||||
uint32_t serial, fingers;
|
||||
|
||||
pointer_client = pointer->focus_client;
|
||||
seat = meta_wayland_pointer_get_seat (pointer);
|
||||
serial = wl_display_next_serial (seat->wl_display);
|
||||
fingers = clutter_event_get_touchpad_gesture_finger_count (event);
|
||||
|
||||
wl_resource_for_each (resource, &pointer_client->pinch_gesture_resources)
|
||||
{
|
||||
zwp_pointer_gesture_pinch_v1_send_begin (resource, serial,
|
||||
clutter_event_get_time (event),
|
||||
pointer->focus_surface->resource,
|
||||
2);
|
||||
fingers);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ handle_swipe_begin (MetaWaylandPointer *pointer,
|
||||
pointer_client = pointer->focus_client;
|
||||
seat = meta_wayland_pointer_get_seat (pointer);
|
||||
serial = wl_display_next_serial (seat->wl_display);
|
||||
fingers = clutter_event_get_gesture_swipe_finger_count (event);
|
||||
fingers = clutter_event_get_touchpad_gesture_finger_count (event);
|
||||
|
||||
wl_resource_for_each (resource, &pointer_client->swipe_gesture_resources)
|
||||
{
|
||||
|
@ -86,6 +86,12 @@ static guint signals[LAST_SIGNAL];
|
||||
G_DEFINE_TYPE (MetaWaylandPointer, meta_wayland_pointer,
|
||||
META_TYPE_WAYLAND_INPUT_DEVICE)
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer);
|
||||
|
||||
static MetaWaylandPointerClient *
|
||||
meta_wayland_pointer_client_new (void)
|
||||
{
|
||||
@ -358,8 +364,8 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
|
||||
if (pointer->focus_client &&
|
||||
!wl_list_empty (&pointer->focus_client->pointer_resources))
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (pointer->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
MetaWaylandInputDevice *input_device =
|
||||
META_WAYLAND_INPUT_DEVICE (pointer);
|
||||
uint32_t time;
|
||||
uint32_t button;
|
||||
uint32_t serial;
|
||||
@ -395,7 +401,7 @@ meta_wayland_pointer_send_button (MetaWaylandPointer *pointer,
|
||||
}
|
||||
|
||||
time = clutter_event_get_time (event);
|
||||
serial = wl_display_next_serial (display);
|
||||
serial = meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
wl_resource_for_each (resource, &pointer->focus_client->pointer_resources)
|
||||
{
|
||||
@ -416,11 +422,27 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandPointer *pointer = grab->pointer;
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (pointer->button_count > 0)
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_set_focus (pointer, surface);
|
||||
switch (display->event_route)
|
||||
{
|
||||
case META_EVENT_ROUTE_WINDOW_OP:
|
||||
case META_EVENT_ROUTE_COMPOSITOR_GRAB:
|
||||
case META_EVENT_ROUTE_FRAME_BUTTON:
|
||||
return;
|
||||
break;
|
||||
|
||||
case META_EVENT_ROUTE_NORMAL:
|
||||
case META_EVENT_ROUTE_WAYLAND_POPUP:
|
||||
break;
|
||||
}
|
||||
|
||||
if (meta_wayland_seat_has_pointer (seat))
|
||||
meta_wayland_pointer_set_focus (pointer, surface);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -493,7 +515,8 @@ meta_wayland_pointer_disable (MetaWaylandPointer *pointer)
|
||||
pointer->cursor_surface_destroy_id);
|
||||
}
|
||||
|
||||
meta_wayland_pointer_end_grab (pointer);
|
||||
meta_wayland_pointer_cancel_grab (pointer);
|
||||
meta_wayland_pointer_reset_grab (pointer);
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
|
||||
g_clear_pointer (&pointer->pointer_clients, g_hash_table_unref);
|
||||
@ -534,7 +557,8 @@ repick_for_event (MetaWaylandPointer *pointer,
|
||||
actor = clutter_input_device_get_pointer_actor (pointer->device);
|
||||
|
||||
if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
|
||||
pointer->current = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
pointer->current =
|
||||
meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
|
||||
else
|
||||
pointer->current = NULL;
|
||||
|
||||
@ -793,22 +817,16 @@ void
|
||||
meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (pointer);
|
||||
|
||||
if (!meta_wayland_seat_has_pointer (seat))
|
||||
return;
|
||||
MetaWaylandInputDevice *input_device = META_WAYLAND_INPUT_DEVICE (pointer);
|
||||
|
||||
if (pointer->focus_surface == surface)
|
||||
return;
|
||||
|
||||
if (pointer->focus_surface != NULL)
|
||||
{
|
||||
struct wl_client *client =
|
||||
wl_resource_get_client (pointer->focus_surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
uint32_t serial;
|
||||
|
||||
serial = wl_display_next_serial (display);
|
||||
serial = meta_wayland_input_device_next_serial (input_device);
|
||||
|
||||
if (pointer->focus_client)
|
||||
{
|
||||
@ -825,11 +843,11 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
if (surface != NULL)
|
||||
{
|
||||
struct wl_client *client = wl_resource_get_client (surface->resource);
|
||||
struct wl_display *display = wl_client_get_display (client);
|
||||
ClutterPoint pos;
|
||||
|
||||
pointer->focus_surface = surface;
|
||||
wl_resource_add_destroy_listener (pointer->focus_surface->resource, &pointer->focus_surface_listener);
|
||||
wl_resource_add_destroy_listener (pointer->focus_surface->resource,
|
||||
&pointer->focus_surface_listener);
|
||||
|
||||
clutter_input_device_get_coords (pointer->device, NULL, &pos);
|
||||
|
||||
@ -843,7 +861,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
meta_wayland_pointer_get_pointer_client (pointer, client);
|
||||
if (pointer->focus_client)
|
||||
{
|
||||
pointer->focus_serial = wl_display_next_serial (display);
|
||||
pointer->focus_serial =
|
||||
meta_wayland_input_device_next_serial (input_device);
|
||||
meta_wayland_pointer_broadcast_enter (pointer,
|
||||
pointer->focus_serial,
|
||||
pointer->focus_surface);
|
||||
@ -861,6 +880,8 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
{
|
||||
const MetaWaylandPointerGrabInterface *interface;
|
||||
|
||||
meta_wayland_pointer_cancel_grab (pointer);
|
||||
|
||||
pointer->grab = grab;
|
||||
interface = pointer->grab->interface;
|
||||
grab->pointer = pointer;
|
||||
@ -868,6 +889,12 @@ meta_wayland_pointer_start_grab (MetaWaylandPointer *pointer,
|
||||
interface->focus (pointer->grab, pointer->current);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_reset_grab (MetaWaylandPointer *pointer)
|
||||
{
|
||||
pointer->grab = &pointer->default_grab;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
{
|
||||
@ -880,6 +907,13 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
meta_wayland_pointer_update_cursor_surface (pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_pointer_cancel_grab (MetaWaylandPointer *pointer)
|
||||
{
|
||||
if (pointer->grab->interface->cancel)
|
||||
pointer->grab->interface->cancel (pointer->grab);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_end_popup_grab (MetaWaylandPointer *pointer)
|
||||
{
|
||||
@ -1059,24 +1093,25 @@ meta_wayland_pointer_create_new_resource (MetaWaylandPointer *pointer,
|
||||
struct wl_resource *seat_resource,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *cr;
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandPointerClient *pointer_client;
|
||||
|
||||
cr = wl_resource_create (client, &wl_pointer_interface, wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (cr, &pointer_interface, pointer,
|
||||
resource = wl_resource_create (client, &wl_pointer_interface,
|
||||
wl_resource_get_version (seat_resource), id);
|
||||
wl_resource_set_implementation (resource, &pointer_interface, pointer,
|
||||
meta_wayland_pointer_unbind_pointer_client_resource);
|
||||
|
||||
pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client);
|
||||
|
||||
wl_list_insert (&pointer_client->pointer_resources,
|
||||
wl_resource_get_link (cr));
|
||||
wl_resource_get_link (resource));
|
||||
|
||||
if (pointer->focus_client == pointer_client)
|
||||
{
|
||||
meta_wayland_pointer_send_enter (pointer, cr,
|
||||
meta_wayland_pointer_send_enter (pointer, resource,
|
||||
pointer->focus_serial,
|
||||
pointer->focus_surface);
|
||||
meta_wayland_pointer_send_frame (pointer, cr);
|
||||
meta_wayland_pointer_send_frame (pointer, resource);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1127,30 +1162,31 @@ relative_pointer_manager_destroy (struct wl_client *client,
|
||||
|
||||
static void
|
||||
relative_pointer_manager_get_relative_pointer (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *manager_resource,
|
||||
uint32_t id,
|
||||
struct wl_resource *pointer_resource)
|
||||
{
|
||||
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
|
||||
struct wl_resource *cr;
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandPointerClient *pointer_client;
|
||||
|
||||
cr = wl_resource_create (client, &zwp_relative_pointer_v1_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
if (cr == NULL)
|
||||
resource = wl_resource_create (client, &zwp_relative_pointer_v1_interface,
|
||||
wl_resource_get_version (manager_resource),
|
||||
id);
|
||||
if (!resource)
|
||||
{
|
||||
wl_client_post_no_memory (client);
|
||||
return;
|
||||
}
|
||||
|
||||
wl_resource_set_implementation (cr, &relative_pointer_interface,
|
||||
wl_resource_set_implementation (resource, &relative_pointer_interface,
|
||||
pointer,
|
||||
meta_wayland_pointer_unbind_pointer_client_resource);
|
||||
|
||||
pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client);
|
||||
|
||||
wl_list_insert (&pointer_client->relative_pointer_resources,
|
||||
wl_resource_get_link (cr));
|
||||
wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
|
||||
|
@ -46,6 +46,7 @@ struct _MetaWaylandPointerGrabInterface
|
||||
const ClutterEvent *event);
|
||||
void (*button) (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event);
|
||||
void (*cancel) (MetaWaylandPointerGrab *grab);
|
||||
};
|
||||
|
||||
struct _MetaWaylandPointerGrab
|
||||
|
@ -101,6 +101,16 @@ popup_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
MetaWaylandPopupGrab *popup_grab = (MetaWaylandPopupGrab*)grab;
|
||||
MetaWaylandSeat *seat = meta_wayland_pointer_get_seat (grab->pointer);
|
||||
|
||||
/*
|
||||
* We rely on having a pointer grab even when the seat doesn't have
|
||||
* the pointer capability. In this case, we shouldn't update any pointer focus
|
||||
* since there is no such thing when the seat doesn't have the pointer
|
||||
* capability.
|
||||
*/
|
||||
if (!meta_wayland_seat_has_pointer (seat))
|
||||
return;
|
||||
|
||||
/* Popup grabs are in owner-events mode (ie, events for the same client
|
||||
are reported as normal) */
|
||||
@ -131,10 +141,17 @@ popup_grab_button (MetaWaylandPointerGrab *grab,
|
||||
meta_wayland_pointer_end_popup_grab (grab->pointer);
|
||||
}
|
||||
|
||||
static void
|
||||
popup_grab_cancel (MetaWaylandPointerGrab *grab)
|
||||
{
|
||||
meta_wayland_pointer_end_popup_grab (grab->pointer);
|
||||
}
|
||||
|
||||
static MetaWaylandPointerGrabInterface popup_grab_interface = {
|
||||
popup_grab_focus,
|
||||
popup_grab_motion,
|
||||
popup_grab_button
|
||||
popup_grab_button,
|
||||
popup_grab_cancel
|
||||
};
|
||||
|
||||
MetaWaylandPopupGrab *
|
||||
@ -249,12 +266,12 @@ meta_wayland_popup_dismiss (MetaWaylandPopup *popup)
|
||||
{
|
||||
MetaWaylandSurface *top_popup_surface;
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandKeyboard *keyboard;
|
||||
|
||||
top_popup_surface = meta_wayland_popup_grab_get_top_popup (popup_grab);
|
||||
seat = meta_wayland_pointer_get_seat (popup_grab->generic.pointer);
|
||||
keyboard = seat->keyboard;
|
||||
meta_wayland_keyboard_set_focus (keyboard, top_popup_surface);
|
||||
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, top_popup_surface);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +289,6 @@ meta_wayland_popup_create (MetaWaylandPopupSurface *popup_surface,
|
||||
meta_wayland_popup_surface_get_surface (popup_surface);
|
||||
MetaWaylandPopup *popup;
|
||||
MetaWaylandSeat *seat;
|
||||
MetaWaylandKeyboard *keyboard;
|
||||
|
||||
/* Don't allow creating popups if the grab has a different client. */
|
||||
if (grab->grab_client != wl_resource_get_client (surface->resource))
|
||||
@ -285,8 +301,8 @@ meta_wayland_popup_create (MetaWaylandPopupSurface *popup_surface,
|
||||
wl_list_insert (&grab->all_popups, &popup->link);
|
||||
|
||||
seat = meta_wayland_pointer_get_seat (grab->generic.pointer);
|
||||
keyboard = seat->keyboard;
|
||||
meta_wayland_keyboard_set_focus (keyboard, surface);
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, surface);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ seat_get_pointer (struct wl_client *client,
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandPointer *pointer = seat->pointer;
|
||||
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_POINTER) != 0)
|
||||
if (meta_wayland_seat_has_pointer (seat))
|
||||
meta_wayland_pointer_create_new_resource (pointer, client, resource, id);
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ seat_get_keyboard (struct wl_client *client,
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandKeyboard *keyboard = seat->keyboard;
|
||||
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0)
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
meta_wayland_keyboard_create_new_resource (keyboard, client, resource, id);
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ seat_get_touch (struct wl_client *client,
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
|
||||
MetaWaylandTouch *touch = seat->touch;
|
||||
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0)
|
||||
if (meta_wayland_seat_has_touch (seat))
|
||||
meta_wayland_touch_create_new_resource (touch, client, resource, id);
|
||||
}
|
||||
|
||||
@ -319,20 +319,20 @@ meta_wayland_seat_update (MetaWaylandSeat *seat,
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_SCROLL:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
|
||||
if (meta_wayland_seat_has_pointer (seat))
|
||||
meta_wayland_pointer_update (seat->pointer, event);
|
||||
break;
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
meta_wayland_keyboard_update (seat->keyboard, (const ClutterKeyEvent *) event);
|
||||
break;
|
||||
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
case CLUTTER_TOUCH_END:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
|
||||
if (meta_wayland_seat_has_touch (seat))
|
||||
meta_wayland_touch_update (seat->touch, event);
|
||||
break;
|
||||
|
||||
@ -356,18 +356,18 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
case CLUTTER_SCROLL:
|
||||
case CLUTTER_TOUCHPAD_SWIPE:
|
||||
case CLUTTER_TOUCHPAD_PINCH:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
|
||||
if (meta_wayland_seat_has_pointer (seat))
|
||||
return meta_wayland_pointer_handle_event (seat->pointer, event);
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
return meta_wayland_keyboard_handle_event (seat->keyboard,
|
||||
(const ClutterKeyEvent *) event);
|
||||
case CLUTTER_TOUCH_BEGIN:
|
||||
case CLUTTER_TOUCH_UPDATE:
|
||||
case CLUTTER_TOUCH_END:
|
||||
if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
|
||||
if (meta_wayland_seat_has_touch (seat))
|
||||
return meta_wayland_touch_handle_event (seat->touch, event);
|
||||
|
||||
default:
|
||||
@ -380,7 +380,7 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
void
|
||||
meta_wayland_seat_repick (MetaWaylandSeat *seat)
|
||||
{
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0)
|
||||
if (!meta_wayland_seat_has_pointer (seat))
|
||||
return;
|
||||
|
||||
meta_wayland_pointer_repick (seat->pointer);
|
||||
@ -393,7 +393,7 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0)
|
||||
if (meta_wayland_seat_has_keyboard (seat))
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
||||
@ -414,7 +414,7 @@ meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
|
||||
ClutterEventSequence *sequence = NULL;
|
||||
gboolean can_grab_surface = FALSE;
|
||||
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_TOUCH) != 0)
|
||||
if (meta_wayland_seat_has_touch (seat))
|
||||
sequence = meta_wayland_touch_find_grab_sequence (seat->touch,
|
||||
surface,
|
||||
serial);
|
||||
@ -425,7 +425,7 @@ meta_wayland_seat_get_grab_info (MetaWaylandSeat *seat,
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((seat->capabilities & WL_SEAT_CAPABILITY_POINTER) != 0 &&
|
||||
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,
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "meta-window-wayland.h"
|
||||
|
||||
#include "compositor/region-utils.h"
|
||||
#include "compositor/meta-shaped-texture-private.h"
|
||||
|
||||
#include "meta-surface-actor.h"
|
||||
#include "meta-surface-actor-wayland.h"
|
||||
@ -701,9 +702,6 @@ static void
|
||||
apply_pending_state (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaSurfaceActorWayland *surface_actor_wayland =
|
||||
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
|
||||
|
||||
if (surface->role)
|
||||
{
|
||||
meta_wayland_surface_role_pre_commit (surface->role, pending);
|
||||
@ -738,21 +736,38 @@ apply_pending_state (MetaWaylandSurface *surface,
|
||||
if (pending->buffer)
|
||||
meta_wayland_surface_ref_buffer_use_count (surface);
|
||||
|
||||
if (switched_buffer && pending->buffer)
|
||||
if (pending->buffer)
|
||||
{
|
||||
CoglTexture *texture;
|
||||
GError *error = NULL;
|
||||
|
||||
texture = meta_wayland_buffer_ensure_texture (pending->buffer);
|
||||
if (!texture)
|
||||
if (!meta_wayland_buffer_attach (pending->buffer, &error))
|
||||
{
|
||||
g_warning ("Could not import pending buffer: %s", error->message);
|
||||
wl_resource_post_error (surface->resource, WL_DISPLAY_ERROR_NO_MEMORY,
|
||||
"Failed to create a texture for surface %i",
|
||||
wl_resource_get_id (surface->resource));
|
||||
|
||||
"Failed to create a texture for surface %i: %s",
|
||||
wl_resource_get_id (surface->resource),
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
goto cleanup;
|
||||
}
|
||||
meta_surface_actor_wayland_set_texture (surface_actor_wayland,
|
||||
texture);
|
||||
|
||||
if (switched_buffer)
|
||||
{
|
||||
MetaShapedTexture *stex;
|
||||
CoglTexture *texture;
|
||||
CoglSnippet *snippet;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
stex = meta_surface_actor_get_texture (surface->surface_actor);
|
||||
texture = meta_wayland_buffer_get_texture (pending->buffer);
|
||||
snippet = meta_wayland_buffer_create_snippet (pending->buffer);
|
||||
is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
|
||||
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
meta_shaped_texture_set_snippet (stex, snippet);
|
||||
meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
|
||||
g_clear_pointer (&snippet, cogl_object_unref);
|
||||
}
|
||||
}
|
||||
|
||||
/* If the newly attached buffer is going to be accessed directly without
|
||||
|
@ -358,26 +358,6 @@ handle_pad_button_event (MetaWaylandTabletPad *pad,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_tablet_pad_update_action (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
guint button;
|
||||
|
||||
button = event->pad_button.button;
|
||||
device = clutter_event_get_source_device (event);
|
||||
input_settings = meta_backend_get_input_settings (meta_get_backend ());
|
||||
|
||||
if (!input_settings)
|
||||
return;
|
||||
|
||||
meta_input_settings_handle_pad_button (input_settings, device,
|
||||
event->type == CLUTTER_PAD_BUTTON_PRESS,
|
||||
button);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_wayland_tablet_pad_handle_event_action (MetaWaylandTabletPad *pad,
|
||||
const ClutterEvent *event)
|
||||
@ -566,18 +546,6 @@ meta_wayland_tablet_pad_update (MetaWaylandTabletPad *pad,
|
||||
|
||||
if (group)
|
||||
meta_wayland_tablet_pad_group_update (group, event);
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_PAD_BUTTON_PRESS:
|
||||
case CLUTTER_PAD_BUTTON_RELEASE:
|
||||
meta_wayland_tablet_pad_update_action (pad, event);
|
||||
break;
|
||||
case CLUTTER_PAD_RING:
|
||||
case CLUTTER_PAD_STRIP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar *
|
||||
|
@ -654,63 +654,6 @@ broadcast_up (MetaWaylandTabletTool *tool,
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
translate_button_action (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
GDesktopStylusButtonAction action;
|
||||
MetaBackend *backend;
|
||||
|
||||
backend = meta_get_backend ();
|
||||
input_settings = meta_backend_get_input_settings (backend);
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
ClutterInputDevice *device;
|
||||
|
||||
device = clutter_event_get_source_device (event);
|
||||
action = meta_input_settings_get_stylus_button_action (input_settings,
|
||||
tool->device_tool,
|
||||
device,
|
||||
event->button.button);
|
||||
}
|
||||
else
|
||||
{
|
||||
action = G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT;
|
||||
}
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_MIDDLE:
|
||||
return BTN_STYLUS;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_RIGHT:
|
||||
return BTN_STYLUS2;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_BACK:
|
||||
return BTN_BACK;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_FORWARD:
|
||||
return BTN_FORWARD;
|
||||
case G_DESKTOP_STYLUS_BUTTON_ACTION_DEFAULT:
|
||||
default:
|
||||
{
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
return clutter_evdev_event_get_event_code (event);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* We can't do much better here, there's several
|
||||
* different BTN_ ranges to cover.
|
||||
*/
|
||||
return event->button.button;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
broadcast_button (MetaWaylandTabletTool *tool,
|
||||
const ClutterEvent *event)
|
||||
@ -718,7 +661,21 @@ broadcast_button (MetaWaylandTabletTool *tool,
|
||||
struct wl_resource *resource;
|
||||
guint32 button;
|
||||
|
||||
button = translate_button_action (tool, event);
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
if (META_IS_BACKEND_NATIVE (backend))
|
||||
{
|
||||
button = clutter_evdev_event_get_event_code (event);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* We can't do much better here, there's several
|
||||
* different BTN_ ranges to cover.
|
||||
*/
|
||||
button = event->button.button;
|
||||
}
|
||||
|
||||
tool->button_serial = wl_display_next_serial (tool->seat->manager->wl_display);
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
@ -745,24 +702,6 @@ broadcast_axis (MetaWaylandTabletTool *tool,
|
||||
if (!clutter_input_device_get_axis_value (source, event->motion.axes, axis, &val))
|
||||
return;
|
||||
|
||||
if (axis == CLUTTER_INPUT_AXIS_PRESSURE)
|
||||
{
|
||||
MetaInputSettings *input_settings;
|
||||
ClutterInputDevice *device;
|
||||
MetaBackend *backend;
|
||||
|
||||
backend = meta_get_backend ();
|
||||
input_settings = meta_backend_get_input_settings (backend);
|
||||
device = clutter_event_get_source_device (event);
|
||||
|
||||
if (input_settings)
|
||||
{
|
||||
val = meta_input_settings_translate_tablet_tool_pressure (input_settings,
|
||||
tool->device_tool,
|
||||
device, val);
|
||||
}
|
||||
}
|
||||
|
||||
value = val * TABLET_AXIS_MAX;
|
||||
|
||||
wl_resource_for_each (resource, &tool->focus_resource_list)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user