Skip to content
Commits on Source (21)
3.36.3
======
* Broadcast clipboard/primary offers [Carlos; !1262]
* Fix monitor screen cast on X11 [Jonas Å.; !1251]
* Implement touch-mode detecation for the X11 backend [Carlos; !1278]
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277]
* Fix leaked DMA buffers in screencasts [Jonas; !1283]
* Fixed crashes [Daniel, Carlos, Jonas D.; !1256, !1258, !1280]
Contributors:
Carlos Garnacho, Daniel van Vugt, Jonas Ådahl
3.36.2
======
* Sync timelines to hardware vsync [Daniel; !724]
......
......@@ -2604,6 +2604,9 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
gboolean retval;
ClutterActorBox old_alloc = { 0, };
 
g_return_val_if_fail (!isnan (box->x1) && !isnan (box->x2) &&
!isnan (box->y1) && !isnan (box->y2), FALSE);
obj = G_OBJECT (self);
 
g_object_freeze_notify (obj);
......@@ -10366,6 +10369,11 @@ clutter_actor_allocate (ClutterActor *self,
old_allocation = priv->allocation;
real_allocation = *box;
 
g_return_if_fail (!isnan (real_allocation.x1) &&
!isnan (real_allocation.x2) &&
!isnan (real_allocation.y1) &&
!isnan (real_allocation.y2));
/* constraints are allowed to modify the allocation only here; we do
* this prior to all the other checks so that we can bail out if the
* allocation did not change
......
......@@ -682,7 +682,6 @@ clutter_seat_warp_pointer (ClutterSeat *seat,
* requirements are fulfilled:
*
* - A touchscreen is available
* - No external keyboard is attached to the device
* - A tablet mode switch, if present, is enabled
*
* Returns: %TRUE if the device is a tablet that doesn't have an external
......
mutter (3.36.3-0ubuntu0.20.04.1) focal; urgency=medium
* New upstream release (LP: #1881971)
- Broadcast clipboard/primary offers
- Fix monitor screen cast on X11
- Implement touch-mode detecation for the X11 backend (LP: #1880596)
- Drop external keyboard detection from touch-mode heuristics
- Fix leaked DMA buffers in screencasts
- Fixed crashes
* Refreshed patches
* d/p/backend-x11-Reintroduce-XInitThreads.patch:
- Dropped (merged upstream)
-- Marco Trevisan (Treviño) <marco@ubuntu.com> Fri, 05 Jun 2020 19:29:32 +0200
mutter (3.36.2-1ubuntu1~20.04.2) focal; urgency=medium
[ Daniel van Vugt ]
......
From: Daniel van Vugt <daniel.van.vugt@canonical.com>
Date: Thu, 14 May 2020 18:13:56 +0800
Subject: backend-x11: Reintroduce XInitThreads
It was removed in 3.34 as part of 6ed5d2e2. And we thought that was the
only thread that might exist and use X11. But the top gnome-shell crasher
in 3.36 seems to suggest otherwise.
We don't know what or where the offending thread is, but since:
1. We used XInitThreads for years already prior to 3.34; and
2. Extensions or any change to mutter/gnome-shell could conceivably use
threads to make X calls, directly or indirectly,
it's probably a good idea to reintroduce XInitThreads. The failing assertion
in libx11 is also accompanied by a strong hint:
```
fprintf(stderr, "[xcb] Most likely this is a multi-threaded client " \
"and XInitThreads has not been called\n");
```
Bug: https://gitlab.gnome.org/GNOME/mutter/-/issues/1252
Bug-Ubuntu: https://bugs.launchpad.net/bugs/1877075
Author: Daniel van Vugt <daniel.van.vugt@canonical.com>
Origin: https://gitlab.gnome.org/GNOME/mutter/-/commit/1d5f9b69
Forwarded: yes
Last-Update: 2020-05-21
(cherry picked from commit 1d5f9b6917517d6e777a652cfa5e648794dc632a)
---
src/backends/x11/meta-backend-x11.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index 515d2a8..7bb8ff3 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -855,6 +855,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
+ XInitThreads ();
}
Display *
......@@ -260,10 +260,10 @@ index 4006777..820b7ea 100644
switch (mode)
{
diff --git a/src/backends/x11/meta-seat-x11.c b/src/backends/x11/meta-seat-x11.c
index e6e9968..587a6ca 100644
index f20cac1..8288228 100644
--- a/src/backends/x11/meta-seat-x11.c
+++ b/src/backends/x11/meta-seat-x11.c
@@ -243,7 +243,8 @@ is_touch_device (XIAnyClassInfo **classes,
@@ -248,7 +248,8 @@ is_touch_device (XIAnyClassInfo **classes,
}
static gboolean
......@@ -273,7 +273,7 @@ index e6e9968..587a6ca 100644
{
gulong nitems, bytes_after;
uint32_t *data = NULL;
@@ -251,7 +252,7 @@ is_touchpad_device (XIDeviceInfo *info)
@@ -256,7 +257,7 @@ is_touchpad_device (XIDeviceInfo *info)
Atom type;
Atom prop;
......@@ -282,7 +282,7 @@ index e6e9968..587a6ca 100644
if (prop == None)
return FALSE;
@@ -272,6 +273,13 @@ is_touchpad_device (XIDeviceInfo *info)
@@ -277,6 +278,13 @@ is_touchpad_device (XIDeviceInfo *info)
return TRUE;
}
......
......@@ -44,7 +44,7 @@ index 2dfe5bc..3d4c2d3 100644
input: 'cogl-config.h.meson',
output: 'cogl-config.h',
diff --git a/meson.build b/meson.build
index ed9cc88..fb35bc8 100644
index bce6095..e184347 100644
--- a/meson.build
+++ b/meson.build
@@ -222,6 +222,8 @@ if have_wayland_eglstream
......
......@@ -4,4 +4,3 @@ meson-add-back-default_driver-option.patch
x11-Add-support-for-fractional-scaling-using-Randr.patch
debian/synaptics-support.patch
debian/tests-Tag-closed-transient-no-input-tests-as-flaky.patch
backend-x11-Reintroduce-XInitThreads.patch
project('mutter', 'c',
version: '3.36.2',
version: '3.36.3',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)
......
......@@ -55,6 +55,7 @@ struct _MetaRemoteDesktopSession
MetaScreenCastSession *screen_cast_session;
gulong screen_cast_session_closed_handler_id;
guint started : 1;
ClutterVirtualInputDevice *virtual_pointer;
ClutterVirtualInputDevice *virtual_keyboard;
......@@ -119,7 +120,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
ClutterBackend *backend = clutter_get_default_backend ();
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
g_assert (!session->virtual_pointer && !session->virtual_keyboard);
g_assert (!session->started);
if (session->screen_cast_session)
{
......@@ -135,6 +136,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE);
init_remote_access_handle (session);
session->started = TRUE;
return TRUE;
}
......@@ -145,6 +147,8 @@ meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
MetaDBusRemoteDesktopSession *skeleton =
META_DBUS_REMOTE_DESKTOP_SESSION (session);
session->started = FALSE;
if (session->screen_cast_session)
{
g_clear_signal_handler (&session->screen_cast_session_closed_handler_id,
......@@ -249,6 +253,37 @@ check_permission (MetaRemoteDesktopSession *session,
g_dbus_method_invocation_get_sender (invocation)) == 0;
}
static gboolean
meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
GDBusMethodInvocation *invocation)
{
if (!session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session not started");
return FALSE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return FALSE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return FALSE;
}
return TRUE;
}
static gboolean
handle_start (MetaDBusRemoteDesktopSession *skeleton,
GDBusMethodInvocation *invocation)
......@@ -256,6 +291,14 @@ handle_start (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
GError *error = NULL;
if (session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Already started");
return TRUE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
......@@ -288,6 +331,14 @@ handle_stop (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!session->started)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Session not started");
return TRUE;
}
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
......@@ -312,13 +363,8 @@ handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterKeyState state;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (pressed)
state = CLUTTER_KEY_STATE_PRESSED;
......@@ -344,13 +390,8 @@ handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterKeyState state;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (pressed)
state = CLUTTER_KEY_STATE_PRESSED;
......@@ -398,13 +439,8 @@ handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton,
uint32_t button;
ClutterButtonState state;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
button = translate_to_clutter_button (button_code);
......@@ -434,13 +470,8 @@ handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton,
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
{
......@@ -487,13 +518,8 @@ handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton,
ClutterScrollDirection direction;
int step_count;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
if (axis > 1)
{
......@@ -538,13 +564,8 @@ handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
CLUTTER_CURRENT_TIME,
......@@ -567,21 +588,8 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
......@@ -617,21 +625,8 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
......@@ -668,21 +663,8 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
MetaScreenCastStream *stream;
double abs_x, abs_y;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!session->screen_cast_session)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"No screen cast active");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
stream_path);
......@@ -714,13 +696,8 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
{
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
return TRUE;
}
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
return TRUE;
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
CLUTTER_CURRENT_TIME,
......
......@@ -160,14 +160,12 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
}
void
meta_renderer_set_legacy_view (MetaRenderer *renderer,
MetaRendererView *legacy_view)
meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view)
{
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
g_assert (!priv->views);
priv->views = g_list_append (priv->views, legacy_view);
priv->views = g_list_append (priv->views, view);
}
/**
......
......@@ -54,8 +54,8 @@ CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
void meta_renderer_rebuild_views (MetaRenderer *renderer);
void meta_renderer_set_legacy_view (MetaRenderer *renderer,
MetaRendererView *legacy_view);
void meta_renderer_add_view (MetaRenderer *renderer,
MetaRendererView *view);
META_EXPORT_TEST
GList * meta_renderer_get_views (MetaRenderer *renderer);
......
......@@ -68,6 +68,7 @@ typedef struct _MetaPipeWireSource
{
GSource base;
MetaScreenCastStreamSrc *src;
struct pw_loop *pipewire_loop;
} MetaPipeWireSource;
......@@ -81,6 +82,7 @@ typedef struct _MetaScreenCastStreamSrcPrivate
struct spa_hook pipewire_core_listener;
gboolean is_enabled;
gboolean emit_closed_after_dispatch;
struct pw_stream *pipewire_stream;
struct spa_hook pipewire_stream_listener;
......@@ -445,7 +447,8 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
uint64_t now_us;
now_us = g_get_monotonic_time ();
if (priv->last_frame_timestamp_us != 0 &&
if (priv->video_format.max_framerate.num > 0 &&
priv->last_frame_timestamp_us != 0 &&
(now_us - priv->last_frame_timestamp_us <
((1000000 * priv->video_format.max_framerate.denom) /
priv->video_format.max_framerate.num)))
......@@ -539,12 +542,6 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
priv->is_enabled = FALSE;
}
static void
meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src)
{
g_signal_emit (src, signals[CLOSED], 0);
}
static void
on_stream_state_changed (void *data,
enum pw_stream_state old,
......@@ -559,7 +556,9 @@ on_stream_state_changed (void *data,
{
case PW_STREAM_STATE_ERROR:
g_warning ("pipewire stream error: %s", error_message);
meta_screen_cast_stream_src_notify_closed (src);
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
priv->emit_closed_after_dispatch = TRUE;
break;
case PW_STREAM_STATE_PAUSED:
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
......@@ -827,11 +826,17 @@ on_core_error (void *data,
const char *message)
{
MetaScreenCastStreamSrc *src = data;
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
g_warning ("pipewire remote error: id:%u %s", id, message);
if (id == PW_ID_CORE && res == -EPIPE)
meta_screen_cast_stream_src_notify_closed (src);
{
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
priv->emit_closed_after_dispatch = TRUE;
}
}
static gboolean
......@@ -848,12 +853,18 @@ pipewire_loop_source_dispatch (GSource *source,
gpointer user_data)
{
MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source;
MetaScreenCastStreamSrc *src = pipewire_source->src;
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
int result;
result = pw_loop_iterate (pipewire_source->pipewire_loop, 0);
if (result < 0)
g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
if (priv->emit_closed_after_dispatch)
g_signal_emit (src, signals[CLOSED], 0);
return TRUE;
}
......@@ -875,13 +886,14 @@ static GSourceFuncs pipewire_source_funcs =
};
static MetaPipeWireSource *
create_pipewire_source (void)
create_pipewire_source (MetaScreenCastStreamSrc *src)
{
MetaPipeWireSource *pipewire_source;
pipewire_source =
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
sizeof (MetaPipeWireSource));
pipewire_source->src = src;
pipewire_source->pipewire_loop = pw_loop_new (NULL);
if (!pipewire_source->pipewire_loop)
{
......@@ -913,7 +925,7 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
priv->pipewire_source = create_pipewire_source ();
priv->pipewire_source = create_pipewire_source (src);
if (!priv->pipewire_source)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
......@@ -975,8 +987,8 @@ meta_screen_cast_stream_src_finalize (GObject *object)
if (meta_screen_cast_stream_src_is_enabled (src))
meta_screen_cast_stream_src_disable (src);
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
g_source_destroy (&priv->pipewire_source->base);
......
......@@ -1380,35 +1380,6 @@ has_touchscreen (MetaSeatNative *seat)
return FALSE;
}
static gboolean
has_external_keyboard (MetaSeatNative *seat)
{
GList *devices, *l;
gboolean has_external = FALSE;
devices = g_udev_client_query_by_subsystem (seat->udev_client, "input");
for (l = devices; l; l = l->next)
{
if (!g_udev_device_has_property (l->data, "ID_INPUT_KEYBOARD"))
continue;
/* May be "hid" or something else, we don't care. This property
* will not be present in virtual "AT Translated Set 2 keyboard"
* devices.
*/
if (!g_udev_device_has_property (l->data, "ID_TYPE"))
break;
has_external = TRUE;
break;
}
g_list_free_full (devices, g_object_unref);
return has_external;
}
static void
update_touch_mode (MetaSeatNative *seat)
{
......@@ -1421,10 +1392,10 @@ update_touch_mode (MetaSeatNative *seat)
else if (seat->has_tablet_switch && !seat->tablet_mode_switch_state)
touch_mode = FALSE;
/* If tablet mode is enabled, or if there is no tablet mode switch
* (eg. kiosk machines), check availability of external keyboards.
* (eg. kiosk machines), assume touch-mode.
*/
else
touch_mode = !seat->has_external_keyboard;
touch_mode = TRUE;
if (seat->touch_mode != touch_mode)
{
......@@ -1465,12 +1436,7 @@ evdev_add_device (MetaSeatNative *seat,
g_signal_emit_by_name (seat, "device-added", device);
if (type == CLUTTER_KEYBOARD_DEVICE)
{
seat->has_external_keyboard = has_external_keyboard (seat);
check_touch_mode = TRUE;
}
else if (type == CLUTTER_TOUCHSCREEN_DEVICE)
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
{
seat->has_touchscreen = TRUE;
check_touch_mode = TRUE;
......@@ -1503,12 +1469,7 @@ evdev_remove_device (MetaSeatNative *seat,
device_type = clutter_input_device_get_device_type (device);
if (device_type == CLUTTER_KEYBOARD_DEVICE)
{
seat->has_external_keyboard = has_external_keyboard (seat);
update_touch_mode (seat);
}
else if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
{
seat->has_touchscreen = has_touchscreen (seat);
update_touch_mode (seat);
......@@ -2553,7 +2514,6 @@ meta_seat_native_constructed (GObject *object)
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
}
seat->has_external_keyboard = has_external_keyboard (seat);
seat->has_touchscreen = has_touchscreen (seat);
update_touch_mode (seat);
......
......@@ -120,7 +120,6 @@ struct _MetaSeatNative
GUdevClient *udev_client;
guint tablet_mode_switch_state : 1;
guint has_external_keyboard : 1;
guint has_touchscreen : 1;
guint has_tablet_switch : 1;
guint touch_mode : 1;
......
......@@ -24,14 +24,75 @@
#include "backends/x11/cm/meta-renderer-x11-cm.h"
#include "backends/meta-renderer-view.h"
struct _MetaRendererX11Cm
{
MetaRendererX11 parent;
MetaRendererView *screen_view;
};
G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
META_TYPE_RENDERER_X11)
void
meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height)
{
cairo_rectangle_int_t view_layout;
if (renderer_x11_cm->screen_view)
return;
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
renderer_x11_cm->screen_view = g_object_new (META_TYPE_RENDERER_VIEW,
"layout", &view_layout,
NULL);
meta_renderer_add_view (META_RENDERER (renderer_x11_cm),
renderer_x11_cm->screen_view);
}
void
meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height)
{
cairo_rectangle_int_t view_layout;
view_layout = (cairo_rectangle_int_t) {
.width = width,
.height = height,
};
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
"layout", &view_layout,
NULL);
}
void
meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
CoglOnscreen *onscreen)
{
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
"framebuffer", onscreen,
NULL);
}
static void
meta_renderer_x11_cm_rebuild_views (MetaRenderer *renderer)
{
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
g_return_if_fail (!meta_renderer_get_views (renderer));
meta_renderer_add_view (renderer, renderer_x11_cm->screen_view);
}
static void
meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
{
......@@ -40,4 +101,7 @@ meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
static void
meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass)
{
MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass);
renderer_class->rebuild_views = meta_renderer_x11_cm_rebuild_views;
}
......@@ -30,4 +30,15 @@ G_DECLARE_FINAL_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
META, RENDERER_X11_CM,
MetaRendererX11)
void meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height);
void meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
int width,
int height);
void meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
CoglOnscreen *onscreen);
#endif /* META_RENDERER_X11_CM_H */
......@@ -855,6 +855,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
static void
meta_backend_x11_init (MetaBackendX11 *x11)
{
XInitThreads ();
}
Display *
......
......@@ -38,7 +38,10 @@ enum
PROP_OPCODE,
PROP_POINTER_ID,
PROP_KEYBOARD_ID,
N_PROPS
N_PROPS,
/* This property is overridden */
PROP_TOUCH_MODE,
};
struct _MetaSeatX11
......@@ -54,6 +57,8 @@ struct _MetaSeatX11
int pointer_id;
int keyboard_id;
int opcode;
guint has_touchscreens : 1;
guint touch_mode : 1;
};
static GParamSpec *props[N_PROPS] = { 0 };
......@@ -605,6 +610,20 @@ pad_passive_button_grab (ClutterInputDevice *device)
g_free (xi_event_mask.mask);
}
static void
update_touch_mode (MetaSeatX11 *seat_x11)
{
gboolean touch_mode;
touch_mode = seat_x11->has_touchscreens;
if (seat_x11->touch_mode == touch_mode)
return;
seat_x11->touch_mode = touch_mode;
g_object_notify (G_OBJECT (seat_x11), "touch-mode");
}
static ClutterInputDevice *
add_device (MetaSeatX11 *seat_x11,
ClutterBackend *backend,
......@@ -635,6 +654,8 @@ add_device (MetaSeatX11 *seat_x11,
info->attachment == seat_x11->keyboard_id))
{
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
seat_x11->has_touchscreens |=
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
}
else
{
......@@ -663,18 +684,38 @@ add_device (MetaSeatX11 *seat_x11,
}
}
update_touch_mode (seat_x11);
return device;
}
static gboolean
has_touchscreens (MetaSeatX11 *seat_x11)
{
GList *l;
for (l = seat_x11->devices; l; l = l->next)
{
if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE)
return TRUE;
}
return FALSE;
}
static void
remove_device (MetaSeatX11 *seat_x11,
int device_id)
{
ClutterInputDevice *device;
gboolean check_touchscreens = FALSE;
device = g_hash_table_lookup (seat_x11->devices_by_id,
GINT_TO_POINTER (device_id));
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
check_touchscreens = TRUE;
if (device != NULL)
{
if (seat_x11->core_pointer == device)
......@@ -695,6 +736,12 @@ remove_device (MetaSeatX11 *seat_x11,
g_hash_table_remove (seat_x11->devices_by_id,
GINT_TO_POINTER (device_id));
}
if (check_touchscreens)
{
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
update_touch_mode (seat_x11);
}
}
static void
......@@ -1272,6 +1319,7 @@ meta_seat_x11_set_property (GObject *object,
case PROP_KEYBOARD_ID:
seat_x11->keyboard_id = g_value_get_int (value);
break;
case PROP_TOUCH_MODE:
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
......@@ -1296,6 +1344,9 @@ meta_seat_x11_get_property (GObject *object,
case PROP_KEYBOARD_ID:
g_value_set_int (value, seat_x11->keyboard_id);
break;
case PROP_TOUCH_MODE:
g_value_set_boolean (value, seat_x11->touch_mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
......@@ -1547,6 +1598,9 @@ meta_seat_x11_class_init (MetaSeatX11Class *klass)
G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_properties (object_class, N_PROPS, props);
g_object_class_override_property (object_class, PROP_TOUCH_MODE,
"touch-mode");
}
static void
......
......@@ -26,15 +26,17 @@
#include <unistd.h>
#endif
#include "backends/x11/cm/meta-backend-x11-cm.h"
#include "backends/x11/cm/meta-renderer-x11-cm.h"
#include "backends/x11/meta-backend-x11.h"
#include "backends/x11/meta-seat-x11.h"
#include "backends/x11/meta-stage-x11.h"
#include "clutter/clutter-mutter.h"
#include "clutter/x11/clutter-x11.h"
#include "clutter/x11/clutter-backend-x11.h"
#include "cogl/cogl.h"
#include "core/display-private.h"
#include "meta/meta-x11-errors.h"
#include "meta-backend-x11.h"
#include "meta-seat-x11.h"
#include "meta-stage-x11.h"
#define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
......@@ -287,8 +289,6 @@ meta_stage_x11_unrealize (ClutterStageWindow *stage_window)
clutter_stage_window_parent_iface->unrealize (stage_window);
g_list_free (stage_x11->legacy_views);
g_clear_object (&stage_x11->legacy_view);
g_clear_pointer (&stage_x11->onscreen, cogl_object_unref);
}
......@@ -330,10 +330,13 @@ meta_stage_x11_realize (ClutterStageWindow *stage_window)
stage_cogl,
NULL);
if (stage_x11->legacy_view)
g_object_set (G_OBJECT (stage_x11->legacy_view),
"framebuffer", stage_x11->onscreen,
NULL);
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
{
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
meta_renderer_x11_cm_set_onscreen (renderer_x11_cm, stage_x11->onscreen);
}
/* We just created a window of the size of the actor. No need to fix
the size of the stage, just update it. */
......@@ -522,34 +525,13 @@ meta_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window)
return stage_x11->clipped_redraws_cool_off == 0;
}
static void
ensure_legacy_view (ClutterStageWindow *stage_window)
{
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
cairo_rectangle_int_t view_layout;
CoglFramebuffer *framebuffer;
if (stage_x11->legacy_view)
return;
_clutter_stage_window_get_geometry (stage_window, &view_layout);
framebuffer = COGL_FRAMEBUFFER (stage_x11->onscreen);
stage_x11->legacy_view = g_object_new (CLUTTER_TYPE_STAGE_VIEW_COGL,
"layout", &view_layout,
"framebuffer", framebuffer,
NULL);
stage_x11->legacy_views = g_list_append (stage_x11->legacy_views,
stage_x11->legacy_view);
}
static GList *
meta_stage_x11_get_views (ClutterStageWindow *stage_window)
{
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
ensure_legacy_view (stage_window);
return stage_x11->legacy_views;
return meta_renderer_get_views (renderer);
}
static int64_t
......@@ -581,6 +563,9 @@ meta_stage_x11_class_init (MetaStageX11Class *klass)
static void
meta_stage_x11_init (MetaStageX11 *stage)
{
MetaRenderer *renderer;
MetaRendererX11Cm *renderer_x11_cm;
stage->xwin = None;
stage->xwin_width = 640;
stage->xwin_height = 480;
......@@ -591,6 +576,19 @@ meta_stage_x11_init (MetaStageX11 *stage)
stage->accept_focus = TRUE;
stage->title = NULL;
stage->backend = meta_get_backend ();
g_assert (stage->backend);
if (META_IS_BACKEND_X11_CM (stage->backend))
{
renderer = meta_backend_get_renderer (stage->backend);
renderer_x11_cm = META_RENDERER_X11_CM (renderer);
meta_renderer_x11_cm_ensure_screen_view (renderer_x11_cm,
stage->xwin_width,
stage->xwin_height);
}
}
static void
......@@ -778,16 +776,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
* X11 compositing manager, we need to reset the legacy
* stage view, now that it has a new size.
*/
if (stage_x11->legacy_view)
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
{
cairo_rectangle_int_t view_layout = {
.width = stage_width,
.height = stage_height
};
g_object_set (G_OBJECT (stage_x11->legacy_view),
"layout", &view_layout,
NULL);
MetaBackend *backend = stage_x11->backend;
MetaRenderer *renderer = meta_backend_get_renderer (backend);
MetaRendererX11Cm *renderer_x11_cm =
META_RENDERER_X11_CM (renderer);
meta_renderer_x11_cm_resize (renderer_x11_cm,
stage_width,
stage_height);
}
}
}
......