Compare commits
44 Commits
3.36.3
...
cherry-pic
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1fd53c480f | ||
![]() |
0c6ac287e6 | ||
![]() |
e8052f169b | ||
![]() |
449fa7bf81 | ||
![]() |
2d899596e2 | ||
![]() |
cf88d64882 | ||
![]() |
92db8902d9 | ||
![]() |
b1d45820ef | ||
![]() |
d07335cd4c | ||
![]() |
d03deb006c | ||
![]() |
c2146b457e | ||
![]() |
77dc3a5065 | ||
![]() |
454875248a | ||
![]() |
ae8acc9980 | ||
![]() |
86d9cd1a66 | ||
![]() |
3a70ba7ae2 | ||
![]() |
36a6235f3a | ||
![]() |
9b349cb25b | ||
![]() |
a83d83f087 | ||
![]() |
b8bd39793a | ||
![]() |
70072c39dd | ||
![]() |
bb4bd4b5c0 | ||
![]() |
ef848f10d1 | ||
![]() |
59cb259fdd | ||
![]() |
76e4b5de7a | ||
![]() |
9acb823603 | ||
![]() |
d721750417 | ||
![]() |
1ec91cc8ee | ||
![]() |
5c7b5ef0d9 | ||
![]() |
e98e1c13dd | ||
![]() |
8b69e7902a | ||
![]() |
b52a0be288 | ||
![]() |
1eb0812f0a | ||
![]() |
b98125a330 | ||
![]() |
78248d8dd3 | ||
![]() |
849d8dfae9 | ||
![]() |
1f896c9735 | ||
![]() |
cc617b059c | ||
![]() |
44a3358125 | ||
![]() |
81deb99435 | ||
![]() |
f25417efcf | ||
![]() |
ecc2b91016 | ||
![]() |
b002343dca | ||
![]() |
0d9ded403f |
20
NEWS
20
NEWS
@@ -1,3 +1,23 @@
|
||||
3.36.4
|
||||
======
|
||||
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
|
||||
* Do not paint textures of fully obscured windows [Robert; !1326]
|
||||
* Turn off CRTCs as well when enabling DPMS [Michel; !1240]
|
||||
* Improve selection support
|
||||
[Robert, Carlos, Sebastian; !1330, !1193, !1253, !1255, !1293, !1350]
|
||||
* Use a more appropriate combine function on opaque areas [Daniel; !1331]
|
||||
* Fix remote desktop being broken without screencast session [Olivier; #1307]
|
||||
* Fix popovers disappearing on wayland and HiDPI [Robert; #1312]
|
||||
* Fixed crashes [Jonas Å.; !1317]
|
||||
* Plugged memory leaks [Jonas Å.; !1283]
|
||||
* Misc. bug fixes and cleanups
|
||||
[Corentin, Sebastian, Jonas Å., Jonas D.; !1314, !1321, !1295, !1333]
|
||||
|
||||
Contributors:
|
||||
Jonas Dreßler, Michel Dänzer, Olivier Fourdan, Carlos Garnacho,
|
||||
Sebastian Keller, Robert Mader, Corentin Noël, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
|
||||
3.36.3
|
||||
======
|
||||
* Broadcast clipboard/primary offers [Carlos; !1262]
|
||||
|
@@ -475,8 +475,10 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
||||
ClutterActor *child;
|
||||
gint n_children = 0;
|
||||
gfloat minimum, natural;
|
||||
float largest_min_size, largest_nat_size;
|
||||
|
||||
minimum = natural = 0;
|
||||
largest_min_size = largest_nat_size = 0;
|
||||
|
||||
clutter_actor_iter_init (&iter, container);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
@@ -491,8 +493,22 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
||||
get_child_size (child, priv->orientation,
|
||||
for_size, &child_min, &child_nat);
|
||||
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
largest_min_size = MAX (largest_min_size, child_min);
|
||||
largest_nat_size = MAX (largest_nat_size, child_nat);
|
||||
}
|
||||
else
|
||||
{
|
||||
minimum += child_min;
|
||||
natural += child_nat;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->is_homogeneous)
|
||||
{
|
||||
minimum = largest_min_size * n_children;
|
||||
natural = largest_nat_size * n_children;
|
||||
}
|
||||
|
||||
if (n_children > 1)
|
||||
@@ -623,6 +639,8 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
size -= (nvis_children - 1) * priv->spacing;
|
||||
|
||||
/* Bring children up to size first */
|
||||
if (isnormal (size) || size == 0)
|
||||
{
|
||||
|
@@ -24,7 +24,7 @@ typedef enum _ClutterPaintFlag
|
||||
{
|
||||
CLUTTER_PAINT_FLAG_NONE = 0,
|
||||
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
|
||||
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 0,
|
||||
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 1,
|
||||
} ClutterPaintFlag;
|
||||
|
||||
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||
|
@@ -4526,8 +4526,8 @@ clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||
CoglFramebuffer *framebuffer;
|
||||
CoglBitmap *bitmap;
|
||||
|
||||
texture_width = (int) ceilf (rect->width * scale);
|
||||
texture_height = (int) ceilf (rect->height * scale);
|
||||
texture_width = (int) roundf (rect->width * scale);
|
||||
texture_height = (int) roundf (rect->height * scale);
|
||||
texture = cogl_texture_2d_new_with_size (cogl_context,
|
||||
texture_width,
|
||||
texture_height);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.36.3',
|
||||
version: '3.36.4',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
@@ -273,14 +273,6 @@ meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -591,6 +583,15 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
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;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
@@ -628,6 +629,14 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
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;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
@@ -666,6 +675,15 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
|
||||
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||
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;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_session_get_stream (session->screen_cast_session,
|
||||
stream_path);
|
||||
if (!stream)
|
||||
|
@@ -121,8 +121,10 @@ stage_painted (MetaStage *stage,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static MetaBackend *
|
||||
@@ -181,6 +183,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||
ClutterStage *stage = get_stage (monitor_src);
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
if (!is_cursor_in_stream (monitor_src))
|
||||
return;
|
||||
@@ -188,7 +191,11 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||
if (clutter_stage_is_redraw_queued (stage))
|
||||
return;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
if (meta_screen_cast_stream_src_pending_follow_up_frame (src))
|
||||
return;
|
||||
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -362,8 +369,9 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data)
|
||||
meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||
@@ -372,9 +380,6 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
|
||||
stage = get_stage (monitor_src);
|
||||
if (!clutter_stage_is_redraw_queued (stage))
|
||||
return FALSE;
|
||||
|
||||
monitor = get_monitor (monitor_src);
|
||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
|
||||
@@ -383,8 +388,9 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer)
|
||||
meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||
@@ -408,7 +414,6 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
||||
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||
{
|
||||
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
|
||||
g_autoptr (GError) error = NULL;
|
||||
CoglFramebuffer *view_framebuffer;
|
||||
MetaRectangle view_layout;
|
||||
int x, y;
|
||||
@@ -429,12 +434,8 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
||||
x, y,
|
||||
cogl_framebuffer_get_width (view_framebuffer),
|
||||
cogl_framebuffer_get_height (view_framebuffer),
|
||||
&error))
|
||||
{
|
||||
g_warning ("Error blitting view into DMABuf framebuffer: %s",
|
||||
error->message);
|
||||
return FALSE;
|
||||
}
|
||||
error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cogl_framebuffer_finish (framebuffer);
|
||||
@@ -442,6 +443,44 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src)
|
||||
{
|
||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||
MetaBackend *backend = get_backend (monitor_src);
|
||||
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||
ClutterStage *stage = get_stage (monitor_src);
|
||||
MetaMonitor *monitor;
|
||||
MetaLogicalMonitor *logical_monitor;
|
||||
MetaRectangle logical_monitor_layout;
|
||||
GList *l;
|
||||
|
||||
monitor = get_monitor (monitor_src);
|
||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
||||
|
||||
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||
{
|
||||
MetaRendererView *view = l->data;
|
||||
MetaRectangle view_layout;
|
||||
MetaRectangle damage;
|
||||
|
||||
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
|
||||
|
||||
if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
|
||||
continue;
|
||||
|
||||
damage = (cairo_rectangle_int_t) {
|
||||
.x = view_layout.x,
|
||||
.y = view_layout.y,
|
||||
.width = 1,
|
||||
.height = 1,
|
||||
};
|
||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &damage);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||
struct spa_meta_cursor *spa_meta_cursor)
|
||||
@@ -562,9 +601,12 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
|
||||
src_class->get_specs = meta_screen_cast_monitor_stream_src_get_specs;
|
||||
src_class->enable = meta_screen_cast_monitor_stream_src_enable;
|
||||
src_class->disable = meta_screen_cast_monitor_stream_src_disable;
|
||||
src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame;
|
||||
src_class->blit_to_framebuffer =
|
||||
meta_screen_cast_monitor_stream_src_blit_to_framebuffer;
|
||||
src_class->record_to_buffer =
|
||||
meta_screen_cast_monitor_stream_src_record_to_buffer;
|
||||
src_class->record_to_framebuffer =
|
||||
meta_screen_cast_monitor_stream_src_record_to_framebuffer;
|
||||
src_class->record_follow_up =
|
||||
meta_screen_cast_monitor_stream_record_follow_up;
|
||||
src_class->set_cursor_metadata =
|
||||
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
|
||||
}
|
||||
|
@@ -91,7 +91,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
||||
struct spa_video_info_raw video_format;
|
||||
int video_stride;
|
||||
|
||||
uint64_t last_frame_timestamp_us;
|
||||
int64_t last_frame_timestamp_us;
|
||||
guint follow_up_frame_source_id;
|
||||
|
||||
GHashTable *dmabuf_handles;
|
||||
|
||||
@@ -109,6 +110,12 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
|
||||
meta_screen_cast_stream_src_init_initable_iface)
|
||||
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
||||
|
||||
static inline uint32_t
|
||||
us2ms (uint64_t us)
|
||||
{
|
||||
return (uint32_t) (us / 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
||||
int *width,
|
||||
@@ -135,23 +142,34 @@ meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data)
|
||||
meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastStreamSrcClass *klass =
|
||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||
|
||||
return klass->record_frame (src, data);
|
||||
return klass->record_to_buffer (src, data, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer)
|
||||
meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastStreamSrcClass *klass =
|
||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||
|
||||
return klass->blit_to_framebuffer (src, framebuffer);
|
||||
return klass->record_to_framebuffer (src, framebuffer, error);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_stream_src_record_follow_up (MetaScreenCastStreamSrc *src)
|
||||
{
|
||||
MetaScreenCastStreamSrcClass *klass =
|
||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||
|
||||
klass->record_follow_up (src);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -409,9 +427,10 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
do_record_frame (MetaScreenCastStreamSrc *src,
|
||||
struct spa_buffer *spa_buffer,
|
||||
uint8_t *data)
|
||||
do_record_frame (MetaScreenCastStreamSrc *src,
|
||||
struct spa_buffer *spa_buffer,
|
||||
uint8_t *data,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
@@ -419,7 +438,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
|
||||
if (spa_buffer->datas[0].data ||
|
||||
spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
||||
{
|
||||
return meta_screen_cast_stream_src_record_frame (src, data);
|
||||
return meta_screen_cast_stream_src_record_to_buffer (src, data, error);
|
||||
}
|
||||
else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||
{
|
||||
@@ -429,14 +448,56 @@ do_record_frame (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *dmabuf_fbo =
|
||||
cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
|
||||
|
||||
return meta_screen_cast_stream_src_blit_to_framebuffer (src, dmabuf_fbo);
|
||||
return meta_screen_cast_stream_src_record_to_framebuffer (src,
|
||||
dmabuf_fbo,
|
||||
error);
|
||||
}
|
||||
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Unknown SPA buffer type %u", spa_buffer->datas[0].type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src)
|
||||
{
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
|
||||
return priv->follow_up_frame_source_id != 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
follow_up_frame_cb (gpointer user_data)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = user_data;
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
|
||||
priv->follow_up_frame_source_id = 0;
|
||||
meta_screen_cast_stream_src_record_follow_up (src);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src,
|
||||
int64_t timeout_us)
|
||||
{
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
|
||||
if (priv->follow_up_frame_source_id)
|
||||
return;
|
||||
|
||||
priv->follow_up_frame_source_id = g_timeout_add (us2ms (timeout_us),
|
||||
follow_up_frame_cb,
|
||||
src);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
||||
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
|
||||
MetaScreenCastRecordFlag flags)
|
||||
{
|
||||
MetaScreenCastStreamSrcPrivate *priv =
|
||||
meta_screen_cast_stream_src_get_instance_private (src);
|
||||
@@ -445,14 +506,29 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
||||
struct spa_buffer *spa_buffer;
|
||||
uint8_t *data = NULL;
|
||||
uint64_t now_us;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
now_us = g_get_monotonic_time ();
|
||||
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)))
|
||||
return;
|
||||
priv->last_frame_timestamp_us != 0)
|
||||
{
|
||||
int64_t min_interval_us;
|
||||
int64_t time_since_last_frame_us;
|
||||
|
||||
min_interval_us =
|
||||
((G_USEC_PER_SEC * priv->video_format.max_framerate.denom) /
|
||||
priv->video_format.max_framerate.num);
|
||||
|
||||
time_since_last_frame_us = now_us - priv->last_frame_timestamp_us;
|
||||
if (time_since_last_frame_us < min_interval_us)
|
||||
{
|
||||
int64_t timeout_us;
|
||||
|
||||
timeout_us = min_interval_us - time_since_last_frame_us;
|
||||
maybe_schedule_follow_up_frame (src, timeout_us);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!priv->pipewire_stream)
|
||||
return;
|
||||
@@ -470,34 +546,43 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
||||
return;
|
||||
}
|
||||
|
||||
if (do_record_frame (src, spa_buffer, data))
|
||||
if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY))
|
||||
{
|
||||
struct spa_meta_region *spa_meta_video_crop;
|
||||
|
||||
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
||||
spa_buffer->datas[0].chunk->stride = priv->video_stride;
|
||||
|
||||
/* Update VideoCrop if needed */
|
||||
spa_meta_video_crop =
|
||||
spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
|
||||
sizeof (*spa_meta_video_crop));
|
||||
if (spa_meta_video_crop)
|
||||
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||
if (do_record_frame (src, spa_buffer, data, &error))
|
||||
{
|
||||
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||
struct spa_meta_region *spa_meta_video_crop;
|
||||
|
||||
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
||||
spa_buffer->datas[0].chunk->stride = priv->video_stride;
|
||||
|
||||
/* Update VideoCrop if needed */
|
||||
spa_meta_video_crop =
|
||||
spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
|
||||
sizeof (*spa_meta_video_crop));
|
||||
if (spa_meta_video_crop)
|
||||
{
|
||||
spa_meta_video_crop->region.position.x = crop_rect.x;
|
||||
spa_meta_video_crop->region.position.y = crop_rect.y;
|
||||
spa_meta_video_crop->region.size.width = crop_rect.width;
|
||||
spa_meta_video_crop->region.size.height = crop_rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
spa_meta_video_crop->region.position.x = 0;
|
||||
spa_meta_video_crop->region.position.y = 0;
|
||||
spa_meta_video_crop->region.size.width = priv->stream_width;
|
||||
spa_meta_video_crop->region.size.height = priv->stream_height;
|
||||
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||
{
|
||||
spa_meta_video_crop->region.position.x = crop_rect.x;
|
||||
spa_meta_video_crop->region.position.y = crop_rect.y;
|
||||
spa_meta_video_crop->region.size.width = crop_rect.width;
|
||||
spa_meta_video_crop->region.size.height = crop_rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
spa_meta_video_crop->region.position.x = 0;
|
||||
spa_meta_video_crop->region.position.y = 0;
|
||||
spa_meta_video_crop->region.size.width = priv->stream_width;
|
||||
spa_meta_video_crop->region.size.height = priv->stream_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_warning ("Failed to record screen cast frame: %s", error->message);
|
||||
spa_buffer->datas[0].chunk->size = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -539,6 +624,8 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
|
||||
|
||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src);
|
||||
|
||||
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||
|
||||
priv->is_enabled = FALSE;
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,12 @@
|
||||
|
||||
typedef struct _MetaScreenCastStream MetaScreenCastStream;
|
||||
|
||||
typedef enum _MetaScreenCastRecordFlag
|
||||
{
|
||||
META_SCREEN_CAST_RECORD_FLAG_NONE = 0,
|
||||
META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY = 1 << 0,
|
||||
} MetaScreenCastRecordFlag;
|
||||
|
||||
#define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc,
|
||||
meta_screen_cast_stream_src,
|
||||
@@ -53,17 +59,24 @@ struct _MetaScreenCastStreamSrcClass
|
||||
float *frame_rate);
|
||||
void (* enable) (MetaScreenCastStreamSrc *src);
|
||||
void (* disable) (MetaScreenCastStreamSrc *src);
|
||||
gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data);
|
||||
gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer);
|
||||
gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data,
|
||||
GError **error);
|
||||
gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer,
|
||||
GError **error);
|
||||
void (* record_follow_up) (MetaScreenCastStreamSrc *src);
|
||||
|
||||
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
|
||||
MetaRectangle *crop_rect);
|
||||
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
|
||||
struct spa_meta_cursor *spa_meta_cursor);
|
||||
};
|
||||
|
||||
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
|
||||
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
|
||||
MetaScreenCastRecordFlag flags);
|
||||
|
||||
gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src);
|
||||
|
||||
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
|
||||
|
||||
|
@@ -327,8 +327,10 @@ screen_cast_window_damaged (MetaWindowActor *actor,
|
||||
MetaScreenCastWindowStreamSrc *window_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -365,6 +367,7 @@ static void
|
||||
sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
||||
{
|
||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
if (!is_cursor_in_stream (window_src))
|
||||
return;
|
||||
@@ -372,7 +375,8 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
||||
if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
|
||||
return;
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -401,6 +405,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
MetaWindowActor *window_actor;
|
||||
MetaScreenCastStream *stream;
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
window_actor = meta_window_actor_from_window (get_window (window_src));
|
||||
if (!window_actor)
|
||||
@@ -438,7 +443,8 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
||||
break;
|
||||
}
|
||||
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -451,8 +457,9 @@ meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data)
|
||||
meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||
uint8_t *data,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastWindowStreamSrc *window_src =
|
||||
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||
@@ -463,8 +470,9 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer)
|
||||
meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||
CoglFramebuffer *framebuffer,
|
||||
GError **error)
|
||||
{
|
||||
MetaScreenCastWindowStreamSrc *window_src =
|
||||
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||
@@ -477,9 +485,13 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
||||
stream_rect.height = get_stream_height (window_src);
|
||||
|
||||
if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
||||
&stream_rect,
|
||||
framebuffer))
|
||||
return FALSE;
|
||||
&stream_rect,
|
||||
framebuffer))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Failed to blit window content to framebuffer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
stream = meta_screen_cast_stream_src_get_stream (src);
|
||||
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
||||
@@ -497,6 +509,15 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src)
|
||||
{
|
||||
MetaScreenCastRecordFlag flags;
|
||||
|
||||
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
|
||||
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||
struct spa_meta_cursor *spa_meta_cursor)
|
||||
@@ -580,9 +601,12 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas
|
||||
src_class->get_specs = meta_screen_cast_window_stream_src_get_specs;
|
||||
src_class->enable = meta_screen_cast_window_stream_src_enable;
|
||||
src_class->disable = meta_screen_cast_window_stream_src_disable;
|
||||
src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
|
||||
src_class->blit_to_framebuffer =
|
||||
meta_screen_cast_window_stream_src_blit_to_framebuffer;
|
||||
src_class->record_to_buffer =
|
||||
meta_screen_cast_window_stream_src_record_to_buffer;
|
||||
src_class->record_to_framebuffer =
|
||||
meta_screen_cast_window_stream_src_record_to_framebuffer;
|
||||
src_class->record_follow_up =
|
||||
meta_screen_cast_window_stream_record_follow_up;
|
||||
src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
|
||||
src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
|
||||
}
|
||||
|
@@ -232,14 +232,28 @@ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
|
||||
uint64_t state,
|
||||
MetaKmsUpdate *kms_update)
|
||||
{
|
||||
MetaGpu *gpu = META_GPU (gpu_kms);
|
||||
GList *l;
|
||||
|
||||
for (l = meta_gpu_get_outputs (META_GPU (gpu_kms)); l; l = l->next)
|
||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaOutput *output = l->data;
|
||||
|
||||
meta_output_kms_set_power_save_mode (output, state, kms_update);
|
||||
}
|
||||
|
||||
if (state != META_POWER_SAVE_ON)
|
||||
{
|
||||
/* Turn off CRTCs for DPMS */
|
||||
for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
|
||||
{
|
||||
MetaCrtc *crtc = META_CRTC (l->data);
|
||||
|
||||
meta_kms_update_mode_set (kms_update,
|
||||
meta_crtc_kms_get_kms_crtc (crtc),
|
||||
NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@@ -2146,6 +2146,7 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
{
|
||||
CoglFramebuffer *dmabuf_fb;
|
||||
CoglDmaBufHandle *dmabuf_handle;
|
||||
struct gbm_bo *new_bo;
|
||||
int dmabuf_fd = -1;
|
||||
|
||||
@@ -2182,8 +2183,11 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
|
||||
if (!dmabuf_fb)
|
||||
return NULL;
|
||||
|
||||
return cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
|
||||
(GDestroyNotify) gbm_bo_destroy);
|
||||
dmabuf_handle =
|
||||
cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
|
||||
(GDestroyNotify) gbm_bo_destroy);
|
||||
cogl_object_unref (dmabuf_fb);
|
||||
return dmabuf_handle;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
|
@@ -843,12 +843,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
|
||||
g_debug ("Client message for stage, win:0x%x",
|
||||
(unsigned int) xevent->xany.window);
|
||||
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@@ -66,4 +66,7 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
int meta_shaped_texture_get_width (MetaShapedTexture *stex);
|
||||
int meta_shaped_texture_get_height (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
#endif
|
||||
|
@@ -87,6 +87,9 @@ struct _MetaShapedTexture
|
||||
/* The region containing only fully opaque pixels */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
/* MetaCullable regions, see that documentation for more details */
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
gboolean size_invalid;
|
||||
MetaMonitorTransform transform;
|
||||
gboolean has_viewport_src_rect;
|
||||
@@ -214,6 +217,15 @@ ensure_size_valid (MetaShapedTexture *stex)
|
||||
update_size (stex);
|
||||
}
|
||||
|
||||
void
|
||||
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
g_clear_pointer (&stex->clip_region, cairo_region_destroy);
|
||||
if (clip_region)
|
||||
stex->clip_region = cairo_region_reference (clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
|
||||
{
|
||||
@@ -239,6 +251,7 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
|
||||
g_clear_pointer (&stex->clip_region, cairo_region_destroy);
|
||||
|
||||
g_clear_pointer (&stex->snippet, cogl_object_unref);
|
||||
|
||||
@@ -390,17 +403,14 @@ get_unblended_pipeline (MetaShapedTexture *stex,
|
||||
CoglContext *ctx)
|
||||
{
|
||||
CoglPipeline *pipeline;
|
||||
CoglColor color;
|
||||
|
||||
if (stex->unblended_pipeline)
|
||||
return stex->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);
|
||||
cogl_pipeline_set_layer_combine (pipeline, 0,
|
||||
"RGBA = REPLACE (TEXTURE)",
|
||||
NULL);
|
||||
|
||||
stex->unblended_pipeline = pipeline;
|
||||
|
||||
@@ -585,12 +595,19 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
|
||||
if (use_opaque_region)
|
||||
{
|
||||
blended_tex_region = cairo_region_create_rectangle (&content_rect);
|
||||
if (stex->clip_region)
|
||||
blended_tex_region = cairo_region_copy (stex->clip_region);
|
||||
else
|
||||
blended_tex_region = cairo_region_create_rectangle (&content_rect);
|
||||
|
||||
cairo_region_subtract (blended_tex_region, stex->opaque_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
blended_tex_region = NULL;
|
||||
if (stex->clip_region)
|
||||
blended_tex_region = cairo_region_reference (stex->clip_region);
|
||||
else
|
||||
blended_tex_region = NULL;
|
||||
}
|
||||
|
||||
/* Limit to how many separate rectangles we'll draw; beyond this just
|
||||
@@ -612,10 +629,21 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
/* First, paint the unblended parts, which are part of the opaque region. */
|
||||
if (use_opaque_region)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
int n_rects;
|
||||
int i;
|
||||
|
||||
if (!cairo_region_is_empty (stex->opaque_region))
|
||||
if (stex->clip_region)
|
||||
{
|
||||
region = cairo_region_copy (stex->clip_region);
|
||||
cairo_region_intersect (region, stex->opaque_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
region = cairo_region_reference (stex->opaque_region);
|
||||
}
|
||||
|
||||
if (!cairo_region_is_empty (region))
|
||||
{
|
||||
CoglPipeline *opaque_pipeline;
|
||||
|
||||
@@ -623,16 +651,18 @@ do_paint_content (MetaShapedTexture *stex,
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (stex->opaque_region);
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_region_get_rectangle (stex->opaque_region, i, &rect);
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
paint_clipped_rectangle_node (stex, root_node,
|
||||
opaque_pipeline,
|
||||
&rect, alloc);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
/* Now, go ahead and paint the blended parts. */
|
||||
@@ -757,6 +787,9 @@ meta_shaped_texture_paint_content (ClutterContent *content,
|
||||
CoglTexture *paint_tex = NULL;
|
||||
uint8_t opacity;
|
||||
|
||||
if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
|
||||
return;
|
||||
|
||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||
* used together with SGIS_generate_mipmap, however this is very
|
||||
* rarely supported. Also, even when it is supported there
|
||||
|
@@ -34,7 +34,6 @@ typedef struct _MetaSurfaceActorPrivate
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* MetaCullable regions, see that documentation for more details */
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *unobscured_region;
|
||||
|
||||
/* Freeze/thaw accounting */
|
||||
@@ -58,6 +57,12 @@ enum
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IN_STAGE_PERSPECTIVE,
|
||||
IN_ACTOR_PERSPECTIVE
|
||||
} ScalePerspectiveType;
|
||||
|
||||
static cairo_region_t *
|
||||
effective_unobscured_region (MetaSurfaceActor *surface_actor)
|
||||
{
|
||||
@@ -79,18 +84,39 @@ effective_unobscured_region (MetaSurfaceActor *surface_actor)
|
||||
}
|
||||
|
||||
static cairo_region_t*
|
||||
get_scaled_region (MetaSurfaceActor *surface_actor,
|
||||
cairo_region_t *region)
|
||||
get_scaled_region (MetaSurfaceActor *surface_actor,
|
||||
cairo_region_t *region,
|
||||
ScalePerspectiveType scale_perspective)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
cairo_region_t *scaled_region;
|
||||
int geometry_scale;
|
||||
float x, y;
|
||||
|
||||
window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor));
|
||||
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||
|
||||
return meta_region_scale_double (region,
|
||||
1.0 / geometry_scale,
|
||||
META_ROUNDING_STRATEGY_GROW);
|
||||
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
||||
cairo_region_translate (region, x, y);
|
||||
|
||||
switch (scale_perspective)
|
||||
{
|
||||
case IN_STAGE_PERSPECTIVE:
|
||||
scaled_region = meta_region_scale_double (region,
|
||||
geometry_scale,
|
||||
META_ROUNDING_STRATEGY_GROW);
|
||||
break;
|
||||
case IN_ACTOR_PERSPECTIVE:
|
||||
scaled_region = meta_region_scale_double (region,
|
||||
1.0 / geometry_scale,
|
||||
META_ROUNDING_STRATEGY_GROW);
|
||||
break;
|
||||
}
|
||||
|
||||
cairo_region_translate (region, -x, -y);
|
||||
cairo_region_translate (scaled_region, -x, -y);
|
||||
|
||||
return scaled_region;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -120,8 +146,9 @@ set_unobscured_region (MetaSurfaceActor *surface_actor,
|
||||
.height = height,
|
||||
};
|
||||
|
||||
priv->unobscured_region =
|
||||
get_scaled_region (surface_actor, unobscured_region);
|
||||
priv->unobscured_region = get_scaled_region (surface_actor,
|
||||
unobscured_region,
|
||||
IN_ACTOR_PERSPECTIVE);
|
||||
|
||||
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
|
||||
}
|
||||
@@ -134,30 +161,23 @@ set_clip_region (MetaSurfaceActor *surface_actor,
|
||||
{
|
||||
MetaSurfaceActorPrivate *priv =
|
||||
meta_surface_actor_get_instance_private (surface_actor);
|
||||
MetaShapedTexture *stex = priv->texture;
|
||||
|
||||
g_clear_pointer (&priv->clip_region, cairo_region_destroy);
|
||||
if (clip_region)
|
||||
if (clip_region && !cairo_region_is_empty (clip_region))
|
||||
{
|
||||
if (cairo_region_is_empty (clip_region))
|
||||
priv->clip_region = cairo_region_reference (clip_region);
|
||||
else
|
||||
priv->clip_region = get_scaled_region (surface_actor, clip_region);
|
||||
cairo_region_t *region;
|
||||
|
||||
region = get_scaled_region (surface_actor,
|
||||
clip_region,
|
||||
IN_ACTOR_PERSPECTIVE);
|
||||
meta_shaped_texture_set_clip_region (stex, region);
|
||||
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_shaped_texture_set_clip_region (stex, clip_region);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_paint (ClutterActor *actor,
|
||||
ClutterPaintContext *paint_context)
|
||||
{
|
||||
MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (actor);
|
||||
MetaSurfaceActorPrivate *priv =
|
||||
meta_surface_actor_get_instance_private (surface_actor);
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->paint (actor,
|
||||
paint_context);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -227,7 +247,6 @@ meta_surface_actor_dispose (GObject *object)
|
||||
g_clear_object (&priv->texture);
|
||||
|
||||
set_unobscured_region (self, NULL);
|
||||
set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -239,7 +258,6 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->paint = meta_surface_actor_paint;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
actor_class->get_paint_volume = meta_surface_actor_get_paint_volume;
|
||||
|
||||
@@ -279,11 +297,8 @@ meta_surface_actor_cull_out (MetaCullable *cullable,
|
||||
|
||||
if (opacity == 0xff)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
cairo_region_t *scaled_opaque_region;
|
||||
cairo_region_t *opaque_region;
|
||||
int geometry_scale;
|
||||
float x, y;
|
||||
cairo_region_t *scaled_opaque_region;
|
||||
|
||||
opaque_region = meta_shaped_texture_get_opaque_region (priv->texture);
|
||||
if (opaque_region)
|
||||
@@ -306,14 +321,9 @@ meta_surface_actor_cull_out (MetaCullable *cullable,
|
||||
return;
|
||||
}
|
||||
|
||||
window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor));
|
||||
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
||||
|
||||
cairo_region_translate (opaque_region, x, y);
|
||||
scaled_opaque_region = meta_region_scale (opaque_region, geometry_scale);
|
||||
cairo_region_translate (scaled_opaque_region, -x, -y);
|
||||
cairo_region_translate (opaque_region, -x, -y);
|
||||
scaled_opaque_region = get_scaled_region (surface_actor,
|
||||
opaque_region,
|
||||
IN_STAGE_PERSPECTIVE);
|
||||
|
||||
if (unobscured_region)
|
||||
cairo_region_subtract (unobscured_region, scaled_opaque_region);
|
||||
|
@@ -1630,8 +1630,8 @@ meta_window_actor_x11_init (MetaWindowActorX11 *self)
|
||||
|
||||
self->shadow_factory = meta_shadow_factory_get_default ();
|
||||
self->shadow_factory_changed_handler_id =
|
||||
g_signal_connect (self->shadow_factory,
|
||||
"changed",
|
||||
G_CALLBACK (invalidate_shadow),
|
||||
self);
|
||||
g_signal_connect_swapped (self->shadow_factory,
|
||||
"changed",
|
||||
G_CALLBACK (invalidate_shadow),
|
||||
self);
|
||||
}
|
||||
|
@@ -152,6 +152,7 @@ owner_changed_cb (MetaSelection *selection,
|
||||
display->saved_clipboard);
|
||||
g_set_object (&display->selection_source, new_owner);
|
||||
meta_selection_set_owner (selection, selection_type, new_owner);
|
||||
g_object_unref (new_owner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +171,7 @@ meta_clipboard_manager_shutdown (MetaDisplay *display)
|
||||
{
|
||||
MetaSelection *selection;
|
||||
|
||||
g_clear_object (&display->selection_source);
|
||||
g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
|
||||
g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
|
||||
selection = meta_display_get_selection (display);
|
||||
|
@@ -495,7 +495,22 @@ if have_wayland
|
||||
'wayland/meta-wayland-cursor-surface.h',
|
||||
'wayland/meta-wayland-data-device.c',
|
||||
'wayland/meta-wayland-data-device.h',
|
||||
'wayland/meta-wayland-data-device-private.h',
|
||||
'wayland/meta-wayland-data-device-primary.c',
|
||||
'wayland/meta-wayland-data-device-primary.h',
|
||||
'wayland/meta-wayland-data-device-primary-legacy.c',
|
||||
'wayland/meta-wayland-data-device-primary-legacy.h',
|
||||
'wayland/meta-wayland-data-offer.c',
|
||||
'wayland/meta-wayland-data-offer.h',
|
||||
'wayland/meta-wayland-data-offer-primary.c',
|
||||
'wayland/meta-wayland-data-offer-primary.h',
|
||||
'wayland/meta-wayland-data-offer-primary-legacy.c',
|
||||
'wayland/meta-wayland-data-offer-primary-legacy.h',
|
||||
'wayland/meta-wayland-data-source.c',
|
||||
'wayland/meta-wayland-data-source.h',
|
||||
'wayland/meta-wayland-data-source-primary.c',
|
||||
'wayland/meta-wayland-data-source-primary.h',
|
||||
'wayland/meta-wayland-data-source-primary-legacy.c',
|
||||
'wayland/meta-wayland-data-source-primary-legacy.h',
|
||||
'wayland/meta-wayland-dma-buf.c',
|
||||
'wayland/meta-wayland-dma-buf.h',
|
||||
'wayland/meta-wayland-dnd-surface.c',
|
||||
@@ -790,6 +805,7 @@ if have_wayland
|
||||
['linux-dmabuf', 'unstable', 'v1', ],
|
||||
['pointer-constraints', 'unstable', 'v1', ],
|
||||
['pointer-gestures', 'unstable', 'v1', ],
|
||||
['primary-selection', 'unstable', 'v1', ],
|
||||
['relative-pointer', 'unstable', 'v1', ],
|
||||
['tablet', 'unstable', 'v2', ],
|
||||
['text-input', 'unstable', 'v3', ],
|
||||
|
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "meta/meta-selection-source.h"
|
||||
#include "wayland/meta-wayland-data-device.h"
|
||||
#include "wayland/meta-wayland-data-device-private.h"
|
||||
|
||||
#define META_TYPE_SELECTION_SOURCE_WAYLAND (meta_selection_source_wayland_get_type ())
|
||||
|
||||
|
354
src/wayland/meta-wayland-data-device-primary-legacy.c
Normal file
354
src/wayland/meta-wayland-data-device-primary-legacy.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* The file is based on src/data-device.c from Weston */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "wayland/meta-wayland-data-device-primary-legacy.h"
|
||||
|
||||
#include "compositor/meta-dnd-actor-private.h"
|
||||
#include "meta/meta-selection-source-memory.h"
|
||||
#include "wayland/meta-selection-source-wayland-private.h"
|
||||
#include "wayland/meta-wayland-data-offer-primary-legacy.h"
|
||||
#include "wayland/meta-wayland-data-source-primary-legacy.h"
|
||||
#include "wayland/meta-wayland-dnd-surface.h"
|
||||
#include "wayland/meta-wayland-pointer.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
|
||||
#include "gtk-primary-selection-server-protocol.h"
|
||||
|
||||
static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device,
|
||||
struct wl_resource *target);
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination,
|
||||
struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
default_destructor (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
set_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device,
|
||||
MetaSelectionSource *selection_source)
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
meta_selection_set_owner (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
selection_source);
|
||||
g_set_object (&data_device->owner, selection_source);
|
||||
}
|
||||
|
||||
static void
|
||||
unset_selection_source (MetaWaylandDataDevicePrimaryLegacy *data_device)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (!data_device->owner)
|
||||
return;
|
||||
|
||||
meta_selection_unset_owner (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
data_device->owner);
|
||||
g_clear_object (&data_device->owner);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_source_destroyed (gpointer data,
|
||||
GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevicePrimaryLegacy *data_device = data;
|
||||
|
||||
data_device->data_source = NULL;
|
||||
unset_selection_source (data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_device_primary_legacy_set_selection (MetaWaylandDataDevicePrimaryLegacy *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (source));
|
||||
|
||||
if (data_device->data_source &&
|
||||
data_device->serial - serial < UINT32_MAX / 2)
|
||||
return;
|
||||
|
||||
if (data_device->data_source)
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (data_device->data_source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
}
|
||||
|
||||
data_device->data_source = source;
|
||||
data_device->serial = serial;
|
||||
|
||||
if (source)
|
||||
{
|
||||
meta_wayland_data_source_set_seat (source, seat);
|
||||
g_object_weak_ref (G_OBJECT (source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
|
||||
selection_source = meta_selection_source_wayland_new (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
|
||||
}
|
||||
|
||||
set_selection_source (data_device, selection_source);
|
||||
g_object_unref (selection_source);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_set_selection (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *source_resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandDataDevicePrimaryLegacy *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
|
||||
MetaWaylandDataSource *source = NULL;
|
||||
|
||||
if (source_resource)
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
meta_wayland_data_device_primary_legacy_set_selection (data_device, source, serial);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_device_interface primary_device_interface = {
|
||||
primary_device_set_selection,
|
||||
default_destructor,
|
||||
};
|
||||
|
||||
static void
|
||||
owner_changed_cb (MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner,
|
||||
MetaWaylandDataDevicePrimaryLegacy *data_device)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandSeat *seat = compositor->seat;
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
if (selection_type == META_SELECTION_PRIMARY)
|
||||
{
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
if (new_owner)
|
||||
{
|
||||
offer = create_and_send_primary_offer (data_device,
|
||||
data_device_resource);
|
||||
}
|
||||
|
||||
gtk_primary_selection_device_send_selection (data_device_resource,
|
||||
offer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimaryLegacy *data_device)
|
||||
{
|
||||
if (data_device->selection_owner_signal_id != 0)
|
||||
return;
|
||||
|
||||
data_device->selection_owner_signal_id =
|
||||
g_signal_connect (meta_display_get_selection (meta_get_display ()),
|
||||
"owner-changed",
|
||||
G_CALLBACK (owner_changed_cb), data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_manager_create_source (struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *source_resource;
|
||||
|
||||
source_resource =
|
||||
wl_resource_create (client, >k_primary_selection_source_interface,
|
||||
wl_resource_get_version (manager_resource),
|
||||
id);
|
||||
meta_wayland_data_source_primary_legacy_new (source_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_manager_get_device (struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
guint32 id,
|
||||
struct wl_resource *seat_resource)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
struct wl_resource *cr;
|
||||
|
||||
cr = wl_resource_create (client, >k_primary_selection_device_interface,
|
||||
wl_resource_get_version (manager_resource), id);
|
||||
wl_resource_set_implementation (cr, &primary_device_interface,
|
||||
&seat->primary_legacy_data_device, unbind_resource);
|
||||
wl_list_insert (&seat->primary_legacy_data_device.resource_list,
|
||||
wl_resource_get_link (cr));
|
||||
|
||||
ensure_owners_changed_handler_connected (&seat->primary_legacy_data_device);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_device_manager_interface primary_manager_interface = {
|
||||
primary_device_manager_create_source,
|
||||
primary_device_manager_get_device,
|
||||
default_destructor,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_primary_manager (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, >k_primary_selection_device_manager_interface,
|
||||
version, id);
|
||||
wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
>k_primary_selection_device_manager_interface,
|
||||
1, NULL, bind_primary_manager) == NULL)
|
||||
g_error ("Could not create data_device");
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
wl_list_init (&data_device->focus_resource_list);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
create_and_send_primary_offer (MetaWaylandDataDevicePrimaryLegacy *data_device,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
struct wl_resource *resource;
|
||||
GList *mimetypes, *l;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY);
|
||||
if (!mimetypes)
|
||||
return NULL;
|
||||
|
||||
offer = meta_wayland_data_offer_primary_legacy_new (target);
|
||||
resource = meta_wayland_data_offer_get_resource (offer);
|
||||
|
||||
gtk_primary_selection_device_send_data_offer (target, resource);
|
||||
|
||||
for (l = mimetypes; l; l = l->next)
|
||||
gtk_primary_selection_offer_send_offer (resource, l->data);
|
||||
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_legacy_data_device);
|
||||
struct wl_client *focus_client;
|
||||
struct wl_resource *data_device_resource;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
|
||||
if (focus_client == data_device->focus_client)
|
||||
return;
|
||||
|
||||
data_device->focus_client = focus_client;
|
||||
move_resources (&data_device->resource_list,
|
||||
&data_device->focus_resource_list);
|
||||
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
move_resources_for_client (&data_device->focus_resource_list,
|
||||
&data_device->resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
55
src/wayland/meta-wayland-data-device-primary-legacy.h
Normal file
55
src/wayland/meta-wayland-data-device-primary-legacy.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta/meta-selection-source.h"
|
||||
#include "wayland/meta-wayland-data-offer.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandDataDevicePrimaryLegacy
|
||||
{
|
||||
uint32_t serial;
|
||||
MetaWaylandDataSource *data_source;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
guint selection_owner_signal_id;
|
||||
|
||||
MetaSelectionSource *owner;
|
||||
};
|
||||
|
||||
void meta_wayland_data_device_primary_legacy_manager_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_data_device_primary_legacy_init (MetaWaylandDataDevicePrimaryLegacy *data_device);
|
||||
|
||||
void meta_wayland_data_device_primary_legacy_set_keyboard_focus (MetaWaylandDataDevicePrimaryLegacy *data_device);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_LEGACY_H */
|
353
src/wayland/meta-wayland-data-device-primary.c
Normal file
353
src/wayland/meta-wayland-data-device-primary.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* The file is based on src/data-device.c from Weston */
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "wayland/meta-wayland-data-device-primary.h"
|
||||
|
||||
#include "compositor/meta-dnd-actor-private.h"
|
||||
#include "meta/meta-selection-source-memory.h"
|
||||
#include "wayland/meta-selection-source-wayland-private.h"
|
||||
#include "wayland/meta-wayland-data-offer-primary.h"
|
||||
#include "wayland/meta-wayland-data-source-primary.h"
|
||||
#include "wayland/meta-wayland-dnd-surface.h"
|
||||
#include "wayland/meta-wayland-pointer.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
|
||||
#include "primary-selection-unstable-v1-server-protocol.h"
|
||||
|
||||
static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device,
|
||||
struct wl_resource *target);
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination,
|
||||
struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
}
|
||||
|
||||
static void
|
||||
default_destructor (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
set_selection_source (MetaWaylandDataDevicePrimary *data_device,
|
||||
MetaSelectionSource *selection_source)
|
||||
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
meta_selection_set_owner (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
selection_source);
|
||||
g_set_object (&data_device->owner, selection_source);
|
||||
}
|
||||
|
||||
static void
|
||||
unset_selection_source (MetaWaylandDataDevicePrimary *data_device)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
if (!data_device->owner)
|
||||
return;
|
||||
|
||||
meta_selection_unset_owner (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
data_device->owner);
|
||||
g_clear_object (&data_device->owner);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_source_destroyed (gpointer data,
|
||||
GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevicePrimary *data_device = data;
|
||||
|
||||
data_device->data_source = NULL;
|
||||
unset_selection_source (data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_device_primary_set_selection (MetaWaylandDataDevicePrimary *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source));
|
||||
|
||||
if (data_device->data_source &&
|
||||
data_device->serial - serial < UINT32_MAX / 2)
|
||||
return;
|
||||
|
||||
if (data_device->data_source)
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (data_device->data_source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
}
|
||||
|
||||
data_device->data_source = source;
|
||||
data_device->serial = serial;
|
||||
|
||||
if (source)
|
||||
{
|
||||
meta_wayland_data_source_set_seat (source, seat);
|
||||
g_object_weak_ref (G_OBJECT (source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
|
||||
selection_source = meta_selection_source_wayland_new (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
selection_source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
|
||||
}
|
||||
|
||||
set_selection_source (data_device, selection_source);
|
||||
g_object_unref (selection_source);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_set_selection (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
struct wl_resource *source_resource,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandDataDevicePrimary *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
|
||||
MetaWaylandDataSource *source = NULL;
|
||||
|
||||
if (source_resource)
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
meta_wayland_data_device_primary_set_selection (data_device, source, serial);
|
||||
}
|
||||
|
||||
static const struct zwp_primary_selection_device_v1_interface primary_device_interface = {
|
||||
primary_device_set_selection,
|
||||
default_destructor,
|
||||
};
|
||||
|
||||
static void
|
||||
owner_changed_cb (MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner,
|
||||
MetaWaylandDataDevicePrimary *data_device)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandSeat *seat = compositor->seat;
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
if (selection_type == META_SELECTION_PRIMARY)
|
||||
{
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
if (new_owner)
|
||||
{
|
||||
offer = create_and_send_primary_offer (data_device,
|
||||
data_device_resource);
|
||||
}
|
||||
|
||||
zwp_primary_selection_device_v1_send_selection (data_device_resource,
|
||||
offer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ensure_owners_changed_handler_connected (MetaWaylandDataDevicePrimary *data_device)
|
||||
{
|
||||
if (data_device->selection_owner_signal_id != 0)
|
||||
return;
|
||||
|
||||
data_device->selection_owner_signal_id =
|
||||
g_signal_connect (meta_display_get_selection (meta_get_display ()),
|
||||
"owner-changed",
|
||||
G_CALLBACK (owner_changed_cb), data_device);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_manager_create_source (struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
guint32 id)
|
||||
{
|
||||
struct wl_resource *source_resource;
|
||||
|
||||
source_resource =
|
||||
wl_resource_create (client, &zwp_primary_selection_source_v1_interface,
|
||||
wl_resource_get_version (manager_resource),
|
||||
id);
|
||||
meta_wayland_data_source_primary_new (source_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_device_manager_get_device (struct wl_client *client,
|
||||
struct wl_resource *manager_resource,
|
||||
guint32 id,
|
||||
struct wl_resource *seat_resource)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
struct wl_resource *cr;
|
||||
|
||||
cr = wl_resource_create (client, &zwp_primary_selection_device_v1_interface,
|
||||
wl_resource_get_version (manager_resource), id);
|
||||
wl_resource_set_implementation (cr, &primary_device_interface,
|
||||
&seat->primary_data_device, unbind_resource);
|
||||
wl_list_insert (&seat->primary_data_device.resource_list, wl_resource_get_link (cr));
|
||||
|
||||
ensure_owners_changed_handler_connected (&seat->primary_data_device);
|
||||
}
|
||||
|
||||
static const struct zwp_primary_selection_device_manager_v1_interface primary_manager_interface = {
|
||||
primary_device_manager_create_source,
|
||||
primary_device_manager_get_device,
|
||||
default_destructor,
|
||||
};
|
||||
|
||||
static void
|
||||
bind_primary_manager (struct wl_client *client,
|
||||
void *data,
|
||||
uint32_t version,
|
||||
uint32_t id)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = wl_resource_create (client, &zwp_primary_selection_device_manager_v1_interface,
|
||||
version, id);
|
||||
wl_resource_set_implementation (resource, &primary_manager_interface, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor)
|
||||
{
|
||||
if (wl_global_create (compositor->wayland_display,
|
||||
&zwp_primary_selection_device_manager_v1_interface,
|
||||
1, NULL, bind_primary_manager) == NULL)
|
||||
g_error ("Could not create data_device");
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
wl_list_init (&data_device->focus_resource_list);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
create_and_send_primary_offer (MetaWaylandDataDevicePrimary *data_device,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
struct wl_resource *resource;
|
||||
GList *mimetypes, *l;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY);
|
||||
if (!mimetypes)
|
||||
return NULL;
|
||||
|
||||
offer = meta_wayland_data_offer_primary_new (target);
|
||||
resource = meta_wayland_data_offer_get_resource (offer);
|
||||
|
||||
zwp_primary_selection_device_v1_send_data_offer (target, resource);
|
||||
|
||||
for (l = mimetypes; l; l = l->next)
|
||||
zwp_primary_selection_offer_v1_send_offer (resource, l->data);
|
||||
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, primary_data_device);
|
||||
struct wl_client *focus_client;
|
||||
struct wl_resource *data_device_resource;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
|
||||
if (focus_client == data_device->focus_client)
|
||||
return;
|
||||
|
||||
data_device->focus_client = focus_client;
|
||||
move_resources (&data_device->resource_list,
|
||||
&data_device->focus_resource_list);
|
||||
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
move_resources_for_client (&data_device->focus_resource_list,
|
||||
&data_device->resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
zwp_primary_selection_device_v1_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
55
src/wayland/meta-wayland-data-device-primary.h
Normal file
55
src/wayland/meta-wayland-data-device-primary.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIMARY_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIMARY_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta/meta-selection-source.h"
|
||||
#include "wayland/meta-wayland-data-offer.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
struct _MetaWaylandDataDevicePrimary
|
||||
{
|
||||
uint32_t serial;
|
||||
MetaWaylandDataSource *data_source;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
guint selection_owner_signal_id;
|
||||
|
||||
MetaSelectionSource *owner;
|
||||
};
|
||||
|
||||
void meta_wayland_data_device_primary_manager_init (MetaWaylandCompositor *compositor);
|
||||
|
||||
void meta_wayland_data_device_primary_init (MetaWaylandDataDevicePrimary *data_device);
|
||||
|
||||
void meta_wayland_data_device_primary_set_keyboard_focus (MetaWaylandDataDevicePrimary *data_device);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIMARY_H */
|
@@ -1,34 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Jonas Ådahl <jadahl@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
|
||||
meta_wayland_data_source_primary,
|
||||
META, WAYLAND_DATA_SOURCE_PRIMARY,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */
|
File diff suppressed because it is too large
Load Diff
@@ -28,44 +28,20 @@
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta/meta-selection-source.h"
|
||||
#include "wayland/meta-wayland-data-offer.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||
typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
META, WAYLAND_DATA_SOURCE, GObject);
|
||||
|
||||
struct _MetaWaylandDataSourceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* send) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd);
|
||||
void (* target) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
void (* cancel) (MetaWaylandDataSource *source);
|
||||
|
||||
void (* action) (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void (* drop_performed) (MetaWaylandDataSource *source);
|
||||
void (* drag_finished) (MetaWaylandDataSource *source);
|
||||
};
|
||||
|
||||
struct _MetaWaylandDataDevice
|
||||
{
|
||||
uint32_t selection_serial;
|
||||
uint32_t primary_serial;
|
||||
MetaWaylandDataSource *selection_data_source;
|
||||
MetaWaylandDataSource *dnd_data_source;
|
||||
MetaWaylandDataSource *primary_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
struct wl_list primary_resource_list;
|
||||
struct wl_list primary_focus_resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
@@ -91,42 +67,7 @@ void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_de
|
||||
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial);
|
||||
void meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source,
|
||||
guint32 serial);
|
||||
|
||||
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
|
||||
gboolean meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
|
||||
struct wl_array *
|
||||
meta_wayland_data_source_get_mime_types (const MetaWaylandDataSource *source);
|
||||
|
||||
gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
|
||||
gboolean has_target);
|
||||
|
||||
void meta_wayland_data_source_cancel (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd);
|
||||
|
||||
void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source);
|
||||
|
||||
uint32_t meta_wayland_data_source_get_actions (MetaWaylandDataSource *source);
|
||||
uint32_t meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source);
|
||||
uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
uint32_t dnd_actions);
|
||||
void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void meta_wayland_data_device_unset_dnd_selection (MetaWaylandDataDevice *data_device);
|
||||
|
||||
const MetaWaylandDragDestFuncs *
|
||||
meta_wayland_data_device_get_drag_dest_funcs (void);
|
||||
|
139
src/wayland/meta-wayland-data-offer-primary-legacy.c
Normal file
139
src/wayland/meta-wayland-data-offer-primary-legacy.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-data-offer-primary-legacy.h"
|
||||
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <glib-unix.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "core/display-private.h"
|
||||
#include "gtk-primary-selection-server-protocol.h"
|
||||
#include "wayland/meta-wayland-data-offer.h"
|
||||
|
||||
static void
|
||||
transfer_cb (MetaSelection *selection,
|
||||
GAsyncResult *res,
|
||||
GOutputStream *stream)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_selection_transfer_finish (selection, res, &error))
|
||||
{
|
||||
g_warning ("Could not fetch selection data: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_offer_receive (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
GOutputStream *stream;
|
||||
GList *mime_types;
|
||||
gboolean found;
|
||||
|
||||
mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY);
|
||||
found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL;
|
||||
g_list_free_full (mime_types, g_free);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
meta_selection_transfer_async (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
mime_type,
|
||||
-1,
|
||||
stream,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) transfer_cb,
|
||||
stream);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_offer_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct gtk_primary_selection_offer_interface primary_offer_interface = {
|
||||
primary_offer_receive,
|
||||
primary_offer_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_primary_offer (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||
{
|
||||
meta_wayland_data_source_cancel (offer->source);
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
}
|
||||
|
||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||
(gpointer *)&offer->source);
|
||||
offer->source = NULL;
|
||||
}
|
||||
|
||||
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
MetaWaylandDataOffer *
|
||||
meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
offer->selection_type = META_SELECTION_PRIMARY;
|
||||
offer->resource = wl_resource_create (wl_resource_get_client (target),
|
||||
>k_primary_selection_offer_interface,
|
||||
wl_resource_get_version (target), 0);
|
||||
wl_resource_set_implementation (offer->resource,
|
||||
&primary_offer_interface,
|
||||
offer,
|
||||
destroy_primary_offer);
|
||||
return offer;
|
||||
}
|
31
src/wayland/meta-wayland-data-offer-primary-legacy.h
Normal file
31
src/wayland/meta-wayland-data-offer-primary-legacy.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H
|
||||
#define META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H
|
||||
|
||||
#include "meta-wayland-data-offer.h"
|
||||
|
||||
MetaWaylandDataOffer * meta_wayland_data_offer_primary_legacy_new (struct wl_resource *target);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_LEGACY_H */
|
139
src/wayland/meta-wayland-data-offer-primary.c
Normal file
139
src/wayland/meta-wayland-data-offer-primary.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "meta-wayland-data-offer-primary.h"
|
||||
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <glib-unix.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "core/display-private.h"
|
||||
#include "primary-selection-unstable-v1-server-protocol.h"
|
||||
#include "wayland/meta-wayland-data-offer.h"
|
||||
|
||||
static void
|
||||
transfer_cb (MetaSelection *selection,
|
||||
GAsyncResult *res,
|
||||
GOutputStream *stream)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_selection_transfer_finish (selection, res, &error))
|
||||
{
|
||||
g_warning ("Could not fetch selection data: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_offer_receive (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *mime_type,
|
||||
int32_t fd)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
GOutputStream *stream;
|
||||
GList *mime_types;
|
||||
gboolean found;
|
||||
|
||||
mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY);
|
||||
found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL;
|
||||
g_list_free_full (mime_types, g_free);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
meta_selection_transfer_async (meta_display_get_selection (display),
|
||||
META_SELECTION_PRIMARY,
|
||||
mime_type,
|
||||
-1,
|
||||
stream,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) transfer_cb,
|
||||
stream);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_offer_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static const struct zwp_primary_selection_offer_v1_interface primary_offer_interface = {
|
||||
primary_offer_receive,
|
||||
primary_offer_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_primary_offer (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||
{
|
||||
meta_wayland_data_source_cancel (offer->source);
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
}
|
||||
|
||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||
(gpointer *)&offer->source);
|
||||
offer->source = NULL;
|
||||
}
|
||||
|
||||
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
MetaWaylandDataOffer *
|
||||
meta_wayland_data_offer_primary_new (struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
offer->selection_type = META_SELECTION_PRIMARY;
|
||||
offer->resource = wl_resource_create (wl_resource_get_client (target),
|
||||
&zwp_primary_selection_offer_v1_interface,
|
||||
wl_resource_get_version (target), 0);
|
||||
wl_resource_set_implementation (offer->resource,
|
||||
&primary_offer_interface,
|
||||
offer,
|
||||
destroy_primary_offer);
|
||||
return offer;
|
||||
}
|
31
src/wayland/meta-wayland-data-offer-primary.h
Normal file
31
src/wayland/meta-wayland-data-offer-primary.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_OFFER_PRIMARY_H
|
||||
#define META_WAYLAND_DATA_OFFER_PRIMARY_H
|
||||
|
||||
#include "meta-wayland-data-offer.h"
|
||||
|
||||
MetaWaylandDataOffer * meta_wayland_data_offer_primary_new (struct wl_resource *target);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_OFFER_PRIMARY_H */
|
327
src/wayland/meta-wayland-data-offer.c
Normal file
327
src/wayland/meta-wayland-data-offer.c
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gio/gunixoutputstream.h>
|
||||
#include <glib-unix.h>
|
||||
#include <glib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "meta/meta-selection.h"
|
||||
#include "wayland/meta-wayland-data-device.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
#include "meta-wayland-data-offer.h"
|
||||
|
||||
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
|
||||
static void
|
||||
data_offer_accept (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
guint32 serial,
|
||||
const char *mime_type)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
/* FIXME: Check that client is currently focused by the input
|
||||
* device that is currently dragging this data source. Should
|
||||
* this be a wl_data_device request? */
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
meta_wayland_data_source_target (offer->source, mime_type);
|
||||
meta_wayland_data_source_set_has_target (offer->source,
|
||||
mime_type != NULL);
|
||||
}
|
||||
|
||||
offer->accepted = mime_type != NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
transfer_cb (MetaSelection *selection,
|
||||
GAsyncResult *res,
|
||||
GOutputStream *stream)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!meta_selection_transfer_finish (selection, res, &error))
|
||||
{
|
||||
g_warning ("Could not fetch selection data: %s", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_receive (struct wl_client *client, struct wl_resource *resource,
|
||||
const char *mime_type, int32_t fd)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaSelectionType selection_type;
|
||||
GList *mime_types;
|
||||
gboolean found;
|
||||
|
||||
selection_type = offer->selection_type;
|
||||
mime_types = meta_selection_get_mimetypes (meta_display_get_selection (display),
|
||||
selection_type);
|
||||
found = g_list_find_custom (mime_types, mime_type, (GCompareFunc) g_strcmp0) != NULL;
|
||||
g_list_free_full (mime_types, g_free);
|
||||
|
||||
if (found)
|
||||
{
|
||||
GOutputStream *stream;
|
||||
|
||||
stream = g_unix_output_stream_new (fd, TRUE);
|
||||
meta_selection_transfer_async (meta_display_get_selection (display),
|
||||
selection_type,
|
||||
mime_type,
|
||||
-1,
|
||||
stream,
|
||||
NULL,
|
||||
(GAsyncReadyCallback) transfer_cb,
|
||||
stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_finish (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
enum wl_data_device_manager_dnd_action current_action;
|
||||
|
||||
if (!offer->source ||
|
||||
offer != meta_wayland_data_source_get_current_offer (offer->source))
|
||||
return;
|
||||
|
||||
if (!offer->accepted || !offer->action_sent)
|
||||
{
|
||||
wl_resource_post_error (offer->resource,
|
||||
WL_DATA_OFFER_ERROR_INVALID_FINISH,
|
||||
"premature finish request");
|
||||
return;
|
||||
}
|
||||
|
||||
current_action = meta_wayland_data_source_get_current_action (offer->source);
|
||||
|
||||
if (current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE ||
|
||||
current_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
{
|
||||
wl_resource_post_error (offer->resource,
|
||||
WL_DATA_OFFER_ERROR_INVALID_OFFER,
|
||||
"offer finished with an invalid action");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_set_actions (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t dnd_actions,
|
||||
uint32_t preferred_action)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
|
||||
if (dnd_actions & ~(ALL_ACTIONS))
|
||||
{
|
||||
wl_resource_post_error (offer->resource,
|
||||
WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid actions mask %x", dnd_actions);
|
||||
return;
|
||||
}
|
||||
|
||||
if (preferred_action &&
|
||||
(!(preferred_action & dnd_actions) ||
|
||||
__builtin_popcount (preferred_action) > 1))
|
||||
{
|
||||
wl_resource_post_error (offer->resource,
|
||||
WL_DATA_OFFER_ERROR_INVALID_ACTION,
|
||||
"invalid action %x", preferred_action);
|
||||
return;
|
||||
}
|
||||
|
||||
offer->dnd_actions = dnd_actions;
|
||||
offer->preferred_dnd_action = preferred_action;
|
||||
|
||||
meta_wayland_data_offer_update_action (offer);
|
||||
}
|
||||
|
||||
static const struct wl_data_offer_interface data_offer_interface = {
|
||||
data_offer_accept,
|
||||
data_offer_receive,
|
||||
data_offer_destroy,
|
||||
data_offer_finish,
|
||||
data_offer_set_actions,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_data_offer (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataOffer *offer = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat;
|
||||
|
||||
if (offer->source)
|
||||
{
|
||||
seat = meta_wayland_data_source_get_seat (offer->source);
|
||||
|
||||
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||
{
|
||||
if (seat->data_device.dnd_data_source == offer->source)
|
||||
{
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
else if (meta_wayland_data_source_get_drop_performed (offer->source))
|
||||
meta_wayland_data_source_cancel (offer->source);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
meta_wayland_data_source_set_has_target (offer->source, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_remove_weak_pointer (G_OBJECT (offer->source),
|
||||
(gpointer *)&offer->source);
|
||||
offer->source = NULL;
|
||||
}
|
||||
|
||||
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||
g_slice_free (MetaWaylandDataOffer, offer);
|
||||
}
|
||||
|
||||
MetaWaylandDataOffer *
|
||||
meta_wayland_data_offer_new (MetaSelectionType selection_type,
|
||||
MetaWaylandDataSource *source,
|
||||
struct wl_resource *target)
|
||||
{
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
offer = g_slice_new0 (MetaWaylandDataOffer);
|
||||
offer->selection_type = selection_type;
|
||||
offer->resource = wl_resource_create (wl_resource_get_client (target),
|
||||
&wl_data_offer_interface,
|
||||
wl_resource_get_version (target), 0);
|
||||
wl_resource_set_implementation (offer->resource,
|
||||
&data_offer_interface,
|
||||
offer,
|
||||
destroy_data_offer);
|
||||
if (source)
|
||||
{
|
||||
offer->source = source;
|
||||
g_object_add_weak_pointer (G_OBJECT (source), (gpointer *)&offer->source);
|
||||
}
|
||||
|
||||
return offer;
|
||||
}
|
||||
|
||||
static enum wl_data_device_manager_dnd_action
|
||||
data_offer_choose_action (MetaWaylandDataOffer *offer)
|
||||
{
|
||||
MetaWaylandDataSource *source = offer->source;
|
||||
uint32_t actions, user_action, available_actions;
|
||||
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
|
||||
meta_wayland_data_source_get_actions (source, &actions);
|
||||
user_action = meta_wayland_data_source_get_user_action (source);
|
||||
|
||||
available_actions = actions & offer->dnd_actions;
|
||||
|
||||
if (!available_actions)
|
||||
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
|
||||
/* If the user is forcing an action, go for it */
|
||||
if ((user_action & available_actions) != 0)
|
||||
return user_action;
|
||||
|
||||
/* If the dest side has a preferred DnD action, use it */
|
||||
if ((offer->preferred_dnd_action & available_actions) != 0)
|
||||
return offer->preferred_dnd_action;
|
||||
|
||||
/* Use the first found action, in bit order */
|
||||
return 1 << (ffs (available_actions) - 1);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer)
|
||||
{
|
||||
enum wl_data_device_manager_dnd_action current_action, action;
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
if (!offer->source)
|
||||
return;
|
||||
|
||||
source = offer->source;
|
||||
current_action = meta_wayland_data_source_get_current_action (source);
|
||||
action = data_offer_choose_action (offer);
|
||||
|
||||
if (current_action == action)
|
||||
return;
|
||||
|
||||
meta_wayland_data_source_set_current_action (source, action);
|
||||
|
||||
if (!meta_wayland_data_source_get_in_ask (source) &&
|
||||
wl_resource_get_version (offer->resource) >=
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
{
|
||||
wl_data_offer_send_action (offer->resource, action);
|
||||
offer->action_sent = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer)
|
||||
{
|
||||
return offer->resource;
|
||||
}
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer)
|
||||
{
|
||||
return offer->source;
|
||||
}
|
51
src/wayland/meta-wayland-data-offer.h
Normal file
51
src/wayland/meta-wayland-data-offer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_OFFER_H
|
||||
#define META_WAYLAND_DATA_OFFER_H
|
||||
|
||||
#include "meta/meta-selection.h"
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
|
||||
struct _MetaWaylandDataOffer
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataSource *source;
|
||||
struct wl_listener source_destroy_listener;
|
||||
gboolean accepted;
|
||||
gboolean action_sent;
|
||||
uint32_t dnd_actions;
|
||||
enum wl_data_device_manager_dnd_action preferred_dnd_action;
|
||||
MetaSelectionType selection_type;
|
||||
};
|
||||
|
||||
MetaWaylandDataOffer * meta_wayland_data_offer_new (MetaSelectionType selection_type,
|
||||
MetaWaylandDataSource *source,
|
||||
struct wl_resource *resource);
|
||||
|
||||
void meta_wayland_data_offer_update_action (MetaWaylandDataOffer *offer);
|
||||
|
||||
struct wl_resource * meta_wayland_data_offer_get_resource (MetaWaylandDataOffer *offer);
|
||||
MetaWaylandDataSource * meta_wayland_data_offer_get_source (MetaWaylandDataOffer *offer);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_OFFER_H */
|
117
src/wayland/meta-wayland-data-source-primary-legacy.c
Normal file
117
src/wayland/meta-wayland-data-source-primary-legacy.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "gtk-primary-selection-server-protocol.h"
|
||||
#include "wayland/meta-wayland-data-source-primary-legacy.h"
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrimaryLegacy
|
||||
{
|
||||
MetaWaylandDataSource parent;
|
||||
} MetaWaylandDataSourcePrimaryLegacy;
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourcePrimaryLegacy, meta_wayland_data_source_primary_legacy,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
|
||||
static void
|
||||
primary_source_offer (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *type)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
if (!meta_wayland_data_source_add_mime_type (source, type))
|
||||
wl_resource_post_no_memory (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_source_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static struct gtk_primary_selection_source_interface primary_source_interface = {
|
||||
primary_source_offer,
|
||||
primary_source_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_primary_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_legacy_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
gtk_primary_selection_source_send_send (resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_legacy_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
if (resource)
|
||||
gtk_primary_selection_source_send_cancelled (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_legacy_init (MetaWaylandDataSourcePrimaryLegacy *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_legacy_class_init (MetaWaylandDataSourcePrimaryLegacyClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_legacy_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_legacy_cancel;
|
||||
}
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source_primary =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY, NULL);
|
||||
|
||||
meta_wayland_data_source_set_resource (source_primary, resource);
|
||||
wl_resource_set_implementation (resource, &primary_source_interface,
|
||||
source_primary, destroy_primary_source);
|
||||
|
||||
return source_primary;
|
||||
}
|
37
src/wayland/meta-wayland-data-source-primary-legacy.h
Normal file
37
src/wayland/meta-wayland-data-source-primary-legacy.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H
|
||||
#define META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H
|
||||
|
||||
#include "meta-wayland-data-source.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY (meta_wayland_data_source_primary_legacy_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimaryLegacy,
|
||||
meta_wayland_data_source_primary_legacy,
|
||||
META, WAYLAND_DATA_SOURCE_PRIMARY_LEGACY,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
MetaWaylandDataSource * meta_wayland_data_source_primary_legacy_new (struct wl_resource *resource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_LEGACY_H */
|
117
src/wayland/meta-wayland-data-source-primary.c
Normal file
117
src/wayland/meta-wayland-data-source-primary.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "primary-selection-unstable-v1-server-protocol.h"
|
||||
#include "wayland/meta-wayland-data-source-primary.h"
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrimary
|
||||
{
|
||||
MetaWaylandDataSource parent;
|
||||
} MetaWaylandDataSourcePrimary;
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
|
||||
static void
|
||||
primary_source_offer (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
const char *type)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
if (!meta_wayland_data_source_add_mime_type (source, type))
|
||||
wl_resource_post_no_memory (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
primary_source_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static struct zwp_primary_selection_source_v1_interface primary_source_interface = {
|
||||
primary_source_offer,
|
||||
primary_source_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_primary_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
zwp_primary_selection_source_v1_send_send (resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
if (resource)
|
||||
zwp_primary_selection_source_v1_send_cancelled (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
|
||||
}
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source_primary =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
|
||||
|
||||
meta_wayland_data_source_set_resource (source_primary, resource);
|
||||
wl_resource_set_implementation (resource, &primary_source_interface,
|
||||
source_primary, destroy_primary_source);
|
||||
|
||||
return source_primary;
|
||||
}
|
37
src/wayland/meta-wayland-data-source-primary.h
Normal file
37
src/wayland/meta-wayland-data-source-primary.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_SOURCE_PRIMARY_H
|
||||
#define META_WAYLAND_DATA_SOURCE_PRIMARY_H
|
||||
|
||||
#include "meta-wayland-data-source.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
|
||||
meta_wayland_data_source_primary,
|
||||
META, WAYLAND_DATA_SOURCE_PRIMARY,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
MetaWaylandDataSource * meta_wayland_data_source_primary_new (struct wl_resource *resource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_SOURCE_PRIMARY_H */
|
523
src/wayland/meta-wayland-data-source.c
Normal file
523
src/wayland/meta-wayland-data-source.c
Normal file
@@ -0,0 +1,523 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include "wayland/meta-wayland-data-source.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
|
||||
#define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrivate
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataOffer *offer;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
uint32_t dnd_actions;
|
||||
enum wl_data_device_manager_dnd_action user_dnd_action;
|
||||
enum wl_data_device_manager_dnd_action current_dnd_action;
|
||||
MetaWaylandSeat *seat;
|
||||
guint actions_set : 1;
|
||||
guint in_ask : 1;
|
||||
guint drop_performed : 1;
|
||||
} MetaWaylandDataSourcePrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_send (priv->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_target (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_target (priv->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (!priv->resource)
|
||||
return;
|
||||
|
||||
wl_data_source_send_cancelled (priv->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
wl_data_source_send_action (priv->resource, action);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
|
||||
{
|
||||
priv->drop_performed = TRUE;
|
||||
wl_data_source_send_dnd_drop_performed (priv->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_real_drag_finished (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
enum wl_data_device_manager_dnd_action action;
|
||||
|
||||
if (meta_wayland_data_source_get_in_ask (source))
|
||||
{
|
||||
action = meta_wayland_data_source_get_current_action (source);
|
||||
meta_wayland_data_source_real_action (source, action);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
|
||||
wl_data_source_send_dnd_finished (priv->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
char **pos;
|
||||
|
||||
wl_array_for_each (pos, &priv->mime_types)
|
||||
g_free (*pos);
|
||||
wl_array_release (&priv->mime_types);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_data_source_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_init (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_array_init (&priv->mime_types);
|
||||
priv->current_dnd_action = -1;
|
||||
priv->drop_performed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_data_source_finalize;
|
||||
|
||||
klass->send = meta_wayland_data_source_real_send;
|
||||
klass->target = meta_wayland_data_source_real_target;
|
||||
klass->cancel = meta_wayland_data_source_real_cancel;
|
||||
klass->action = meta_wayland_data_source_real_action;
|
||||
klass->drop_performed = meta_wayland_data_source_real_drop_performed;
|
||||
klass->drag_finished = meta_wayland_data_source_real_drag_finished;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
data_source_offer (struct wl_client *client,
|
||||
struct wl_resource *resource, const char *type)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
if (!meta_wayland_data_source_add_mime_type (source, type))
|
||||
wl_resource_post_no_memory (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_destroy (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
data_source_set_actions (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
uint32_t dnd_actions)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (priv->actions_set)
|
||||
{
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"cannot set actions more than once");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dnd_actions & ~(ALL_ACTIONS))
|
||||
{
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid actions mask %x", dnd_actions);
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta_wayland_data_source_get_seat (source))
|
||||
{
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid action change after "
|
||||
"wl_data_device.start_drag");
|
||||
return;
|
||||
}
|
||||
|
||||
meta_wayland_data_source_set_actions (source, dnd_actions);
|
||||
}
|
||||
|
||||
static struct wl_data_source_interface data_source_interface = {
|
||||
data_source_offer,
|
||||
data_source_destroy,
|
||||
data_source_set_actions
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
MetaWaylandDataSource *
|
||||
meta_wayland_data_source_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSource *source =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
meta_wayland_data_source_set_resource (source, resource);
|
||||
wl_resource_set_implementation (resource, &data_source_interface,
|
||||
source, destroy_data_source);
|
||||
|
||||
if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
{
|
||||
priv->dnd_actions = priv->user_dnd_action =
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
struct wl_resource *
|
||||
meta_wayland_data_source_get_resource (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->resource;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_resource (MetaWaylandDataSource *source,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->resource = resource;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->in_ask;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->in_ask =
|
||||
priv->current_dnd_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
if (META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target)
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->target (source, mime_type);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
||||
const char *mime_type,
|
||||
int fd)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->send (source, mime_type, fd);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_has_target (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->has_target;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_seat (MetaWaylandDataSource *source,
|
||||
MetaWaylandSeat *seat)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->seat = seat;
|
||||
}
|
||||
|
||||
MetaWaylandSeat *
|
||||
meta_wayland_data_source_get_seat (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->seat;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
|
||||
gboolean has_target)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->has_target = has_target;
|
||||
}
|
||||
|
||||
struct wl_array *
|
||||
meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private ((MetaWaylandDataSource *)source);
|
||||
|
||||
return &priv->mime_types;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->cancel (source);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_get_actions (MetaWaylandDataSource *source,
|
||||
uint32_t *dnd_actions)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (dnd_actions)
|
||||
*dnd_actions = priv->dnd_actions;
|
||||
|
||||
return priv->actions_set;
|
||||
}
|
||||
|
||||
enum wl_data_device_manager_dnd_action
|
||||
meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (!priv->seat)
|
||||
return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
|
||||
|
||||
return priv->user_dnd_action;
|
||||
}
|
||||
|
||||
enum wl_data_device_manager_dnd_action
|
||||
meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->current_dnd_action;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source,
|
||||
MetaWaylandDataOffer *offer)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->offer = offer;
|
||||
}
|
||||
|
||||
MetaWaylandDataOffer *
|
||||
meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->offer;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (priv->current_dnd_action == action)
|
||||
return;
|
||||
|
||||
priv->current_dnd_action = action;
|
||||
|
||||
if (!meta_wayland_data_source_get_in_ask (source))
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->action (source, action);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
uint32_t dnd_actions)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->dnd_actions = dnd_actions;
|
||||
priv->actions_set = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
MetaWaylandDataOffer *offer;
|
||||
|
||||
if (priv->user_dnd_action == action)
|
||||
return;
|
||||
|
||||
priv->user_dnd_action = action;
|
||||
offer = meta_wayland_data_source_get_current_offer (source);
|
||||
|
||||
if (offer)
|
||||
meta_wayland_data_offer_update_action (offer);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->drop_performed;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drop_performed (source);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source)
|
||||
{
|
||||
META_WAYLAND_DATA_SOURCE_GET_CLASS (source)->drag_finished (source);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
char **pos;
|
||||
|
||||
pos = wl_array_add (&priv->mime_types, sizeof (*pos));
|
||||
|
||||
if (pos)
|
||||
{
|
||||
*pos = g_strdup (mime_type);
|
||||
return *pos != NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
char **p;
|
||||
|
||||
wl_array_for_each (p, &priv->mime_types)
|
||||
{
|
||||
if (g_strcmp0 (mime_type, *p) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
112
src/wayland/meta-wayland-data-source.h
Normal file
112
src/wayland/meta-wayland-data-source.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright © 2011 Kristian Høgsberg
|
||||
* 2020 Red Hat Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef META_WAYLAND_DATA_SOURCE_H
|
||||
#define META_WAYLAND_DATA_SOURCE_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
#include "wayland/meta-wayland-types.h"
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE (meta_wayland_data_source_get_type ())
|
||||
G_DECLARE_DERIVABLE_TYPE (MetaWaylandDataSource,
|
||||
meta_wayland_data_source,
|
||||
META, WAYLAND_DATA_SOURCE,
|
||||
GObject)
|
||||
|
||||
typedef struct _MetaWaylandDataSourceClass MetaWaylandDataSourceClass;
|
||||
|
||||
struct _MetaWaylandDataSourceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* send) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd);
|
||||
void (* target) (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
void (* cancel) (MetaWaylandDataSource *source);
|
||||
|
||||
void (* action) (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void (* drop_performed) (MetaWaylandDataSource *source);
|
||||
void (* drag_finished) (MetaWaylandDataSource *source);
|
||||
};
|
||||
|
||||
MetaWaylandDataSource * meta_wayland_data_source_new (struct wl_resource *resource);
|
||||
|
||||
struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_set_resource (MetaWaylandDataSource *source,
|
||||
struct wl_resource *resource);
|
||||
|
||||
gboolean meta_wayland_data_source_get_in_ask (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_update_in_ask (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||
const char *mime_type);
|
||||
void meta_wayland_data_source_send (MetaWaylandDataSource *source,
|
||||
const char *mime_type,
|
||||
int fd);
|
||||
void meta_wayland_data_source_cancel (MetaWaylandDataSource *source);
|
||||
|
||||
gboolean meta_wayland_data_source_has_target (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_set_seat (MetaWaylandDataSource *source,
|
||||
MetaWaylandSeat *seat);
|
||||
MetaWaylandSeat * meta_wayland_data_source_get_seat (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_set_has_target (MetaWaylandDataSource *source,
|
||||
gboolean has_target);
|
||||
struct wl_array * meta_wayland_data_source_get_mime_types (MetaWaylandDataSource *source);
|
||||
gboolean meta_wayland_data_source_add_mime_type (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type);
|
||||
gboolean meta_wayland_data_source_has_mime_type (MetaWaylandDataSource *source,
|
||||
const char *mime_type);
|
||||
|
||||
gboolean meta_wayland_data_source_get_actions (MetaWaylandDataSource *source,
|
||||
uint32_t *dnd_actions);
|
||||
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
uint32_t dnd_actions);
|
||||
|
||||
enum wl_data_device_manager_dnd_action
|
||||
meta_wayland_data_source_get_current_action (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action);
|
||||
|
||||
enum wl_data_device_manager_dnd_action
|
||||
meta_wayland_data_source_get_user_action (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
|
||||
MetaWaylandDataOffer *
|
||||
meta_wayland_data_source_get_current_offer (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_set_current_offer (MetaWaylandDataSource *source,
|
||||
MetaWaylandDataOffer *offer);
|
||||
|
||||
gboolean meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source);
|
||||
|
||||
void meta_wayland_data_source_notify_drop_performed (MetaWaylandDataSource *source);
|
||||
void meta_wayland_data_source_notify_finish (MetaWaylandDataSource *source);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_SOURCE_H */
|
@@ -662,8 +662,6 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
MetaRectangle old_geometry;
|
||||
gboolean geometry_changed;
|
||||
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
@@ -672,8 +670,6 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
||||
return;
|
||||
}
|
||||
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
|
||||
surface_role_class->apply_state (surface_role, pending);
|
||||
@@ -688,13 +684,37 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
||||
meta_wayland_window_configuration_free (configuration);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_zxdg_toplevel_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandZxdgToplevelV6 *xdg_toplevel =
|
||||
META_WAYLAND_ZXDG_TOPLEVEL_V6 (surface_role);
|
||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||
META_WAYLAND_ZXDG_SURFACE_V6 (xdg_toplevel);
|
||||
MetaWaylandZxdgSurfaceV6Private *xdg_surface_priv =
|
||||
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
MetaRectangle old_geometry;
|
||||
gboolean geometry_changed;
|
||||
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!pending->newly_attached)
|
||||
return;
|
||||
|
||||
/* If the window disappeared the surface is not coming back. */
|
||||
if (!window)
|
||||
return;
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
|
||||
surface_role_class->post_apply_state (surface_role, pending);
|
||||
|
||||
geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry);
|
||||
|
||||
@@ -734,7 +754,6 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
||||
wl_resource_post_error (surface->resource,
|
||||
ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
|
||||
"Invalid min/max size");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -832,6 +851,8 @@ meta_wayland_zxdg_toplevel_v6_class_init (MetaWaylandZxdgToplevelV6Class *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_zxdg_toplevel_v6_apply_state;
|
||||
surface_role_class->post_apply_state =
|
||||
meta_wayland_zxdg_toplevel_v6_post_apply_state;
|
||||
surface_role_class->get_toplevel = meta_wayland_zxdg_toplevel_v6_get_toplevel;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
@@ -964,12 +985,7 @@ meta_wayland_zxdg_popup_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role);
|
||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
|
||||
if (xdg_popup->setup.parent_surface)
|
||||
finish_popup_setup (xdg_popup);
|
||||
@@ -977,12 +993,27 @@ meta_wayland_zxdg_popup_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class);
|
||||
surface_role_class->apply_state (surface_role, pending);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_zxdg_popup_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
|
||||
/* If the window disappeared the surface is not coming back. */
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class);
|
||||
surface_role_class->post_apply_state (surface_role, pending);
|
||||
|
||||
if (!pending->newly_attached)
|
||||
return;
|
||||
|
||||
@@ -1165,6 +1196,8 @@ meta_wayland_zxdg_popup_v6_class_init (MetaWaylandZxdgPopupV6Class *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_zxdg_popup_v6_apply_state;
|
||||
surface_role_class->post_apply_state =
|
||||
meta_wayland_zxdg_popup_v6_post_apply_state;
|
||||
surface_role_class->get_toplevel = meta_wayland_zxdg_popup_v6_get_toplevel;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
@@ -1331,8 +1364,6 @@ meta_wayland_zxdg_surface_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
{
|
||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
||||
MetaWaylandShellSurface *shell_surface =
|
||||
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
||||
MetaWaylandZxdgSurfaceV6Private *priv =
|
||||
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
@@ -1370,8 +1401,18 @@ meta_wayland_zxdg_surface_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
|
||||
if (surface->buffer_ref.buffer)
|
||||
priv->first_buffer_attached = TRUE;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_zxdg_surface_v6_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
||||
MetaWaylandZxdgSurfaceV6Private *priv =
|
||||
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
|
||||
MetaWaylandShellSurface *shell_surface =
|
||||
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
||||
|
||||
if (pending->has_new_geometry)
|
||||
{
|
||||
@@ -1526,6 +1567,8 @@ meta_wayland_zxdg_surface_v6_class_init (MetaWaylandZxdgSurfaceV6Class *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_zxdg_surface_v6_apply_state;
|
||||
surface_role_class->post_apply_state =
|
||||
meta_wayland_zxdg_surface_v6_post_apply_state;
|
||||
surface_role_class->assigned = meta_wayland_zxdg_surface_v6_assigned;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "wayland/meta-wayland-seat.h"
|
||||
|
||||
#include "wayland/meta-wayland-data-device.h"
|
||||
#include "wayland/meta-wayland-data-device-primary-legacy.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#include "wayland/meta-wayland-tablet-seat.h"
|
||||
#include "wayland/meta-wayland-versions.h"
|
||||
@@ -231,6 +232,8 @@ meta_wayland_seat_new (MetaWaylandCompositor *compositor,
|
||||
seat->gtk_text_input = meta_wayland_gtk_text_input_new (seat);
|
||||
|
||||
meta_wayland_data_device_init (&seat->data_device);
|
||||
meta_wayland_data_device_primary_init (&seat->primary_data_device);
|
||||
meta_wayland_data_device_primary_legacy_init (&seat->primary_legacy_data_device);
|
||||
|
||||
clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||
meta_wayland_seat_update_capabilities (seat, clutter_seat);
|
||||
@@ -431,6 +434,8 @@ meta_wayland_seat_set_input_focus (MetaWaylandSeat *seat,
|
||||
{
|
||||
meta_wayland_keyboard_set_focus (seat->keyboard, surface);
|
||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
||||
meta_wayland_data_device_primary_set_keyboard_focus (&seat->primary_data_device);
|
||||
meta_wayland_data_device_primary_legacy_set_keyboard_focus (&seat->primary_legacy_data_device);
|
||||
}
|
||||
|
||||
tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||
|
@@ -26,6 +26,8 @@
|
||||
|
||||
#include "clutter/clutter.h"
|
||||
#include "wayland/meta-wayland-data-device.h"
|
||||
#include "wayland/meta-wayland-data-device-primary.h"
|
||||
#include "wayland/meta-wayland-data-device-primary-legacy.h"
|
||||
#include "wayland/meta-wayland-input-device.h"
|
||||
#include "wayland/meta-wayland-keyboard.h"
|
||||
#include "wayland/meta-wayland-pointer.h"
|
||||
@@ -45,6 +47,8 @@ struct _MetaWaylandSeat
|
||||
MetaWaylandTouch *touch;
|
||||
|
||||
MetaWaylandDataDevice data_device;
|
||||
MetaWaylandDataDevicePrimary primary_data_device;
|
||||
MetaWaylandDataDevicePrimaryLegacy primary_legacy_data_device;
|
||||
|
||||
MetaWaylandGtkTextInput *gtk_text_input;
|
||||
MetaWaylandTextInput *text_input;
|
||||
|
@@ -113,6 +113,10 @@ static void
|
||||
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending);
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending);
|
||||
|
||||
static gboolean
|
||||
meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaLogicalMonitor *logical_monitor);
|
||||
@@ -757,8 +761,6 @@ cleanup:
|
||||
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED],
|
||||
0);
|
||||
|
||||
meta_wayland_surface_state_reset (state);
|
||||
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
@@ -782,6 +784,11 @@ cleanup:
|
||||
meta_window_actor_notify_damaged (toplevel_window_actor);
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->role)
|
||||
meta_wayland_surface_role_post_apply_state (surface->role, state);
|
||||
|
||||
meta_wayland_surface_state_reset (state);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1696,6 +1703,17 @@ meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role
|
||||
klass->pre_apply_state (surface_role, pending);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRoleClass *klass;
|
||||
|
||||
klass = META_WAYLAND_SURFACE_ROLE_GET_CLASS (surface_role);
|
||||
if (klass->post_apply_state)
|
||||
klass->post_apply_state (surface_role, pending);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
|
@@ -58,6 +58,8 @@ struct _MetaWaylandSurfaceRoleClass
|
||||
MetaWaylandSurfaceState *pending);
|
||||
void (*apply_state) (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending);
|
||||
void (*post_apply_state) (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending);
|
||||
gboolean (*is_on_logical_monitor) (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaLogicalMonitor *logical_monitor);
|
||||
MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role);
|
||||
|
@@ -37,6 +37,8 @@ typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
||||
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||
typedef struct _MetaWaylandDataDevicePrimary MetaWaylandDataDevicePrimary;
|
||||
typedef struct _MetaWaylandDataDevicePrimaryLegacy MetaWaylandDataDevicePrimaryLegacy;
|
||||
|
||||
typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
|
||||
typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat;
|
||||
|
@@ -744,8 +744,6 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
MetaRectangle old_geometry;
|
||||
gboolean geometry_changed;
|
||||
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
@@ -765,8 +763,6 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
return;
|
||||
}
|
||||
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
||||
surface_role_class->apply_state (surface_role, pending);
|
||||
@@ -780,17 +776,42 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
meta_wayland_window_configuration_free (configuration);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xdg_toplevel_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
||||
MetaWaylandXdgSurfacePrivate *xdg_surface_priv =
|
||||
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWindow *window;
|
||||
MetaRectangle old_geometry;
|
||||
MetaRectangle window_geometry;
|
||||
|
||||
gboolean geometry_changed;
|
||||
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
||||
surface_role_class->post_apply_state (surface_role, pending);
|
||||
|
||||
if (!pending->newly_attached)
|
||||
return;
|
||||
|
||||
geometry_changed = !meta_rectangle_equal (&old_geometry, &xdg_surface_priv->geometry);
|
||||
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
|
||||
geometry_changed = !meta_rectangle_equal (&old_geometry, &window_geometry);
|
||||
|
||||
if (geometry_changed || pending->has_acked_configure_serial)
|
||||
{
|
||||
MetaRectangle window_geometry;
|
||||
|
||||
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
|
||||
meta_window_wayland_finish_move_resize (window, window_geometry, pending);
|
||||
}
|
||||
else if (pending->dx != 0 || pending->dy != 0)
|
||||
@@ -821,7 +842,6 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
wl_resource_post_error (surface->resource,
|
||||
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
||||
"Invalid min/max size");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -940,6 +960,7 @@ meta_wayland_xdg_toplevel_class_init (MetaWaylandXdgToplevelClass *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_xdg_toplevel_apply_state;
|
||||
surface_role_class->post_apply_state = meta_wayland_xdg_toplevel_post_apply_state;
|
||||
surface_role_class->get_toplevel = meta_wayland_xdg_toplevel_get_toplevel;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
@@ -1092,10 +1113,6 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window;
|
||||
MetaRectangle buffer_rect;
|
||||
MetaWindow *parent_window;
|
||||
MetaRectangle parent_buffer_rect;
|
||||
|
||||
if (xdg_popup->setup.parent_surface)
|
||||
finish_popup_setup (xdg_popup);
|
||||
@@ -1118,8 +1135,23 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
"Can't commit buffer to dismissed popup");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xdg_popup_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandXdgPopup *xdg_popup = META_WAYLAND_XDG_POPUP (surface_role);
|
||||
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class =
|
||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_popup_parent_class);
|
||||
MetaWindow *window;
|
||||
MetaWindow *parent_window;
|
||||
MetaRectangle buffer_rect;
|
||||
MetaRectangle parent_buffer_rect;
|
||||
|
||||
/* If the window disappeared the surface is not coming back. */
|
||||
window = meta_wayland_surface_get_window (surface);
|
||||
if (!window)
|
||||
return;
|
||||
@@ -1130,6 +1162,8 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
if (!surface->buffer_ref.buffer)
|
||||
return;
|
||||
|
||||
surface_role_class->post_apply_state (surface_role, pending);
|
||||
|
||||
if (pending->has_acked_configure_serial)
|
||||
{
|
||||
MetaRectangle window_geometry;
|
||||
@@ -1326,6 +1360,7 @@ meta_wayland_xdg_popup_class_init (MetaWaylandXdgPopupClass *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_xdg_popup_apply_state;
|
||||
surface_role_class->post_apply_state = meta_wayland_xdg_popup_post_apply_state;
|
||||
surface_role_class->get_toplevel = meta_wayland_xdg_popup_get_toplevel;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
@@ -1504,8 +1539,6 @@ meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
||||
MetaWaylandShellSurface *shell_surface =
|
||||
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
||||
MetaWaylandXdgSurfacePrivate *priv =
|
||||
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
@@ -1526,8 +1559,17 @@ meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
|
||||
if (surface->buffer_ref.buffer)
|
||||
priv->first_buffer_attached = TRUE;
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xdg_surface_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceState *pending)
|
||||
{
|
||||
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
||||
MetaWaylandXdgSurfacePrivate *priv =
|
||||
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
||||
MetaWaylandShellSurface *shell_surface =
|
||||
META_WAYLAND_SHELL_SURFACE (surface_role);
|
||||
|
||||
if (pending->has_new_geometry)
|
||||
{
|
||||
@@ -1680,6 +1722,7 @@ meta_wayland_xdg_surface_class_init (MetaWaylandXdgSurfaceClass *klass)
|
||||
|
||||
surface_role_class = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||
surface_role_class->apply_state = meta_wayland_xdg_surface_apply_state;
|
||||
surface_role_class->post_apply_state = meta_wayland_xdg_surface_post_apply_state;
|
||||
surface_role_class->assigned = meta_wayland_xdg_surface_assigned;
|
||||
|
||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||
|
@@ -395,6 +395,8 @@ meta_wayland_init (void)
|
||||
|
||||
meta_wayland_outputs_init (compositor);
|
||||
meta_wayland_data_device_manager_init (compositor);
|
||||
meta_wayland_data_device_primary_manager_init (compositor);
|
||||
meta_wayland_data_device_primary_legacy_manager_init (compositor);
|
||||
meta_wayland_subsurfaces_init (compositor);
|
||||
meta_wayland_shell_init (compositor);
|
||||
meta_wayland_pointer_gestures_init (compositor);
|
||||
|
@@ -230,7 +230,7 @@ xdnd_send_position (MetaXWaylandDnd *dnd,
|
||||
XEvent xev = { 0 };
|
||||
|
||||
user_action = meta_wayland_data_source_get_user_action (source);
|
||||
actions = meta_wayland_data_source_get_actions (source);
|
||||
meta_wayland_data_source_get_actions (source, &actions);
|
||||
|
||||
if (user_action & actions)
|
||||
action = user_action;
|
||||
@@ -367,6 +367,7 @@ transfer_cb (MetaSelection *selection,
|
||||
}
|
||||
|
||||
g_output_stream_close (stream, NULL, NULL);
|
||||
g_object_unref (stream);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -32,13 +32,6 @@
|
||||
#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8"
|
||||
#define STRING_MIMETYPE "text/plain"
|
||||
|
||||
/* Set an arbitrary (although generous) threshold to determine whether a
|
||||
* XFixesSelectionNotify corresponds to a XSetSelectionOwner from another
|
||||
* client. The selection timestamp is not updated if the owner client is
|
||||
* closed.
|
||||
*/
|
||||
#define SELECTION_CLEARED_BY_CLIENT(e) (e->timestamp - e->selection_timestamp < 50)
|
||||
|
||||
static gboolean
|
||||
atom_to_selection_type (Display *xdisplay,
|
||||
Atom selection,
|
||||
@@ -342,7 +335,7 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
|
||||
|
||||
if (event->owner == None && x11_display->selection.owners[selection_type])
|
||||
{
|
||||
if (SELECTION_CLEARED_BY_CLIENT (event))
|
||||
if (event->subtype == XFixesSetSelectionOwnerNotify)
|
||||
{
|
||||
MetaSelectionSource *source;
|
||||
|
||||
|
Reference in New Issue
Block a user