Compare commits
120 Commits
citadel
...
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 | ||
|
dc75c7d297 | ||
|
33c008b90a | ||
|
98a0c5cb35 | ||
|
b425f11536 | ||
|
a1bc2e0adc | ||
|
63fc71f05b | ||
|
31307720bf | ||
|
cb7ba2e90f | ||
|
ba1f4221e9 | ||
|
6e6183ec08 | ||
|
493aeb65c8 | ||
|
36f5a0a491 | ||
|
3daf912449 | ||
|
fadfca2e16 | ||
|
b1df6d08a5 | ||
|
63bf5f1150 | ||
|
d9d8732096 | ||
|
797c349245 | ||
|
b5691d6bf0 | ||
|
c7ad9b33c2 | ||
|
e49297975a | ||
|
858c12e73f | ||
|
b80b465a65 | ||
|
2cc8061f35 | ||
|
dbecb93233 | ||
|
adbe09afc3 | ||
|
bfe9b333c0 | ||
|
06b0d41baf | ||
|
a62fe66a25 | ||
|
5f40493c84 | ||
|
e8d9996c9c | ||
|
5465c912c7 | ||
|
a32bb758f7 | ||
|
ac8075bbf5 | ||
|
da9eb4718b | ||
|
9ad61fe02f | ||
|
7a09d07b9c | ||
|
456e6f345d | ||
|
20cf6b630d | ||
|
1e17f8813b | ||
|
d985517573 | ||
|
107bb3d9c2 | ||
|
b1c47c6213 | ||
|
c43f178495 | ||
|
c46bea9dff | ||
|
622e8c348f | ||
|
51b65b98f5 | ||
|
7ec0a9dd68 | ||
|
6ce42e100f | ||
|
13a23f16c1 | ||
|
40dc22659b | ||
|
fdcb68f4d0 | ||
|
17491bae06 | ||
|
568876da95 | ||
|
ea546a8b90 | ||
|
e8f29a3336 | ||
|
5e9986bbcb | ||
|
3edf6a5292 | ||
|
ad500ef4e5 | ||
|
9a2471db47 | ||
|
db164bcfa2 | ||
|
83553e3f6e | ||
|
3b2f6ae93d | ||
|
bc47f0a1ac | ||
|
c8986d19e5 | ||
|
7baabc7ed0 | ||
|
b0709504ea | ||
|
7e94311e2e | ||
|
e339a57ddf | ||
|
e3b2b90c72 | ||
|
6f094bd399 | ||
|
2c805524b4 | ||
|
95c1baf3d1 | ||
|
6f9b5edd4d | ||
|
31809e1214 | ||
|
82f3bdd14e |
59
NEWS
59
NEWS
@ -1,3 +1,62 @@
|
|||||||
|
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]
|
||||||
|
* Fix monitor screen cast on X11 [Jonas Å.; !1251]
|
||||||
|
* Implement touch-mode detecation for the X11 backend [Carlos; !1278]
|
||||||
|
* Drop external keyboard detection from touch-mode heuristics [Carlos; !1277]
|
||||||
|
* Fix leaked DMA buffers in screencasts [Jonas; !1283]
|
||||||
|
* Fixed crashes [Daniel, Carlos, Jonas D.; !1256, !1258, !1280]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Carlos Garnacho, Daniel van Vugt, Jonas Ådahl
|
||||||
|
|
||||||
|
3.36.2
|
||||||
|
======
|
||||||
|
* Sync timelines to hardware vsync [Daniel; !724]
|
||||||
|
* Fix screencasting non-maximized windows [Jonas; !1174]
|
||||||
|
* Make window-aliveness checks less aggressive [Jonas; !1182]
|
||||||
|
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
|
||||||
|
* Preserve keyboard state on VT switch [Olivier; !1185]
|
||||||
|
* Fix trackball button scrolling [Phillip; #1120]
|
||||||
|
* Fix tiled monitor support [Jonas Å.; !1199]
|
||||||
|
* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206]
|
||||||
|
* Synchronize shadows to server-side decorations [Olivier; !1214]
|
||||||
|
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
|
||||||
|
* Fix capturing with multiple stage views [Jonas Å.; !1222]
|
||||||
|
* Fixed crashes [Jonas D., Carlos; !1173, !1183]
|
||||||
|
* Misc. bug fixes and cleanups [Andre, Georges, Simon, Christian, Carlos, Marco,
|
||||||
|
Pekka, Laurent, Jonas D.; !1169, !1170, !1172, !1168, !1184, !1200, !1209,
|
||||||
|
#1074, !1208]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Marco Trevisan (Treviño), Laurent Bigonville, Jonas Dreßler, Olivier Fourdan,
|
||||||
|
Carlos Garnacho, Andre Moreira Magalhaes, Simon McVittie,
|
||||||
|
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
|
||||||
|
Daniel van Vugt, Phillip Wood, Jonas Ådahl
|
||||||
|
|
||||||
|
Translators:
|
||||||
|
Dušan Kazik [sk], Christian Kirbach [de]
|
||||||
|
|
||||||
3.36.1
|
3.36.1
|
||||||
======
|
======
|
||||||
* Fix hardware cursor on GPU hotplpug [Pekka; !1097]
|
* Fix hardware cursor on GPU hotplpug [Pekka; !1097]
|
||||||
|
@ -2410,6 +2410,7 @@ clutter_actor_should_pick_paint (ClutterActor *self)
|
|||||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||||
|
|
||||||
if (CLUTTER_ACTOR_IS_MAPPED (self) &&
|
if (CLUTTER_ACTOR_IS_MAPPED (self) &&
|
||||||
|
clutter_actor_has_allocation (self) &&
|
||||||
(_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL ||
|
(_clutter_context_get_pick_mode () == CLUTTER_PICK_ALL ||
|
||||||
CLUTTER_ACTOR_IS_REACTIVE (self)))
|
CLUTTER_ACTOR_IS_REACTIVE (self)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -2603,6 +2604,9 @@ clutter_actor_set_allocation_internal (ClutterActor *self,
|
|||||||
gboolean retval;
|
gboolean retval;
|
||||||
ClutterActorBox old_alloc = { 0, };
|
ClutterActorBox old_alloc = { 0, };
|
||||||
|
|
||||||
|
g_return_val_if_fail (!isnan (box->x1) && !isnan (box->x2) &&
|
||||||
|
!isnan (box->y1) && !isnan (box->y2), FALSE);
|
||||||
|
|
||||||
obj = G_OBJECT (self);
|
obj = G_OBJECT (self);
|
||||||
|
|
||||||
g_object_freeze_notify (obj);
|
g_object_freeze_notify (obj);
|
||||||
@ -4193,7 +4197,9 @@ clutter_actor_continue_paint (ClutterActor *self,
|
|||||||
clutter_paint_node_unref (dummy);
|
clutter_paint_node_unref (dummy);
|
||||||
|
|
||||||
/* XXX:2.0 - Call the paint() virtual directly */
|
/* XXX:2.0 - Call the paint() virtual directly */
|
||||||
if (g_signal_has_handler_pending (self, actor_signals[PAINT],
|
if (!(clutter_paint_context_get_paint_flags (paint_context) &
|
||||||
|
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL) &&
|
||||||
|
g_signal_has_handler_pending (self, actor_signals[PAINT],
|
||||||
0, TRUE))
|
0, TRUE))
|
||||||
g_signal_emit (self, actor_signals[PAINT], 0, paint_context);
|
g_signal_emit (self, actor_signals[PAINT], 0, paint_context);
|
||||||
else
|
else
|
||||||
@ -10363,6 +10369,11 @@ clutter_actor_allocate (ClutterActor *self,
|
|||||||
old_allocation = priv->allocation;
|
old_allocation = priv->allocation;
|
||||||
real_allocation = *box;
|
real_allocation = *box;
|
||||||
|
|
||||||
|
g_return_if_fail (!isnan (real_allocation.x1) &&
|
||||||
|
!isnan (real_allocation.x2) &&
|
||||||
|
!isnan (real_allocation.y1) &&
|
||||||
|
!isnan (real_allocation.y2));
|
||||||
|
|
||||||
/* constraints are allowed to modify the allocation only here; we do
|
/* constraints are allowed to modify the allocation only here; we do
|
||||||
* this prior to all the other checks so that we can bail out if the
|
* this prior to all the other checks so that we can bail out if the
|
||||||
* allocation did not change
|
* allocation did not change
|
||||||
|
@ -475,8 +475,10 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
|||||||
ClutterActor *child;
|
ClutterActor *child;
|
||||||
gint n_children = 0;
|
gint n_children = 0;
|
||||||
gfloat minimum, natural;
|
gfloat minimum, natural;
|
||||||
|
float largest_min_size, largest_nat_size;
|
||||||
|
|
||||||
minimum = natural = 0;
|
minimum = natural = 0;
|
||||||
|
largest_min_size = largest_nat_size = 0;
|
||||||
|
|
||||||
clutter_actor_iter_init (&iter, container);
|
clutter_actor_iter_init (&iter, container);
|
||||||
while (clutter_actor_iter_next (&iter, &child))
|
while (clutter_actor_iter_next (&iter, &child))
|
||||||
@ -491,8 +493,22 @@ get_preferred_size_for_orientation (ClutterBoxLayout *self,
|
|||||||
get_child_size (child, priv->orientation,
|
get_child_size (child, priv->orientation,
|
||||||
for_size, &child_min, &child_nat);
|
for_size, &child_min, &child_nat);
|
||||||
|
|
||||||
minimum += child_min;
|
if (priv->is_homogeneous)
|
||||||
natural += child_nat;
|
{
|
||||||
|
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)
|
if (n_children > 1)
|
||||||
@ -623,6 +639,8 @@ get_preferred_size_for_opposite_orientation (ClutterBoxLayout *self,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
size -= (nvis_children - 1) * priv->spacing;
|
||||||
|
|
||||||
/* Bring children up to size first */
|
/* Bring children up to size first */
|
||||||
if (isnormal (size) || size == 0)
|
if (isnormal (size) || size == 0)
|
||||||
{
|
{
|
||||||
|
@ -346,6 +346,12 @@ on_captured_event (ClutterActor *stage,
|
|||||||
ClutterModifierType modifier_state;
|
ClutterModifierType modifier_state;
|
||||||
gboolean has_button = TRUE;
|
gboolean has_button = TRUE;
|
||||||
|
|
||||||
|
if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action)))
|
||||||
|
{
|
||||||
|
clutter_click_action_release (action);
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
|
||||||
|
|
||||||
switch (clutter_event_type (event))
|
switch (clutter_event_type (event))
|
||||||
|
@ -190,6 +190,26 @@ master_clock_get_swap_wait_time (ClutterMasterClockDefault *master_clock)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
master_clock_get_next_presentation_time (ClutterMasterClockDefault *master_clock)
|
||||||
|
{
|
||||||
|
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||||
|
const GSList *stages, *l;
|
||||||
|
int64_t earliest = -1;
|
||||||
|
|
||||||
|
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||||
|
|
||||||
|
for (l = stages; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
gint64 t = _clutter_stage_get_next_presentation_time (l->data);
|
||||||
|
|
||||||
|
if (earliest == -1 || (t != -1 && t < earliest))
|
||||||
|
earliest = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
return earliest;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
|
master_clock_schedule_stage_updates (ClutterMasterClockDefault *master_clock)
|
||||||
{
|
{
|
||||||
@ -466,7 +486,11 @@ clutter_clock_dispatch (GSource *source,
|
|||||||
COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)");
|
COGL_TRACE_BEGIN (ClutterMasterClockTick, "Master Clock (tick)");
|
||||||
|
|
||||||
/* Get the time to use for this frame */
|
/* Get the time to use for this frame */
|
||||||
master_clock->cur_tick = g_source_get_time (source);
|
master_clock->cur_tick = master_clock_get_next_presentation_time (master_clock);
|
||||||
|
|
||||||
|
/* On the first frame the backend might not have an answer */
|
||||||
|
if (master_clock->cur_tick <= 0)
|
||||||
|
master_clock->cur_tick = g_source_get_time (source);
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
#ifdef CLUTTER_ENABLE_DEBUG
|
||||||
master_clock->remaining_budget = master_clock->frame_budget;
|
master_clock->remaining_budget = master_clock->frame_budget;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "clutter-input-device-private.h"
|
#include "clutter-input-device-private.h"
|
||||||
#include "clutter-input-pointer-a11y-private.h"
|
#include "clutter-input-pointer-a11y-private.h"
|
||||||
#include "clutter-macros.h"
|
#include "clutter-macros.h"
|
||||||
|
#include "clutter-paint-context-private.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-stage-private.h"
|
#include "clutter-stage-private.h"
|
||||||
#include "clutter-stage-view.h"
|
#include "clutter-stage-view.h"
|
||||||
@ -48,6 +49,23 @@ void clutter_stage_capture_into (ClutterStage *stage,
|
|||||||
cairo_rectangle_int_t *rect,
|
cairo_rectangle_int_t *rect,
|
||||||
uint8_t *data);
|
uint8_t *data);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
void clutter_stage_paint_to_framebuffer (ClutterStage *stage,
|
||||||
|
CoglFramebuffer *framebuffer,
|
||||||
|
const cairo_rectangle_int_t *rect,
|
||||||
|
float scale,
|
||||||
|
ClutterPaintFlag paint_flags);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||||
|
const cairo_rectangle_int_t *rect,
|
||||||
|
float scale,
|
||||||
|
uint8_t *data,
|
||||||
|
int stride,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
ClutterPaintFlag paint_flags,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
CLUTTER_EXPORT
|
CLUTTER_EXPORT
|
||||||
void clutter_stage_freeze_updates (ClutterStage *stage);
|
void clutter_stage_freeze_updates (ClutterStage *stage);
|
||||||
|
|
||||||
|
@ -20,11 +20,22 @@
|
|||||||
|
|
||||||
#include "clutter-paint-context.h"
|
#include "clutter-paint-context.h"
|
||||||
|
|
||||||
|
typedef enum _ClutterPaintFlag
|
||||||
|
{
|
||||||
|
CLUTTER_PAINT_FLAG_NONE = 0,
|
||||||
|
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
|
||||||
|
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL = 1 << 1,
|
||||||
|
} ClutterPaintFlag;
|
||||||
|
|
||||||
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
|
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||||
const cairo_region_t *redraw_clip);
|
const cairo_region_t *redraw_clip,
|
||||||
|
ClutterPaintFlag paint_flags);
|
||||||
|
|
||||||
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
|
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);
|
||||||
|
|
||||||
CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
|
CoglFramebuffer * clutter_paint_context_get_base_framebuffer (ClutterPaintContext *paint_context);
|
||||||
|
|
||||||
|
CLUTTER_EXPORT
|
||||||
|
ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context);
|
||||||
|
|
||||||
#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
|
#endif /* CLUTTER_PAINT_CONTEXT_PRIVATE_H */
|
||||||
|
@ -23,6 +23,8 @@ struct _ClutterPaintContext
|
|||||||
{
|
{
|
||||||
grefcount ref_count;
|
grefcount ref_count;
|
||||||
|
|
||||||
|
ClutterPaintFlag paint_flags;
|
||||||
|
|
||||||
GList *framebuffers;
|
GList *framebuffers;
|
||||||
|
|
||||||
ClutterStageView *view;
|
ClutterStageView *view;
|
||||||
@ -36,7 +38,8 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
|
|||||||
|
|
||||||
ClutterPaintContext *
|
ClutterPaintContext *
|
||||||
clutter_paint_context_new_for_view (ClutterStageView *view,
|
clutter_paint_context_new_for_view (ClutterStageView *view,
|
||||||
const cairo_region_t *redraw_clip)
|
const cairo_region_t *redraw_clip,
|
||||||
|
ClutterPaintFlag paint_flags)
|
||||||
{
|
{
|
||||||
ClutterPaintContext *paint_context;
|
ClutterPaintContext *paint_context;
|
||||||
CoglFramebuffer *framebuffer;
|
CoglFramebuffer *framebuffer;
|
||||||
@ -45,6 +48,7 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
|
|||||||
g_ref_count_init (&paint_context->ref_count);
|
g_ref_count_init (&paint_context->ref_count);
|
||||||
paint_context->view = view;
|
paint_context->view = view;
|
||||||
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
|
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
|
||||||
|
paint_context->paint_flags = paint_flags;
|
||||||
|
|
||||||
framebuffer = clutter_stage_view_get_framebuffer (view);
|
framebuffer = clutter_stage_view_get_framebuffer (view);
|
||||||
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
|
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
|
||||||
@ -62,6 +66,8 @@ clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer)
|
|||||||
|
|
||||||
paint_context = g_new0 (ClutterPaintContext, 1);
|
paint_context = g_new0 (ClutterPaintContext, 1);
|
||||||
g_ref_count_init (&paint_context->ref_count);
|
g_ref_count_init (&paint_context->ref_count);
|
||||||
|
paint_context->paint_flags = (CLUTTER_PAINT_FLAG_NO_CURSORS |
|
||||||
|
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL);
|
||||||
|
|
||||||
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
|
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
|
||||||
|
|
||||||
@ -170,3 +176,12 @@ clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context)
|
|||||||
|
|
||||||
return !paint_context->view;
|
return !paint_context->view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_paint_context_get_paint_flags: (skip)
|
||||||
|
*/
|
||||||
|
ClutterPaintFlag
|
||||||
|
clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context)
|
||||||
|
{
|
||||||
|
return paint_context->paint_flags;
|
||||||
|
}
|
||||||
|
@ -682,7 +682,6 @@ clutter_seat_warp_pointer (ClutterSeat *seat,
|
|||||||
* requirements are fulfilled:
|
* requirements are fulfilled:
|
||||||
*
|
*
|
||||||
* - A touchscreen is available
|
* - A touchscreen is available
|
||||||
* - No external keyboard is attached to the device
|
|
||||||
* - A tablet mode switch, if present, is enabled
|
* - A tablet mode switch, if present, is enabled
|
||||||
*
|
*
|
||||||
* Returns: %TRUE if the device is a tablet that doesn't have an external
|
* Returns: %TRUE if the device is a tablet that doesn't have an external
|
||||||
|
@ -78,6 +78,7 @@ void _clutter_stage_schedule_update (ClutterStage *stage);
|
|||||||
gint64 _clutter_stage_get_update_time (ClutterStage *stage);
|
gint64 _clutter_stage_get_update_time (ClutterStage *stage);
|
||||||
void _clutter_stage_clear_update_time (ClutterStage *stage);
|
void _clutter_stage_clear_update_time (ClutterStage *stage);
|
||||||
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
||||||
|
int64_t _clutter_stage_get_next_presentation_time (ClutterStage *stage);
|
||||||
|
|
||||||
void clutter_stage_log_pick (ClutterStage *stage,
|
void clutter_stage_log_pick (ClutterStage *stage,
|
||||||
const graphene_point_t *vertices,
|
const graphene_point_t *vertices,
|
||||||
|
@ -178,6 +178,22 @@ _clutter_stage_window_clear_update_time (ClutterStageWindow *window)
|
|||||||
iface->clear_update_time (window);
|
iface->clear_update_time (window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
_clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window)
|
||||||
|
{
|
||||||
|
ClutterStageWindowInterface *iface;
|
||||||
|
|
||||||
|
g_return_val_if_fail (CLUTTER_IS_STAGE_WINDOW (window), 0);
|
||||||
|
|
||||||
|
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||||
|
|
||||||
|
/* If not implemented then just revert to the old behaviour... */
|
||||||
|
if (iface->get_next_presentation_time == NULL)
|
||||||
|
return _clutter_stage_window_get_update_time (window);
|
||||||
|
|
||||||
|
return iface->get_next_presentation_time (window);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
_clutter_stage_window_set_accept_focus (ClutterStageWindow *window,
|
||||||
gboolean accept_focus)
|
gboolean accept_focus)
|
||||||
|
@ -61,6 +61,8 @@ struct _ClutterStageWindowInterface
|
|||||||
GList *(* get_views) (ClutterStageWindow *stage_window);
|
GList *(* get_views) (ClutterStageWindow *stage_window);
|
||||||
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
|
int64_t (* get_frame_counter) (ClutterStageWindow *stage_window);
|
||||||
void (* finish_frame) (ClutterStageWindow *stage_window);
|
void (* finish_frame) (ClutterStageWindow *stage_window);
|
||||||
|
|
||||||
|
int64_t (* get_next_presentation_time) (ClutterStageWindow *stage_window);
|
||||||
};
|
};
|
||||||
|
|
||||||
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
|
ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *window);
|
||||||
@ -101,6 +103,8 @@ void _clutter_stage_window_finish_frame (ClutterStageWin
|
|||||||
|
|
||||||
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);
|
int64_t _clutter_stage_window_get_frame_counter (ClutterStageWindow *window);
|
||||||
|
|
||||||
|
int64_t _clutter_stage_window_get_next_presentation_time (ClutterStageWindow *window);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_STAGE_WINDOW_H__ */
|
#endif /* __CLUTTER_STAGE_WINDOW_H__ */
|
||||||
|
@ -934,7 +934,8 @@ clutter_stage_do_paint_view (ClutterStage *stage,
|
|||||||
ClutterPaintContext *paint_context;
|
ClutterPaintContext *paint_context;
|
||||||
cairo_rectangle_int_t clip_rect;
|
cairo_rectangle_int_t clip_rect;
|
||||||
|
|
||||||
paint_context = clutter_paint_context_new_for_view (view, redraw_clip);
|
paint_context = clutter_paint_context_new_for_view (view, redraw_clip,
|
||||||
|
CLUTTER_PAINT_FLAG_NONE);
|
||||||
|
|
||||||
cairo_region_get_extents (redraw_clip, &clip_rect);
|
cairo_region_get_extents (redraw_clip, &clip_rect);
|
||||||
setup_view_for_pick_or_paint (stage, view, &clip_rect);
|
setup_view_for_pick_or_paint (stage, view, &clip_rect);
|
||||||
@ -1320,15 +1321,9 @@ clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
|||||||
{
|
{
|
||||||
ClutterStagePrivate *priv = stage->priv;
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
|
|
||||||
if (g_hash_table_contains (priv->pending_relayouts, stage))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (g_hash_table_size (priv->pending_relayouts) == 0)
|
if (g_hash_table_size (priv->pending_relayouts) == 0)
|
||||||
_clutter_stage_schedule_update (stage);
|
_clutter_stage_schedule_update (stage);
|
||||||
|
|
||||||
if (actor == (ClutterActor *) stage)
|
|
||||||
g_hash_table_remove_all (priv->pending_relayouts);
|
|
||||||
|
|
||||||
g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
|
g_hash_table_add (priv->pending_relayouts, g_object_ref (actor));
|
||||||
priv->pending_relayouts_version++;
|
priv->pending_relayouts_version++;
|
||||||
}
|
}
|
||||||
@ -3751,6 +3746,21 @@ _clutter_stage_clear_update_time (ClutterStage *stage)
|
|||||||
_clutter_stage_window_clear_update_time (stage_window);
|
_clutter_stage_window_clear_update_time (stage_window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t
|
||||||
|
_clutter_stage_get_next_presentation_time (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
ClutterStageWindow *stage_window;
|
||||||
|
|
||||||
|
if (CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
stage_window = _clutter_stage_get_window (stage);
|
||||||
|
if (stage_window == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return _clutter_stage_window_get_next_presentation_time (stage_window);
|
||||||
|
}
|
||||||
|
|
||||||
ClutterPaintVolume *
|
ClutterPaintVolume *
|
||||||
_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage)
|
_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage)
|
||||||
{
|
{
|
||||||
@ -4463,6 +4473,100 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_paint_to_framebuffer: (skip)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clutter_stage_paint_to_framebuffer (ClutterStage *stage,
|
||||||
|
CoglFramebuffer *framebuffer,
|
||||||
|
const cairo_rectangle_int_t *rect,
|
||||||
|
float scale,
|
||||||
|
ClutterPaintFlag paint_flags)
|
||||||
|
{
|
||||||
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
|
ClutterPaintContext *paint_context;
|
||||||
|
cairo_region_t *redraw_clip;
|
||||||
|
|
||||||
|
redraw_clip = cairo_region_create_rectangle (rect);
|
||||||
|
paint_context = clutter_paint_context_new_for_framebuffer (framebuffer);
|
||||||
|
cairo_region_destroy (redraw_clip);
|
||||||
|
|
||||||
|
cogl_framebuffer_push_matrix (framebuffer);
|
||||||
|
cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection);
|
||||||
|
cogl_framebuffer_set_viewport (framebuffer,
|
||||||
|
-(rect->x * scale),
|
||||||
|
-(rect->y * scale),
|
||||||
|
priv->viewport[2] * scale,
|
||||||
|
priv->viewport[3] * scale);
|
||||||
|
clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
|
||||||
|
cogl_framebuffer_pop_matrix (framebuffer);
|
||||||
|
|
||||||
|
clutter_paint_context_destroy (paint_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_paint_to_buffer: (skip)
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_stage_paint_to_buffer (ClutterStage *stage,
|
||||||
|
const cairo_rectangle_int_t *rect,
|
||||||
|
float scale,
|
||||||
|
uint8_t *data,
|
||||||
|
int stride,
|
||||||
|
CoglPixelFormat format,
|
||||||
|
ClutterPaintFlag paint_flags,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
int texture_width, texture_height;
|
||||||
|
CoglTexture2D *texture;
|
||||||
|
CoglOffscreen *offscreen;
|
||||||
|
CoglFramebuffer *framebuffer;
|
||||||
|
CoglBitmap *bitmap;
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Failed to create %dx%d texture",
|
||||||
|
texture_width, texture_height);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
|
||||||
|
framebuffer = COGL_FRAMEBUFFER (offscreen);
|
||||||
|
|
||||||
|
cogl_object_unref (texture);
|
||||||
|
|
||||||
|
if (!cogl_framebuffer_allocate (framebuffer, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
clutter_stage_paint_to_framebuffer (stage, framebuffer,
|
||||||
|
rect, scale, paint_flags);
|
||||||
|
|
||||||
|
bitmap = cogl_bitmap_new_for_data (cogl_context,
|
||||||
|
texture_width, texture_height,
|
||||||
|
format,
|
||||||
|
stride,
|
||||||
|
data);
|
||||||
|
|
||||||
|
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
|
||||||
|
0, 0,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
bitmap);
|
||||||
|
|
||||||
|
cogl_object_unref (bitmap);
|
||||||
|
cogl_object_unref (framebuffer);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
capture_view_into (ClutterStage *stage,
|
capture_view_into (ClutterStage *stage,
|
||||||
gboolean paint,
|
gboolean paint,
|
||||||
@ -4471,50 +4575,17 @@ capture_view_into (ClutterStage *stage,
|
|||||||
uint8_t *data,
|
uint8_t *data,
|
||||||
int stride)
|
int stride)
|
||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer;
|
g_autoptr (GError) error = NULL;
|
||||||
ClutterBackend *backend;
|
|
||||||
CoglContext *context;
|
|
||||||
CoglBitmap *bitmap;
|
|
||||||
cairo_rectangle_int_t view_layout;
|
|
||||||
float view_scale;
|
float view_scale;
|
||||||
float texture_width;
|
|
||||||
float texture_height;
|
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||||
|
|
||||||
framebuffer = clutter_stage_view_get_framebuffer (view);
|
|
||||||
|
|
||||||
if (paint)
|
|
||||||
{
|
|
||||||
cairo_region_t *region;
|
|
||||||
|
|
||||||
_clutter_stage_maybe_setup_viewport (stage, view);
|
|
||||||
region = cairo_region_create_rectangle (rect);
|
|
||||||
clutter_stage_do_paint_view (stage, view, region);
|
|
||||||
cairo_region_destroy (region);
|
|
||||||
}
|
|
||||||
|
|
||||||
view_scale = clutter_stage_view_get_scale (view);
|
view_scale = clutter_stage_view_get_scale (view);
|
||||||
texture_width = roundf (rect->width * view_scale);
|
if (!clutter_stage_paint_to_buffer (stage, rect, view_scale, data, stride,
|
||||||
texture_height = roundf (rect->height * view_scale);
|
CLUTTER_CAIRO_FORMAT_ARGB32,
|
||||||
|
CLUTTER_PAINT_FLAG_NO_CURSORS,
|
||||||
backend = clutter_get_default_backend ();
|
&error))
|
||||||
context = clutter_backend_get_cogl_context (backend);
|
g_warning ("Failed to capture stage: %s", error->message);
|
||||||
bitmap = cogl_bitmap_new_for_data (context,
|
|
||||||
texture_width, texture_height,
|
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
|
||||||
stride,
|
|
||||||
data);
|
|
||||||
|
|
||||||
clutter_stage_view_get_layout (view, &view_layout);
|
|
||||||
|
|
||||||
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
|
|
||||||
roundf ((rect->x - view_layout.x) * view_scale),
|
|
||||||
roundf ((rect->y - view_layout.y) * view_scale),
|
|
||||||
COGL_READ_PIXELS_COLOR_BUFFER,
|
|
||||||
bitmap);
|
|
||||||
|
|
||||||
cogl_object_unref (bitmap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -235,7 +235,12 @@ clutter_stage_cogl_schedule_update (ClutterStageWindow *stage_window,
|
|||||||
stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
|
stage_cogl->update_time = next_presentation_time - max_render_time_allowed;
|
||||||
|
|
||||||
if (stage_cogl->update_time == stage_cogl->last_update_time)
|
if (stage_cogl->update_time == stage_cogl->last_update_time)
|
||||||
stage_cogl->update_time = stage_cogl->last_update_time + refresh_interval;
|
{
|
||||||
|
stage_cogl->update_time += refresh_interval;
|
||||||
|
next_presentation_time += refresh_interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
stage_cogl->next_presentation_time = next_presentation_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint64
|
static gint64
|
||||||
@ -256,6 +261,29 @@ clutter_stage_cogl_clear_update_time (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
stage_cogl->last_update_time = stage_cogl->update_time;
|
stage_cogl->last_update_time = stage_cogl->update_time;
|
||||||
stage_cogl->update_time = -1;
|
stage_cogl->update_time = -1;
|
||||||
|
stage_cogl->next_presentation_time = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t
|
||||||
|
clutter_stage_cogl_get_next_presentation_time (ClutterStageWindow *stage_window)
|
||||||
|
{
|
||||||
|
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_window);
|
||||||
|
int64_t now = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
if (stage_cogl->next_presentation_time > 0 &&
|
||||||
|
stage_cogl->next_presentation_time <= now)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (BACKEND,
|
||||||
|
"Missed some frames. Something blocked for over "
|
||||||
|
"%" G_GINT64_FORMAT "ms.",
|
||||||
|
(now - stage_cogl->next_presentation_time) / 1000);
|
||||||
|
|
||||||
|
stage_cogl->update_time = -1;
|
||||||
|
clutter_stage_cogl_schedule_update (stage_window,
|
||||||
|
stage_cogl->last_sync_delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stage_cogl->next_presentation_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterActor *
|
static ClutterActor *
|
||||||
@ -375,15 +403,11 @@ static gboolean
|
|||||||
swap_framebuffer (ClutterStageWindow *stage_window,
|
swap_framebuffer (ClutterStageWindow *stage_window,
|
||||||
ClutterStageView *view,
|
ClutterStageView *view,
|
||||||
cairo_region_t *swap_region,
|
cairo_region_t *swap_region,
|
||||||
gboolean swap_with_damage,
|
gboolean swap_with_damage)
|
||||||
cairo_region_t *queued_redraw_clip)
|
|
||||||
{
|
{
|
||||||
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
|
||||||
int *damage, n_rects, i;
|
int *damage, n_rects, i;
|
||||||
|
|
||||||
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
|
|
||||||
paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
|
|
||||||
|
|
||||||
n_rects = cairo_region_num_rectangles (swap_region);
|
n_rects = cairo_region_num_rectangles (swap_region);
|
||||||
damage = g_newa (int, n_rects * 4);
|
damage = g_newa (int, n_rects * 4);
|
||||||
for (i = 0; i < n_rects; i++)
|
for (i = 0; i < n_rects; i++)
|
||||||
@ -620,7 +644,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
gboolean swap_with_damage;
|
gboolean swap_with_damage;
|
||||||
ClutterActor *wrapper;
|
ClutterActor *wrapper;
|
||||||
cairo_region_t *redraw_clip;
|
cairo_region_t *redraw_clip;
|
||||||
cairo_region_t *queued_redraw_clip;
|
cairo_region_t *queued_redraw_clip = NULL;
|
||||||
cairo_region_t *fb_clip_region;
|
cairo_region_t *fb_clip_region;
|
||||||
cairo_region_t *swap_region;
|
cairo_region_t *swap_region;
|
||||||
cairo_rectangle_int_t redraw_rect;
|
cairo_rectangle_int_t redraw_rect;
|
||||||
@ -644,6 +668,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
|
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
|
||||||
|
|
||||||
redraw_clip = clutter_stage_view_take_redraw_clip (view);
|
redraw_clip = clutter_stage_view_take_redraw_clip (view);
|
||||||
|
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION))
|
||||||
|
queued_redraw_clip = cairo_region_copy (redraw_clip);
|
||||||
|
|
||||||
/* NB: a NULL redraw clip == full stage redraw */
|
/* NB: a NULL redraw clip == full stage redraw */
|
||||||
if (!redraw_clip)
|
if (!redraw_clip)
|
||||||
@ -711,8 +737,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
redraw_clip = cairo_region_create_rectangle (&view_rect);
|
redraw_clip = cairo_region_create_rectangle (&view_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
queued_redraw_clip = cairo_region_copy (redraw_clip);
|
|
||||||
|
|
||||||
if (may_use_clipped_redraw &&
|
if (may_use_clipped_redraw &&
|
||||||
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
|
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
|
||||||
use_clipped_redraw = TRUE;
|
use_clipped_redraw = TRUE;
|
||||||
@ -922,7 +946,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&redraw_clip, cairo_region_destroy);
|
g_clear_pointer (&redraw_clip, cairo_region_destroy);
|
||||||
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
|
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
|
||||||
|
|
||||||
if (do_swap_buffer)
|
if (do_swap_buffer)
|
||||||
@ -943,11 +966,17 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
swap_region = transformed_swap_region;
|
swap_region = transformed_swap_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (queued_redraw_clip)
|
||||||
|
{
|
||||||
|
paint_damage_region (stage_window, view,
|
||||||
|
swap_region, queued_redraw_clip);
|
||||||
|
cairo_region_destroy (queued_redraw_clip);
|
||||||
|
}
|
||||||
|
|
||||||
res = swap_framebuffer (stage_window,
|
res = swap_framebuffer (stage_window,
|
||||||
view,
|
view,
|
||||||
swap_region,
|
swap_region,
|
||||||
swap_with_damage,
|
swap_with_damage);
|
||||||
queued_redraw_clip);
|
|
||||||
|
|
||||||
cairo_region_destroy (swap_region);
|
cairo_region_destroy (swap_region);
|
||||||
|
|
||||||
@ -955,6 +984,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1008,6 +1038,7 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
|
|||||||
iface->schedule_update = clutter_stage_cogl_schedule_update;
|
iface->schedule_update = clutter_stage_cogl_schedule_update;
|
||||||
iface->get_update_time = clutter_stage_cogl_get_update_time;
|
iface->get_update_time = clutter_stage_cogl_get_update_time;
|
||||||
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
|
iface->clear_update_time = clutter_stage_cogl_clear_update_time;
|
||||||
|
iface->get_next_presentation_time = clutter_stage_cogl_get_next_presentation_time;
|
||||||
iface->redraw = clutter_stage_cogl_redraw;
|
iface->redraw = clutter_stage_cogl_redraw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,6 +1084,7 @@ _clutter_stage_cogl_init (ClutterStageCogl *stage)
|
|||||||
stage->refresh_rate = 0.0;
|
stage->refresh_rate = 0.0;
|
||||||
|
|
||||||
stage->update_time = -1;
|
stage->update_time = -1;
|
||||||
|
stage->next_presentation_time = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -48,6 +48,7 @@ struct _ClutterStageCogl
|
|||||||
gint64 last_presentation_time;
|
gint64 last_presentation_time;
|
||||||
gint64 update_time;
|
gint64 update_time;
|
||||||
int64_t last_update_time;
|
int64_t last_update_time;
|
||||||
|
int64_t next_presentation_time;
|
||||||
|
|
||||||
/* We only enable clipped redraws after 2 frames, since we've seen
|
/* We only enable clipped redraws after 2 frames, since we've seen
|
||||||
* a lot of drivers can struggle to get going and may output some
|
* a lot of drivers can struggle to get going and may output some
|
||||||
|
@ -121,6 +121,9 @@ cogl_texture_2d_new_with_size (CoglContext *ctx,
|
|||||||
{
|
{
|
||||||
CoglTextureLoader *loader;
|
CoglTextureLoader *loader;
|
||||||
|
|
||||||
|
g_return_val_if_fail (width >= 1, NULL);
|
||||||
|
g_return_val_if_fail (height >= 1, NULL);
|
||||||
|
|
||||||
loader = _cogl_texture_create_loader ();
|
loader = _cogl_texture_create_loader ();
|
||||||
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
loader->src_type = COGL_TEXTURE_SOURCE_TYPE_SIZED;
|
||||||
loader->src.sized.width = width;
|
loader->src.sized.width = width;
|
||||||
|
@ -132,8 +132,8 @@ _cogl_framebuffer_gl_flush_viewport_state (CoglFramebuffer *framebuffer)
|
|||||||
{
|
{
|
||||||
float gl_viewport_y;
|
float gl_viewport_y;
|
||||||
|
|
||||||
g_assert (framebuffer->viewport_width >=0 &&
|
g_return_if_fail (framebuffer->viewport_width >= 0);
|
||||||
framebuffer->viewport_height >=0);
|
g_return_if_fail (framebuffer->viewport_height >= 0);
|
||||||
|
|
||||||
/* Convert the Cogl viewport y offset to an OpenGL viewport y offset
|
/* Convert the Cogl viewport y offset to an OpenGL viewport y offset
|
||||||
* NB: OpenGL defines its window and viewport origins to be bottom
|
* NB: OpenGL defines its window and viewport origins to be bottom
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
project('mutter', 'c',
|
project('mutter', 'c',
|
||||||
version: '3.36.1',
|
version: '3.36.4',
|
||||||
meson_version: '>= 0.50.0',
|
meson_version: '>= 0.50.0',
|
||||||
license: 'GPLv2+'
|
license: 'GPLv2+'
|
||||||
)
|
)
|
||||||
|
85
po/de.po
85
po/de.po
@ -13,8 +13,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: mutter master\n"
|
"Project-Id-Version: mutter master\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||||
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
|
"POT-Creation-Date: 2020-03-30 20:11+0000\n"
|
||||||
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
|
"PO-Revision-Date: 2020-04-06 23:13+0200\n"
|
||||||
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
|
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
|
||||||
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@ -22,7 +22,7 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Generator: Poedit 2.2.1\n"
|
"X-Generator: Poedit 2.3\n"
|
||||||
|
|
||||||
#: data/50-mutter-navigation.xml:6
|
#: data/50-mutter-navigation.xml:6
|
||||||
msgid "Navigation"
|
msgid "Navigation"
|
||||||
@ -435,20 +435,33 @@ msgstr "Zusatztaste zum Finden des Zeigers"
|
|||||||
msgid "This key will initiate the “locate pointer” action."
|
msgid "This key will initiate the “locate pointer” action."
|
||||||
msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen."
|
msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen."
|
||||||
|
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:155
|
#: data/org.gnome.mutter.gschema.xml.in:142
|
||||||
|
msgid "Timeout for check-alive ping"
|
||||||
|
msgstr "Reaktionsschwellwert bei Kontaktkontrolle"
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:143
|
||||||
|
msgid ""
|
||||||
|
"Number of milliseconds a client has to respond to a ping request in order to "
|
||||||
|
"not be detected as frozen. Using 0 will disable the alive check completely."
|
||||||
|
msgstr ""
|
||||||
|
"Zeit in Millisekunden, innerhalb welcher ein Client auf eine "
|
||||||
|
"Kontaktkontrolle antworten muss, um nicht als abgestürzt zu gelten. »0« "
|
||||||
|
"bedeutet, dass die Kontaktkontrolle ausgeschaltet wird."
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:165
|
||||||
msgid "Select window from tab popup"
|
msgid "Select window from tab popup"
|
||||||
msgstr "Fenster aus Tab-Anzeige auswählen"
|
msgstr "Fenster aus Tab-Anzeige auswählen"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:160
|
#: data/org.gnome.mutter.gschema.xml.in:170
|
||||||
msgid "Cancel tab popup"
|
msgid "Cancel tab popup"
|
||||||
msgstr "Tab-Anzeige abbrechen"
|
msgstr "Tab-Anzeige abbrechen"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:165
|
#: data/org.gnome.mutter.gschema.xml.in:175
|
||||||
msgid "Switch monitor configurations"
|
msgid "Switch monitor configurations"
|
||||||
msgstr "Bildschirmkonfigurationen wechseln"
|
msgstr "Bildschirmkonfigurationen wechseln"
|
||||||
|
|
||||||
# Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird.
|
# Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird.
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:170
|
#: data/org.gnome.mutter.gschema.xml.in:180
|
||||||
msgid "Rotates the built-in monitor configuration"
|
msgid "Rotates the built-in monitor configuration"
|
||||||
msgstr "Wechselt die Konfiguration des eingebauten Bildschirms"
|
msgstr "Wechselt die Konfiguration des eingebauten Bildschirms"
|
||||||
|
|
||||||
@ -569,7 +582,7 @@ msgstr ""
|
|||||||
#. TRANSLATORS: This string refers to a button that switches between
|
#. TRANSLATORS: This string refers to a button that switches between
|
||||||
#. * different modes.
|
#. * different modes.
|
||||||
#.
|
#.
|
||||||
#: src/backends/meta-input-settings.c:2531
|
#: src/backends/meta-input-settings.c:2631
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Mode Switch (Group %d)"
|
msgid "Mode Switch (Group %d)"
|
||||||
msgstr "Moduswechsel (Gruppe %d)"
|
msgstr "Moduswechsel (Gruppe %d)"
|
||||||
@ -577,34 +590,34 @@ msgstr "Moduswechsel (Gruppe %d)"
|
|||||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||||
#. * mapping through the available outputs.
|
#. * mapping through the available outputs.
|
||||||
#.
|
#.
|
||||||
#: src/backends/meta-input-settings.c:2554
|
#: src/backends/meta-input-settings.c:2654
|
||||||
msgid "Switch monitor"
|
msgid "Switch monitor"
|
||||||
msgstr "Bildschirm wechseln"
|
msgstr "Bildschirm wechseln"
|
||||||
|
|
||||||
#: src/backends/meta-input-settings.c:2556
|
#: src/backends/meta-input-settings.c:2656
|
||||||
msgid "Show on-screen help"
|
msgid "Show on-screen help"
|
||||||
msgstr "Bildschirmhilfe anzeigen"
|
msgstr "Bildschirmhilfe anzeigen"
|
||||||
|
|
||||||
#: src/backends/meta-monitor.c:223
|
#: src/backends/meta-monitor.c:226
|
||||||
msgid "Built-in display"
|
msgid "Built-in display"
|
||||||
msgstr "Eingebaute Anzeige"
|
msgstr "Eingebaute Anzeige"
|
||||||
|
|
||||||
#: src/backends/meta-monitor.c:252
|
#: src/backends/meta-monitor.c:255
|
||||||
msgid "Unknown"
|
msgid "Unknown"
|
||||||
msgstr "Unbekannt"
|
msgstr "Unbekannt"
|
||||||
|
|
||||||
#: src/backends/meta-monitor.c:254
|
#: src/backends/meta-monitor.c:257
|
||||||
msgid "Unknown Display"
|
msgid "Unknown Display"
|
||||||
msgstr "Unbekannte Anzeige"
|
msgstr "Unbekannte Anzeige"
|
||||||
|
|
||||||
#: src/backends/meta-monitor.c:262
|
#: src/backends/meta-monitor.c:265
|
||||||
#, c-format
|
#, c-format
|
||||||
msgctxt ""
|
msgctxt ""
|
||||||
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
||||||
msgid "%s %s"
|
msgid "%s %s"
|
||||||
msgstr "%s %s"
|
msgstr "%s %s"
|
||||||
|
|
||||||
#: src/backends/meta-monitor.c:270
|
#: src/backends/meta-monitor.c:273
|
||||||
#, c-format
|
#, c-format
|
||||||
msgctxt ""
|
msgctxt ""
|
||||||
"This is a monitor vendor name followed by product/model name where size in "
|
"This is a monitor vendor name followed by product/model name where size in "
|
||||||
@ -614,13 +627,13 @@ msgstr "%s %s"
|
|||||||
|
|
||||||
# https://de.wikipedia.org/wiki/Composition-Manager
|
# https://de.wikipedia.org/wiki/Composition-Manager
|
||||||
#. Translators: this string will appear in Sysprof
|
#. Translators: this string will appear in Sysprof
|
||||||
#: src/backends/meta-profiler.c:82
|
#: src/backends/meta-profiler.c:79
|
||||||
msgid "Compositor"
|
msgid "Compositor"
|
||||||
msgstr "Compositor"
|
msgstr "Compositor"
|
||||||
|
|
||||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||||
#. * we have no way to get it to exit
|
#. * we have no way to get it to exit
|
||||||
#: src/compositor/compositor.c:510
|
#: src/compositor/compositor.c:533
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Another compositing manager is already running on screen %i on display “%s”."
|
"Another compositing manager is already running on screen %i on display “%s”."
|
||||||
@ -632,47 +645,47 @@ msgstr ""
|
|||||||
msgid "Bell event"
|
msgid "Bell event"
|
||||||
msgstr "Klangereignis"
|
msgstr "Klangereignis"
|
||||||
|
|
||||||
#: src/core/main.c:185
|
#: src/core/main.c:190
|
||||||
msgid "Disable connection to session manager"
|
msgid "Disable connection to session manager"
|
||||||
msgstr "Verbindung zur Sitzungsverwaltung deaktivieren"
|
msgstr "Verbindung zur Sitzungsverwaltung deaktivieren"
|
||||||
|
|
||||||
#: src/core/main.c:191
|
#: src/core/main.c:196
|
||||||
msgid "Replace the running window manager"
|
msgid "Replace the running window manager"
|
||||||
msgstr "Den aktuellen Fensterverwalter ersetzen"
|
msgstr "Den aktuellen Fensterverwalter ersetzen"
|
||||||
|
|
||||||
#: src/core/main.c:197
|
#: src/core/main.c:202
|
||||||
msgid "Specify session management ID"
|
msgid "Specify session management ID"
|
||||||
msgstr "Kennung der Sitzungsverwaltung angeben"
|
msgstr "Kennung der Sitzungsverwaltung angeben"
|
||||||
|
|
||||||
#: src/core/main.c:202
|
#: src/core/main.c:207
|
||||||
msgid "X Display to use"
|
msgid "X Display to use"
|
||||||
msgstr "Zu verwendende X-Anzeige"
|
msgstr "Zu verwendende X-Anzeige"
|
||||||
|
|
||||||
#: src/core/main.c:208
|
#: src/core/main.c:213
|
||||||
msgid "Initialize session from savefile"
|
msgid "Initialize session from savefile"
|
||||||
msgstr "Sitzung anhand gespeicherter Datei starten"
|
msgstr "Sitzung anhand gespeicherter Datei starten"
|
||||||
|
|
||||||
#: src/core/main.c:214
|
#: src/core/main.c:219
|
||||||
msgid "Make X calls synchronous"
|
msgid "Make X calls synchronous"
|
||||||
msgstr "X-Aufrufe abgleichen"
|
msgstr "X-Aufrufe abgleichen"
|
||||||
|
|
||||||
#: src/core/main.c:221
|
#: src/core/main.c:226
|
||||||
msgid "Run as a wayland compositor"
|
msgid "Run as a wayland compositor"
|
||||||
msgstr "Als Wayland-Compositor ausführen"
|
msgstr "Als Wayland-Compositor ausführen"
|
||||||
|
|
||||||
#: src/core/main.c:227
|
#: src/core/main.c:232
|
||||||
msgid "Run as a nested compositor"
|
msgid "Run as a nested compositor"
|
||||||
msgstr "Als eingebetteten Compositor ausführen"
|
msgstr "Als eingebetteten Compositor ausführen"
|
||||||
|
|
||||||
#: src/core/main.c:233
|
#: src/core/main.c:238
|
||||||
msgid "Run wayland compositor without starting Xwayland"
|
msgid "Run wayland compositor without starting Xwayland"
|
||||||
msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten"
|
msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten"
|
||||||
|
|
||||||
#: src/core/main.c:241
|
#: src/core/main.c:246
|
||||||
msgid "Run as a full display server, rather than nested"
|
msgid "Run as a full display server, rather than nested"
|
||||||
msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)"
|
msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)"
|
||||||
|
|
||||||
#: src/core/main.c:247
|
#: src/core/main.c:252
|
||||||
msgid "Run with X11 backend"
|
msgid "Run with X11 backend"
|
||||||
msgstr "Mit X11-Backend ausführen"
|
msgstr "Mit X11-Backend ausführen"
|
||||||
|
|
||||||
@ -728,21 +741,21 @@ msgstr "Version ausgeben"
|
|||||||
msgid "Mutter plugin to use"
|
msgid "Mutter plugin to use"
|
||||||
msgstr "Zu benutzendes Mutter-Plugin"
|
msgstr "Zu benutzendes Mutter-Plugin"
|
||||||
|
|
||||||
#: src/core/prefs.c:1849
|
#: src/core/prefs.c:1911
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace %d"
|
msgid "Workspace %d"
|
||||||
msgstr "Arbeitsfläche %d"
|
msgstr "Arbeitsfläche %d"
|
||||||
|
|
||||||
#: src/core/util.c:121
|
#: src/core/util.c:122
|
||||||
msgid "Mutter was compiled without support for verbose mode\n"
|
msgid "Mutter was compiled without support for verbose mode\n"
|
||||||
msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n"
|
msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n"
|
||||||
|
|
||||||
#: src/wayland/meta-wayland-tablet-pad.c:567
|
#: src/wayland/meta-wayland-tablet-pad.c:568
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Mode Switch: Mode %d"
|
msgid "Mode Switch: Mode %d"
|
||||||
msgstr "Moduswechsel: Modus %d"
|
msgstr "Moduswechsel: Modus %d"
|
||||||
|
|
||||||
#: src/x11/meta-x11-display.c:671
|
#: src/x11/meta-x11-display.c:676
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Display “%s” already has a window manager; try using the --replace option to "
|
"Display “%s” already has a window manager; try using the --replace option to "
|
||||||
@ -751,21 +764,21 @@ msgstr ""
|
|||||||
"Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option "
|
"Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option "
|
||||||
"»--replace«, um den aktuellen Fensterverwalter zu ersetzen."
|
"»--replace«, um den aktuellen Fensterverwalter zu ersetzen."
|
||||||
|
|
||||||
#: src/x11/meta-x11-display.c:1032
|
#: src/x11/meta-x11-display.c:1089
|
||||||
msgid "Failed to initialize GDK\n"
|
msgid "Failed to initialize GDK\n"
|
||||||
msgstr "GDK konnte nicht initialisiert werden\n"
|
msgstr "GDK konnte nicht initialisiert werden\n"
|
||||||
|
|
||||||
#: src/x11/meta-x11-display.c:1056
|
#: src/x11/meta-x11-display.c:1113
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Failed to open X Window System display “%s”\n"
|
msgid "Failed to open X Window System display “%s”\n"
|
||||||
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
|
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
|
||||||
|
|
||||||
#: src/x11/meta-x11-display.c:1140
|
#: src/x11/meta-x11-display.c:1196
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Screen %d on display “%s” is invalid\n"
|
msgid "Screen %d on display “%s” is invalid\n"
|
||||||
msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n"
|
msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n"
|
||||||
|
|
||||||
#: src/x11/meta-x11-selection-input-stream.c:445
|
#: src/x11/meta-x11-selection-input-stream.c:460
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Format %s not supported"
|
msgid "Format %s not supported"
|
||||||
msgstr "Format %s wird nicht unterstützt"
|
msgstr "Format %s wird nicht unterstützt"
|
||||||
|
167
po/sk.po
167
po/sk.po
@ -13,8 +13,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: mutter\n"
|
"Project-Id-Version: mutter\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||||
"POT-Creation-Date: 2018-02-06 04:14+0000\n"
|
"POT-Creation-Date: 2020-03-30 20:11+0000\n"
|
||||||
"PO-Revision-Date: 2018-03-17 21:52+0100\n"
|
"PO-Revision-Date: 2020-04-05 22:21+0200\n"
|
||||||
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
|
"Last-Translator: Dušan Kazik <prescott66@gmail.com>\n"
|
||||||
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
|
||||||
"Language: sk\n"
|
"Language: sk\n"
|
||||||
@ -22,7 +22,7 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
|
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
|
||||||
"X-Generator: Poedit 2.0.6\n"
|
"X-Generator: Poedit 2.3\n"
|
||||||
|
|
||||||
#: data/50-mutter-navigation.xml:6
|
#: data/50-mutter-navigation.xml:6
|
||||||
msgid "Navigation"
|
msgid "Navigation"
|
||||||
@ -468,29 +468,47 @@ msgid ""
|
|||||||
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
||||||
"mutter default to layout logical monitors in a logical pixel coordinate "
|
"mutter default to layout logical monitors in a logical pixel coordinate "
|
||||||
"space, while scaling monitor framebuffers instead of window content, to "
|
"space, while scaling monitor framebuffers instead of window content, to "
|
||||||
"manage HiDPI monitors. Does not require a restart. • “remote-desktop” — "
|
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
|
||||||
"enables remote desktop support. To support remote desktop with screen "
|
"mutter request a low priority real-time scheduling. The executable or user "
|
||||||
"sharing, “screen-cast” must also be enabled. • “screen-cast” — enables "
|
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
|
||||||
"screen cast support."
|
"initializes Xwayland lazily if there are X11 clients. Requires restart."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:134
|
||||||
|
msgid "Modifier to use to locate the pointer"
|
||||||
|
msgstr "Modifikátor použitý na lokalizovanie ukazovateľa"
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:135
|
||||||
|
msgid "This key will initiate the “locate pointer” action."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:142
|
||||||
|
msgid "Timeout for check-alive ping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: data/org.gnome.mutter.gschema.xml.in:143
|
||||||
|
msgid ""
|
||||||
|
"Number of milliseconds a client has to respond to a ping request in order to "
|
||||||
|
"not be detected as frozen. Using 0 will disable the alive check completely."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
# summary
|
# summary
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:145
|
#: data/org.gnome.mutter.gschema.xml.in:165
|
||||||
msgid "Select window from tab popup"
|
msgid "Select window from tab popup"
|
||||||
msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora"
|
msgstr "Vybrať okno z rozbaľovacej ponuky tabulátora"
|
||||||
|
|
||||||
# summary
|
# summary
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:150
|
#: data/org.gnome.mutter.gschema.xml.in:170
|
||||||
msgid "Cancel tab popup"
|
msgid "Cancel tab popup"
|
||||||
msgstr "Zrušit rozbaľovaciu ponuku tabulátora"
|
msgstr "Zrušit rozbaľovaciu ponuku tabulátora"
|
||||||
|
|
||||||
# PK: predpokladam ze to prepisane medzi tlacidlami
|
# PK: predpokladam ze to prepisane medzi tlacidlami
|
||||||
# description
|
# description
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:155
|
#: data/org.gnome.mutter.gschema.xml.in:175
|
||||||
msgid "Switch monitor configurations"
|
msgid "Switch monitor configurations"
|
||||||
msgstr "Prepnúť nastavenia monitorov"
|
msgstr "Prepnúť nastavenia monitorov"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.gschema.xml.in:160
|
#: data/org.gnome.mutter.gschema.xml.in:180
|
||||||
msgid "Rotates the built-in monitor configuration"
|
msgid "Rotates the built-in monitor configuration"
|
||||||
msgstr "Otočí nastavenie vstavaného monitora"
|
msgstr "Otočí nastavenie vstavaného monitora"
|
||||||
|
|
||||||
@ -554,23 +572,27 @@ msgid "Re-enable shortcuts"
|
|||||||
msgstr "Znovu povoliť klávesové skratky"
|
msgstr "Znovu povoliť klávesové skratky"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
|
||||||
msgid "Allow grabs with Xwayland"
|
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
||||||
msgid ""
|
msgid ""
|
||||||
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
"Allow all keyboard events to be routed to X11 “override redirect” windows "
|
||||||
"taken into account. For a X11 grab to be taken into account under Wayland, "
|
"with a grab when running in Xwayland. This option is to support X11 clients "
|
||||||
"the client must also either send a specific X11 ClientMessage to the root "
|
"which map an “override redirect” window (which do not receive keyboard "
|
||||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
"focus) and issue a keyboard grab to force all keyboard events to that "
|
||||||
"access-rules”."
|
"window. This option is seldom used and has no effect on regular X11 windows "
|
||||||
|
"which can receive keyboard focus under normal circumstances. For a X11 grab "
|
||||||
|
"to be taken into account under Wayland, the client must also either send a "
|
||||||
|
"specific X11 ClientMessage to the root window or be among the applications "
|
||||||
|
"white-listed in key “xwayland-grab-access-rules”."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
|
||||||
msgid "Xwayland applications allowed to issue keyboard grabs"
|
msgid "Xwayland applications allowed to issue keyboard grabs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
|
||||||
msgid ""
|
msgid ""
|
||||||
"List the resource names or resource class of X11 windows either allowed or "
|
"List the resource names or resource class of X11 windows either allowed or "
|
||||||
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
|
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
|
||||||
@ -587,7 +609,7 @@ msgstr ""
|
|||||||
#. TRANSLATORS: This string refers to a button that switches between
|
#. TRANSLATORS: This string refers to a button that switches between
|
||||||
#. * different modes.
|
#. * different modes.
|
||||||
#.
|
#.
|
||||||
#: src/backends/meta-input-settings.c:2260
|
#: src/backends/meta-input-settings.c:2631
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Mode Switch (Group %d)"
|
msgid "Mode Switch (Group %d)"
|
||||||
msgstr "Prepínač režimu (skupina č. %d)"
|
msgstr "Prepínač režimu (skupina č. %d)"
|
||||||
@ -597,53 +619,61 @@ msgstr "Prepínač režimu (skupina č. %d)"
|
|||||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||||
#. * mapping through the available outputs.
|
#. * mapping through the available outputs.
|
||||||
#.
|
#.
|
||||||
#: src/backends/meta-input-settings.c:2283
|
#: src/backends/meta-input-settings.c:2654
|
||||||
msgid "Switch monitor"
|
msgid "Switch monitor"
|
||||||
msgstr "Prepnúť monitor"
|
msgstr "Prepnúť monitor"
|
||||||
|
|
||||||
#: src/backends/meta-input-settings.c:2285
|
#: src/backends/meta-input-settings.c:2656
|
||||||
msgid "Show on-screen help"
|
msgid "Show on-screen help"
|
||||||
msgstr "Zobraziť pomocníka na obrazovke"
|
msgstr "Zobraziť pomocníka na obrazovke"
|
||||||
|
|
||||||
#: src/backends/meta-monitor-manager.c:900
|
#: src/backends/meta-monitor.c:226
|
||||||
msgid "Built-in display"
|
msgid "Built-in display"
|
||||||
msgstr "Vstavaný displej"
|
msgstr "Vstavaný displej"
|
||||||
|
|
||||||
#: src/backends/meta-monitor-manager.c:923
|
#: src/backends/meta-monitor.c:255
|
||||||
msgid "Unknown"
|
msgid "Unknown"
|
||||||
msgstr "Neznámy"
|
msgstr "Neznámy"
|
||||||
|
|
||||||
#: src/backends/meta-monitor-manager.c:925
|
#: src/backends/meta-monitor.c:257
|
||||||
msgid "Unknown Display"
|
msgid "Unknown Display"
|
||||||
msgstr "Neznámy displej"
|
msgstr "Neznámy displej"
|
||||||
|
|
||||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
#: src/backends/meta-monitor.c:265
|
||||||
#. * size in inches, like 'Dell 15"'
|
|
||||||
#.
|
|
||||||
#: src/backends/meta-monitor-manager.c:933
|
|
||||||
#, c-format
|
#, c-format
|
||||||
|
#| msgid "%s %s"
|
||||||
|
msgctxt ""
|
||||||
|
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
||||||
msgid "%s %s"
|
msgid "%s %s"
|
||||||
msgstr "%s %s"
|
msgstr "%s %s"
|
||||||
|
|
||||||
|
#: src/backends/meta-monitor.c:273
|
||||||
|
#, c-format
|
||||||
|
#| msgid "%s %s"
|
||||||
|
msgctxt ""
|
||||||
|
"This is a monitor vendor name followed by product/model name where size in "
|
||||||
|
"inches could not be calculated, e.g. Dell U2414H"
|
||||||
|
msgid "%s %s"
|
||||||
|
msgstr "%s %s"
|
||||||
|
|
||||||
|
#. Translators: this string will appear in Sysprof
|
||||||
|
#: src/backends/meta-profiler.c:79
|
||||||
|
msgid "Compositor"
|
||||||
|
msgstr "Kompozítor"
|
||||||
|
|
||||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||||
#. * we have no way to get it to exit
|
#. * we have no way to get it to exit
|
||||||
#: src/compositor/compositor.c:481
|
#: src/compositor/compositor.c:533
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Another compositing manager is already running on screen %i on display “%s”."
|
"Another compositing manager is already running on screen %i on display “%s”."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
|
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
|
||||||
|
|
||||||
#: src/core/bell.c:194
|
#: src/core/bell.c:192
|
||||||
msgid "Bell event"
|
msgid "Bell event"
|
||||||
msgstr "Udalosť zvončeka"
|
msgstr "Udalosť zvončeka"
|
||||||
|
|
||||||
# X window system preloz, napr. system na spravu okien X
|
|
||||||
#: src/core/display.c:608
|
|
||||||
#, c-format
|
|
||||||
msgid "Failed to open X Window System display “%s”\n"
|
|
||||||
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
|
||||||
|
|
||||||
# cmd desc
|
# cmd desc
|
||||||
#: src/core/main.c:190
|
#: src/core/main.c:190
|
||||||
msgid "Disable connection to session manager"
|
msgid "Disable connection to session manager"
|
||||||
@ -683,41 +713,45 @@ msgstr "Spustí ako kompozitor protokolu wayland"
|
|||||||
msgid "Run as a nested compositor"
|
msgid "Run as a nested compositor"
|
||||||
msgstr "Spustí ako kompozitor s vnoreným režimom"
|
msgstr "Spustí ako kompozitor s vnoreným režimom"
|
||||||
|
|
||||||
#: src/core/main.c:240
|
#: src/core/main.c:238
|
||||||
|
msgid "Run wayland compositor without starting Xwayland"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/core/main.c:246
|
||||||
msgid "Run as a full display server, rather than nested"
|
msgid "Run as a full display server, rather than nested"
|
||||||
msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu"
|
msgstr "Spustí ako plnohodnotný zobrazovací server, namiesto vnoreného režimu"
|
||||||
|
|
||||||
#: src/core/main.c:246
|
#: src/core/main.c:252
|
||||||
msgid "Run with X11 backend"
|
msgid "Run with X11 backend"
|
||||||
msgstr "Spustí s obslužným programom X11"
|
msgstr "Spustí s obslužným programom X11"
|
||||||
|
|
||||||
# %s is a window title
|
# %s is a window title
|
||||||
#. Translators: %s is a window title
|
#. Translators: %s is a window title
|
||||||
#: src/core/meta-close-dialog-default.c:147
|
#: src/core/meta-close-dialog-default.c:151
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "“%s” is not responding."
|
msgid "“%s” is not responding."
|
||||||
msgstr "„%s“ neodpovedá."
|
msgstr "„%s“ neodpovedá."
|
||||||
|
|
||||||
#: src/core/meta-close-dialog-default.c:149
|
#: src/core/meta-close-dialog-default.c:153
|
||||||
msgid "Application is not responding."
|
msgid "Application is not responding."
|
||||||
msgstr "Aplikácia neodpovedá."
|
msgstr "Aplikácia neodpovedá."
|
||||||
|
|
||||||
#: src/core/meta-close-dialog-default.c:154
|
#: src/core/meta-close-dialog-default.c:158
|
||||||
msgid ""
|
msgid ""
|
||||||
"You may choose to wait a short while for it to continue or force the "
|
"You may choose to wait a short while for it to continue or force the "
|
||||||
"application to quit entirely."
|
"application to quit entirely."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť."
|
"Môžete chvíľu počkať na pokračovanie aplikácie, alebo ju môžete ukončiť."
|
||||||
|
|
||||||
#: src/core/meta-close-dialog-default.c:161
|
#: src/core/meta-close-dialog-default.c:165
|
||||||
msgid "_Force Quit"
|
msgid "_Force Quit"
|
||||||
msgstr "_Vynútiť ukončenie"
|
msgstr "_Vynútiť ukončenie"
|
||||||
|
|
||||||
#: src/core/meta-close-dialog-default.c:161
|
#: src/core/meta-close-dialog-default.c:165
|
||||||
msgid "_Wait"
|
msgid "_Wait"
|
||||||
msgstr "_Počkať"
|
msgstr "_Počkať"
|
||||||
|
|
||||||
#: src/core/mutter.c:39
|
#: src/core/mutter.c:38
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"mutter %s\n"
|
"mutter %s\n"
|
||||||
@ -733,21 +767,30 @@ msgstr ""
|
|||||||
"Záruka sa NEPOSKYTUJE; ani na PREDAJNOSŤ alebo VHODNOSŤ PRE URČITÝ ÚČEL.\n"
|
"Záruka sa NEPOSKYTUJE; ani na PREDAJNOSŤ alebo VHODNOSŤ PRE URČITÝ ÚČEL.\n"
|
||||||
|
|
||||||
# cmd desc
|
# cmd desc
|
||||||
#: src/core/mutter.c:53
|
#: src/core/mutter.c:52
|
||||||
msgid "Print version"
|
msgid "Print version"
|
||||||
msgstr "Zobrazí verziu"
|
msgstr "Zobrazí verziu"
|
||||||
|
|
||||||
# cmd desc
|
# cmd desc
|
||||||
#: src/core/mutter.c:59
|
#: src/core/mutter.c:58
|
||||||
msgid "Mutter plugin to use"
|
msgid "Mutter plugin to use"
|
||||||
msgstr "Použije zásuvný modul Mutter"
|
msgstr "Použije zásuvný modul Mutter"
|
||||||
|
|
||||||
#: src/core/prefs.c:1997
|
#: src/core/prefs.c:1911
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Workspace %d"
|
msgid "Workspace %d"
|
||||||
msgstr "Pracovný priestor č. %d"
|
msgstr "Pracovný priestor č. %d"
|
||||||
|
|
||||||
#: src/core/screen.c:583
|
#: src/core/util.c:122
|
||||||
|
msgid "Mutter was compiled without support for verbose mode\n"
|
||||||
|
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
||||||
|
|
||||||
|
#: src/wayland/meta-wayland-tablet-pad.c:568
|
||||||
|
#, c-format
|
||||||
|
msgid "Mode Switch: Mode %d"
|
||||||
|
msgstr "Prepínač režimu: Režim č. %d"
|
||||||
|
|
||||||
|
#: src/x11/meta-x11-display.c:676
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"Display “%s” already has a window manager; try using the --replace option to "
|
"Display “%s” already has a window manager; try using the --replace option to "
|
||||||
@ -756,21 +799,27 @@ msgstr ""
|
|||||||
"Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa "
|
"Displej „%s“ už má správcu okien. Skúste použiť prepínač --replace, aby sa "
|
||||||
"aktuálny správca nahradil."
|
"aktuálny správca nahradil."
|
||||||
|
|
||||||
#: src/core/screen.c:668
|
#: src/x11/meta-x11-display.c:1089
|
||||||
|
msgid "Failed to initialize GDK\n"
|
||||||
|
msgstr "Zlyhala inicializácia GDK\n"
|
||||||
|
|
||||||
|
# X window system preloz, napr. system na spravu okien X
|
||||||
|
#: src/x11/meta-x11-display.c:1113
|
||||||
|
#, c-format
|
||||||
|
msgid "Failed to open X Window System display “%s”\n"
|
||||||
|
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
|
||||||
|
|
||||||
|
#: src/x11/meta-x11-display.c:1196
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Screen %d on display “%s” is invalid\n"
|
msgid "Screen %d on display “%s” is invalid\n"
|
||||||
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
|
||||||
|
|
||||||
#: src/core/util.c:120
|
#: src/x11/meta-x11-selection-input-stream.c:460
|
||||||
msgid "Mutter was compiled without support for verbose mode\n"
|
|
||||||
msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
|
|
||||||
|
|
||||||
#: src/wayland/meta-wayland-tablet-pad.c:563
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Mode Switch: Mode %d"
|
msgid "Format %s not supported"
|
||||||
msgstr "Prepínač režimu: Režim č. %d"
|
msgstr "Formát %s nie je podporovaný"
|
||||||
|
|
||||||
#: src/x11/session.c:1818
|
#: src/x11/session.c:1821
|
||||||
msgid ""
|
msgid ""
|
||||||
"These windows do not support “save current setup” and will have to be "
|
"These windows do not support “save current setup” and will have to be "
|
||||||
"restarted manually next time you log in."
|
"restarted manually next time you log in."
|
||||||
@ -779,7 +828,7 @@ msgstr ""
|
|||||||
"prihlásení ich budete musieť znovu spustiť ručne."
|
"prihlásení ich budete musieť znovu spustiť ručne."
|
||||||
|
|
||||||
# window title; wm_client_machine
|
# window title; wm_client_machine
|
||||||
#: src/x11/window-props.c:559
|
#: src/x11/window-props.c:569
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s (on %s)"
|
msgid "%s (on %s)"
|
||||||
msgstr "%s (na %s)"
|
msgstr "%s (na %s)"
|
||||||
|
@ -818,7 +818,7 @@ update_trackball_scroll_button (MetaInputSettings *input_settings,
|
|||||||
|
|
||||||
for (l = devices; l; l = l->next)
|
for (l = devices; l; l = l->next)
|
||||||
{
|
{
|
||||||
device = devices->data;
|
device = l->data;
|
||||||
|
|
||||||
if (input_settings_class->is_trackball_device (input_settings, device))
|
if (input_settings_class->is_trackball_device (input_settings, device))
|
||||||
input_settings_class->set_scroll_button (input_settings, device, button);
|
input_settings_class->set_scroll_button (input_settings, device, button);
|
||||||
|
@ -172,6 +172,7 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|||||||
MetaCrtc *crtc;
|
MetaCrtc *crtc;
|
||||||
MetaMonitorTransform transform;
|
MetaMonitorTransform transform;
|
||||||
MetaMonitorTransform crtc_transform;
|
MetaMonitorTransform crtc_transform;
|
||||||
|
MetaMonitorTransform crtc_hw_transform;
|
||||||
int crtc_x, crtc_y;
|
int crtc_x, crtc_y;
|
||||||
float x_offset, y_offset;
|
float x_offset, y_offset;
|
||||||
float scale = 0.0;
|
float scale = 0.0;
|
||||||
@ -200,10 +201,12 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|||||||
|
|
||||||
transform = data->logical_monitor_config->transform;
|
transform = data->logical_monitor_config->transform;
|
||||||
crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
crtc_transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
||||||
if (!meta_monitor_manager_is_transform_handled (data->monitor_manager,
|
if (meta_monitor_manager_is_transform_handled (data->monitor_manager,
|
||||||
crtc,
|
crtc,
|
||||||
crtc_transform))
|
crtc_transform))
|
||||||
crtc_transform = META_MONITOR_TRANSFORM_NORMAL;
|
crtc_hw_transform = crtc_transform;
|
||||||
|
else
|
||||||
|
crtc_hw_transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
|
meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
|
||||||
&crtc_x, &crtc_y);
|
&crtc_x, &crtc_y);
|
||||||
@ -244,7 +247,7 @@ assign_monitor_crtc (MetaMonitor *monitor,
|
|||||||
.crtc = crtc,
|
.crtc = crtc,
|
||||||
.mode = crtc_mode,
|
.mode = crtc_mode,
|
||||||
.layout = crtc_layout,
|
.layout = crtc_layout,
|
||||||
.transform = crtc_transform,
|
.transform = crtc_hw_transform,
|
||||||
.outputs = g_ptr_array_new ()
|
.outputs = g_ptr_array_new ()
|
||||||
};
|
};
|
||||||
g_ptr_array_add (crtc_info->outputs, output);
|
g_ptr_array_add (crtc_info->outputs, output);
|
||||||
@ -443,23 +446,35 @@ MetaMonitorsConfigKey *
|
|||||||
meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager)
|
meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager)
|
||||||
{
|
{
|
||||||
MetaMonitorsConfigKey *config_key;
|
MetaMonitorsConfigKey *config_key;
|
||||||
|
MetaMonitorSpec *laptop_monitor_spec;
|
||||||
GList *l;
|
GList *l;
|
||||||
GList *monitor_specs;
|
GList *monitor_specs;
|
||||||
|
|
||||||
|
laptop_monitor_spec = NULL;
|
||||||
monitor_specs = NULL;
|
monitor_specs = NULL;
|
||||||
for (l = monitor_manager->monitors; l; l = l->next)
|
for (l = monitor_manager->monitors; l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaMonitor *monitor = l->data;
|
MetaMonitor *monitor = l->data;
|
||||||
MetaMonitorSpec *monitor_spec;
|
MetaMonitorSpec *monitor_spec;
|
||||||
|
|
||||||
if (meta_monitor_is_laptop_panel (monitor) &&
|
if (meta_monitor_is_laptop_panel (monitor))
|
||||||
is_lid_closed (monitor_manager))
|
{
|
||||||
continue;
|
laptop_monitor_spec = meta_monitor_get_spec (monitor);
|
||||||
|
|
||||||
|
if (is_lid_closed (monitor_manager))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
|
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
|
||||||
monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
|
monitor_specs = g_list_prepend (monitor_specs, monitor_spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!monitor_specs && laptop_monitor_spec)
|
||||||
|
{
|
||||||
|
monitor_specs =
|
||||||
|
g_list_prepend (NULL, meta_monitor_spec_clone (laptop_monitor_spec));
|
||||||
|
}
|
||||||
|
|
||||||
if (!monitor_specs)
|
if (!monitor_specs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -817,19 +817,19 @@ calculate_tile_coordinate (MetaMonitor *monitor,
|
|||||||
case META_MONITOR_TRANSFORM_270:
|
case META_MONITOR_TRANSFORM_270:
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
||||||
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
|
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
|
||||||
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
|
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
|
||||||
y += other_output->tile_info.tile_w;
|
y += other_output->tile_info.tile_w;
|
||||||
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
|
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
|
||||||
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
|
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
|
||||||
x += other_output->tile_info.tile_h;
|
x += other_output->tile_info.tile_h;
|
||||||
break;
|
break;
|
||||||
case META_MONITOR_TRANSFORM_90:
|
case META_MONITOR_TRANSFORM_90:
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
||||||
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
|
if (other_output->tile_info.loc_v_tile == output->tile_info.loc_v_tile &&
|
||||||
other_output->tile_info.loc_h_tile > output->tile_info.loc_h_tile)
|
other_output->tile_info.loc_h_tile < output->tile_info.loc_h_tile)
|
||||||
y += other_output->tile_info.tile_w;
|
y += other_output->tile_info.tile_w;
|
||||||
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
|
if (other_output->tile_info.loc_h_tile == output->tile_info.loc_h_tile &&
|
||||||
other_output->tile_info.loc_v_tile > output->tile_info.loc_v_tile)
|
other_output->tile_info.loc_v_tile < output->tile_info.loc_v_tile)
|
||||||
x += other_output->tile_info.tile_h;
|
x += other_output->tile_info.tile_h;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ struct _MetaRemoteDesktopSession
|
|||||||
|
|
||||||
MetaScreenCastSession *screen_cast_session;
|
MetaScreenCastSession *screen_cast_session;
|
||||||
gulong screen_cast_session_closed_handler_id;
|
gulong screen_cast_session_closed_handler_id;
|
||||||
|
guint started : 1;
|
||||||
|
|
||||||
ClutterVirtualInputDevice *virtual_pointer;
|
ClutterVirtualInputDevice *virtual_pointer;
|
||||||
ClutterVirtualInputDevice *virtual_keyboard;
|
ClutterVirtualInputDevice *virtual_keyboard;
|
||||||
@ -119,7 +120,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
ClutterSeat *seat = clutter_backend_get_default_seat (backend);
|
||||||
|
|
||||||
g_assert (!session->virtual_pointer && !session->virtual_keyboard);
|
g_assert (!session->started);
|
||||||
|
|
||||||
if (session->screen_cast_session)
|
if (session->screen_cast_session)
|
||||||
{
|
{
|
||||||
@ -135,6 +136,7 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|||||||
clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE);
|
clutter_seat_create_virtual_device (seat, CLUTTER_TOUCHSCREEN_DEVICE);
|
||||||
|
|
||||||
init_remote_access_handle (session);
|
init_remote_access_handle (session);
|
||||||
|
session->started = TRUE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -145,6 +147,8 @@ meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
|
|||||||
MetaDBusRemoteDesktopSession *skeleton =
|
MetaDBusRemoteDesktopSession *skeleton =
|
||||||
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
META_DBUS_REMOTE_DESKTOP_SESSION (session);
|
||||||
|
|
||||||
|
session->started = FALSE;
|
||||||
|
|
||||||
if (session->screen_cast_session)
|
if (session->screen_cast_session)
|
||||||
{
|
{
|
||||||
g_clear_signal_handler (&session->screen_cast_session_closed_handler_id,
|
g_clear_signal_handler (&session->screen_cast_session_closed_handler_id,
|
||||||
@ -249,6 +253,29 @@ check_permission (MetaRemoteDesktopSession *session,
|
|||||||
g_dbus_method_invocation_get_sender (invocation)) == 0;
|
g_dbus_method_invocation_get_sender (invocation)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_remote_desktop_session_check_can_notify (MetaRemoteDesktopSession *session,
|
||||||
|
GDBusMethodInvocation *invocation)
|
||||||
|
{
|
||||||
|
if (!session->started)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Session not started");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!check_permission (session, invocation))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_ACCESS_DENIED,
|
||||||
|
"Permission denied");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
||||||
GDBusMethodInvocation *invocation)
|
GDBusMethodInvocation *invocation)
|
||||||
@ -256,6 +283,14 @@ handle_start (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (session->started)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Already started");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!check_permission (session, invocation))
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
@ -288,6 +323,14 @@ handle_stop (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
|
||||||
|
if (!session->started)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Session not started");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!check_permission (session, invocation))
|
||||||
{
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
@ -312,13 +355,8 @@ handle_notify_keyboard_keycode (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
ClutterKeyState state;
|
ClutterKeyState state;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
state = CLUTTER_KEY_STATE_PRESSED;
|
state = CLUTTER_KEY_STATE_PRESSED;
|
||||||
@ -344,13 +382,8 @@ handle_notify_keyboard_keysym (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
ClutterKeyState state;
|
ClutterKeyState state;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pressed)
|
if (pressed)
|
||||||
state = CLUTTER_KEY_STATE_PRESSED;
|
state = CLUTTER_KEY_STATE_PRESSED;
|
||||||
@ -398,13 +431,8 @@ handle_notify_pointer_button (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
uint32_t button;
|
uint32_t button;
|
||||||
ClutterButtonState state;
|
ClutterButtonState state;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
button = translate_to_clutter_button (button_code);
|
button = translate_to_clutter_button (button_code);
|
||||||
|
|
||||||
@ -434,13 +462,8 @@ handle_notify_pointer_axis (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
|
ClutterScrollFinishFlags finish_flags = CLUTTER_SCROLL_FINISHED_NONE;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
|
if (flags & META_REMOTE_DESKTOP_NOTIFY_AXIS_FLAGS_FINISH)
|
||||||
{
|
{
|
||||||
@ -487,13 +510,8 @@ handle_notify_pointer_axis_discrete (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
ClutterScrollDirection direction;
|
ClutterScrollDirection direction;
|
||||||
int step_count;
|
int step_count;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (axis > 1)
|
if (axis > 1)
|
||||||
{
|
{
|
||||||
@ -538,13 +556,8 @@ handle_notify_pointer_motion_relative (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
|
clutter_virtual_input_device_notify_relative_motion (session->virtual_pointer,
|
||||||
CLUTTER_CURRENT_TIME,
|
CLUTTER_CURRENT_TIME,
|
||||||
@ -567,13 +580,9 @@ handle_notify_pointer_motion_absolute (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaScreenCastStream *stream;
|
MetaScreenCastStream *stream;
|
||||||
double abs_x, abs_y;
|
double abs_x, abs_y;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!session->screen_cast_session)
|
if (!session->screen_cast_session)
|
||||||
{
|
{
|
||||||
@ -617,13 +626,8 @@ handle_notify_touch_down (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaScreenCastStream *stream;
|
MetaScreenCastStream *stream;
|
||||||
double abs_x, abs_y;
|
double abs_x, abs_y;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!session->screen_cast_session)
|
if (!session->screen_cast_session)
|
||||||
{
|
{
|
||||||
@ -668,13 +672,9 @@ handle_notify_touch_motion (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
MetaScreenCastStream *stream;
|
MetaScreenCastStream *stream;
|
||||||
double abs_x, abs_y;
|
double abs_x, abs_y;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!session->screen_cast_session)
|
if (!session->screen_cast_session)
|
||||||
{
|
{
|
||||||
@ -714,13 +714,8 @@ handle_notify_touch_up (MetaDBusRemoteDesktopSession *skeleton,
|
|||||||
{
|
{
|
||||||
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
MetaRemoteDesktopSession *session = META_REMOTE_DESKTOP_SESSION (skeleton);
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!meta_remote_desktop_session_check_can_notify (session, invocation))
|
||||||
{
|
return TRUE;
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
||||||
G_DBUS_ERROR_ACCESS_DENIED,
|
|
||||||
"Permission denied");
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
|
clutter_virtual_input_device_notify_touch_up (session->virtual_touchscreen,
|
||||||
CLUTTER_CURRENT_TIME,
|
CLUTTER_CURRENT_TIME,
|
||||||
|
@ -160,14 +160,12 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_renderer_set_legacy_view (MetaRenderer *renderer,
|
meta_renderer_add_view (MetaRenderer *renderer,
|
||||||
MetaRendererView *legacy_view)
|
MetaRendererView *view)
|
||||||
{
|
{
|
||||||
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
|
||||||
|
|
||||||
g_assert (!priv->views);
|
priv->views = g_list_append (priv->views, view);
|
||||||
|
|
||||||
priv->views = g_list_append (priv->views, legacy_view);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -54,8 +54,8 @@ CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer);
|
|||||||
|
|
||||||
void meta_renderer_rebuild_views (MetaRenderer *renderer);
|
void meta_renderer_rebuild_views (MetaRenderer *renderer);
|
||||||
|
|
||||||
void meta_renderer_set_legacy_view (MetaRenderer *renderer,
|
void meta_renderer_add_view (MetaRenderer *renderer,
|
||||||
MetaRendererView *legacy_view);
|
MetaRendererView *view);
|
||||||
|
|
||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
GList * meta_renderer_get_views (MetaRenderer *renderer);
|
GList * meta_renderer_get_views (MetaRenderer *renderer);
|
||||||
|
@ -115,13 +115,16 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stage_painted (MetaStage *stage,
|
stage_painted (MetaStage *stage,
|
||||||
ClutterStageView *view,
|
ClutterStageView *view,
|
||||||
gpointer user_data)
|
ClutterPaintContext *paint_context,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (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 *
|
static MetaBackend *
|
||||||
@ -180,6 +183,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
|||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
ClutterStage *stage = get_stage (monitor_src);
|
ClutterStage *stage = get_stage (monitor_src);
|
||||||
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
if (!is_cursor_in_stream (monitor_src))
|
if (!is_cursor_in_stream (monitor_src))
|
||||||
return;
|
return;
|
||||||
@ -187,7 +191,11 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
|||||||
if (clutter_stage_is_redraw_queued (stage))
|
if (clutter_stage_is_redraw_queued (stage))
|
||||||
return;
|
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
|
static void
|
||||||
@ -361,8 +369,9 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data)
|
uint8_t *data,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||||
@ -371,9 +380,6 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|||||||
MetaLogicalMonitor *logical_monitor;
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
|
||||||
stage = get_stage (monitor_src);
|
stage = get_stage (monitor_src);
|
||||||
if (!clutter_stage_is_redraw_queued (stage))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
monitor = get_monitor (monitor_src);
|
monitor = get_monitor (monitor_src);
|
||||||
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||||
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
|
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
|
||||||
@ -382,8 +388,9 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||||
CoglFramebuffer *framebuffer)
|
CoglFramebuffer *framebuffer,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||||
@ -407,7 +414,6 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|||||||
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
|
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
CoglFramebuffer *view_framebuffer;
|
CoglFramebuffer *view_framebuffer;
|
||||||
MetaRectangle view_layout;
|
MetaRectangle view_layout;
|
||||||
int x, y;
|
int x, y;
|
||||||
@ -428,12 +434,8 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|||||||
x, y,
|
x, y,
|
||||||
cogl_framebuffer_get_width (view_framebuffer),
|
cogl_framebuffer_get_width (view_framebuffer),
|
||||||
cogl_framebuffer_get_height (view_framebuffer),
|
cogl_framebuffer_get_height (view_framebuffer),
|
||||||
&error))
|
error))
|
||||||
{
|
return FALSE;
|
||||||
g_warning ("Error blitting view into DMABuf framebuffer: %s",
|
|
||||||
error->message);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cogl_framebuffer_finish (framebuffer);
|
cogl_framebuffer_finish (framebuffer);
|
||||||
@ -441,6 +443,44 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
|
|||||||
return TRUE;
|
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
|
static void
|
||||||
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
struct spa_meta_cursor *spa_meta_cursor)
|
struct spa_meta_cursor *spa_meta_cursor)
|
||||||
@ -561,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->get_specs = meta_screen_cast_monitor_stream_src_get_specs;
|
||||||
src_class->enable = meta_screen_cast_monitor_stream_src_enable;
|
src_class->enable = meta_screen_cast_monitor_stream_src_enable;
|
||||||
src_class->disable = meta_screen_cast_monitor_stream_src_disable;
|
src_class->disable = meta_screen_cast_monitor_stream_src_disable;
|
||||||
src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame;
|
src_class->record_to_buffer =
|
||||||
src_class->blit_to_framebuffer =
|
meta_screen_cast_monitor_stream_src_record_to_buffer;
|
||||||
meta_screen_cast_monitor_stream_src_blit_to_framebuffer;
|
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 =
|
src_class->set_cursor_metadata =
|
||||||
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,7 @@ typedef struct _MetaPipeWireSource
|
|||||||
{
|
{
|
||||||
GSource base;
|
GSource base;
|
||||||
|
|
||||||
|
MetaScreenCastStreamSrc *src;
|
||||||
struct pw_loop *pipewire_loop;
|
struct pw_loop *pipewire_loop;
|
||||||
} MetaPipeWireSource;
|
} MetaPipeWireSource;
|
||||||
|
|
||||||
@ -81,6 +82,7 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||||||
struct spa_hook pipewire_core_listener;
|
struct spa_hook pipewire_core_listener;
|
||||||
|
|
||||||
gboolean is_enabled;
|
gboolean is_enabled;
|
||||||
|
gboolean emit_closed_after_dispatch;
|
||||||
|
|
||||||
struct pw_stream *pipewire_stream;
|
struct pw_stream *pipewire_stream;
|
||||||
struct spa_hook pipewire_stream_listener;
|
struct spa_hook pipewire_stream_listener;
|
||||||
@ -89,7 +91,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||||||
struct spa_video_info_raw video_format;
|
struct spa_video_info_raw video_format;
|
||||||
int video_stride;
|
int video_stride;
|
||||||
|
|
||||||
uint64_t last_frame_timestamp_us;
|
int64_t last_frame_timestamp_us;
|
||||||
|
guint follow_up_frame_source_id;
|
||||||
|
|
||||||
GHashTable *dmabuf_handles;
|
GHashTable *dmabuf_handles;
|
||||||
|
|
||||||
@ -107,6 +110,12 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
|
|||||||
meta_screen_cast_stream_src_init_initable_iface)
|
meta_screen_cast_stream_src_init_initable_iface)
|
||||||
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
|
||||||
|
|
||||||
|
static inline uint32_t
|
||||||
|
us2ms (uint64_t us)
|
||||||
|
{
|
||||||
|
return (uint32_t) (us / 1000);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
||||||
int *width,
|
int *width,
|
||||||
@ -133,23 +142,34 @@ meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data)
|
uint8_t *data,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcClass *klass =
|
MetaScreenCastStreamSrcClass *klass =
|
||||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
return klass->record_frame (src, data);
|
return klass->record_to_buffer (src, data, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||||
CoglFramebuffer *framebuffer)
|
CoglFramebuffer *framebuffer,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcClass *klass =
|
MetaScreenCastStreamSrcClass *klass =
|
||||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
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
|
static void
|
||||||
@ -407,9 +427,10 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
do_record_frame (MetaScreenCastStreamSrc *src,
|
do_record_frame (MetaScreenCastStreamSrc *src,
|
||||||
struct spa_buffer *spa_buffer,
|
struct spa_buffer *spa_buffer,
|
||||||
uint8_t *data)
|
uint8_t *data,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
@ -417,7 +438,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
|
|||||||
if (spa_buffer->datas[0].data ||
|
if (spa_buffer->datas[0].data ||
|
||||||
spa_buffer->datas[0].type == SPA_DATA_MemFd)
|
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)
|
else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
|
||||||
{
|
{
|
||||||
@ -427,14 +448,56 @@ do_record_frame (MetaScreenCastStreamSrc *src,
|
|||||||
CoglFramebuffer *dmabuf_fbo =
|
CoglFramebuffer *dmabuf_fbo =
|
||||||
cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
|
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;
|
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
|
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 =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
@ -443,13 +506,29 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
struct spa_buffer *spa_buffer;
|
struct spa_buffer *spa_buffer;
|
||||||
uint8_t *data = NULL;
|
uint8_t *data = NULL;
|
||||||
uint64_t now_us;
|
uint64_t now_us;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
now_us = g_get_monotonic_time ();
|
now_us = g_get_monotonic_time ();
|
||||||
if (priv->last_frame_timestamp_us != 0 &&
|
if (priv->video_format.max_framerate.num > 0 &&
|
||||||
(now_us - priv->last_frame_timestamp_us <
|
priv->last_frame_timestamp_us != 0)
|
||||||
((1000000 * priv->video_format.max_framerate.denom) /
|
{
|
||||||
priv->video_format.max_framerate.num)))
|
int64_t min_interval_us;
|
||||||
return;
|
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)
|
if (!priv->pipewire_stream)
|
||||||
return;
|
return;
|
||||||
@ -467,34 +546,43 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
return;
|
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;
|
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||||
|
if (do_record_frame (src, spa_buffer, data, &error))
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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;
|
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||||
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.position.x = crop_rect.x;
|
||||||
spa_meta_video_crop->region.size.height = crop_rect.height;
|
spa_meta_video_crop->region.position.y = crop_rect.y;
|
||||||
}
|
spa_meta_video_crop->region.size.width = crop_rect.width;
|
||||||
else
|
spa_meta_video_crop->region.size.height = crop_rect.height;
|
||||||
{
|
}
|
||||||
spa_meta_video_crop->region.position.x = 0;
|
else
|
||||||
spa_meta_video_crop->region.position.y = 0;
|
{
|
||||||
spa_meta_video_crop->region.size.width = priv->stream_width;
|
spa_meta_video_crop->region.position.x = 0;
|
||||||
spa_meta_video_crop->region.size.height = priv->stream_height;
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -536,13 +624,9 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
|
|
||||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src);
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src);
|
||||||
|
|
||||||
priv->is_enabled = FALSE;
|
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
priv->is_enabled = FALSE;
|
||||||
meta_screen_cast_stream_src_notify_closed (MetaScreenCastStreamSrc *src)
|
|
||||||
{
|
|
||||||
g_signal_emit (src, signals[CLOSED], 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -559,7 +643,9 @@ on_stream_state_changed (void *data,
|
|||||||
{
|
{
|
||||||
case PW_STREAM_STATE_ERROR:
|
case PW_STREAM_STATE_ERROR:
|
||||||
g_warning ("pipewire stream error: %s", error_message);
|
g_warning ("pipewire stream error: %s", error_message);
|
||||||
meta_screen_cast_stream_src_notify_closed (src);
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
||||||
|
meta_screen_cast_stream_src_disable (src);
|
||||||
|
priv->emit_closed_after_dispatch = TRUE;
|
||||||
break;
|
break;
|
||||||
case PW_STREAM_STATE_PAUSED:
|
case PW_STREAM_STATE_PAUSED:
|
||||||
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
|
if (priv->node_id == SPA_ID_INVALID && priv->pipewire_stream)
|
||||||
@ -827,11 +913,17 @@ on_core_error (void *data,
|
|||||||
const char *message)
|
const char *message)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = data;
|
MetaScreenCastStreamSrc *src = data;
|
||||||
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
|
|
||||||
g_warning ("pipewire remote error: id:%u %s", id, message);
|
g_warning ("pipewire remote error: id:%u %s", id, message);
|
||||||
|
|
||||||
if (id == PW_ID_CORE && res == -EPIPE)
|
if (id == PW_ID_CORE && res == -EPIPE)
|
||||||
meta_screen_cast_stream_src_notify_closed (src);
|
{
|
||||||
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
||||||
|
meta_screen_cast_stream_src_disable (src);
|
||||||
|
priv->emit_closed_after_dispatch = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -848,12 +940,18 @@ pipewire_loop_source_dispatch (GSource *source,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source;
|
MetaPipeWireSource *pipewire_source = (MetaPipeWireSource *) source;
|
||||||
|
MetaScreenCastStreamSrc *src = pipewire_source->src;
|
||||||
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
result = pw_loop_iterate (pipewire_source->pipewire_loop, 0);
|
result = pw_loop_iterate (pipewire_source->pipewire_loop, 0);
|
||||||
if (result < 0)
|
if (result < 0)
|
||||||
g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
|
g_warning ("pipewire_loop_iterate failed: %s", spa_strerror (result));
|
||||||
|
|
||||||
|
if (priv->emit_closed_after_dispatch)
|
||||||
|
g_signal_emit (src, signals[CLOSED], 0);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -875,13 +973,14 @@ static GSourceFuncs pipewire_source_funcs =
|
|||||||
};
|
};
|
||||||
|
|
||||||
static MetaPipeWireSource *
|
static MetaPipeWireSource *
|
||||||
create_pipewire_source (void)
|
create_pipewire_source (MetaScreenCastStreamSrc *src)
|
||||||
{
|
{
|
||||||
MetaPipeWireSource *pipewire_source;
|
MetaPipeWireSource *pipewire_source;
|
||||||
|
|
||||||
pipewire_source =
|
pipewire_source =
|
||||||
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
|
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
|
||||||
sizeof (MetaPipeWireSource));
|
sizeof (MetaPipeWireSource));
|
||||||
|
pipewire_source->src = src;
|
||||||
pipewire_source->pipewire_loop = pw_loop_new (NULL);
|
pipewire_source->pipewire_loop = pw_loop_new (NULL);
|
||||||
if (!pipewire_source->pipewire_loop)
|
if (!pipewire_source->pipewire_loop)
|
||||||
{
|
{
|
||||||
@ -913,7 +1012,7 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
|
|||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
|
|
||||||
priv->pipewire_source = create_pipewire_source ();
|
priv->pipewire_source = create_pipewire_source (src);
|
||||||
if (!priv->pipewire_source)
|
if (!priv->pipewire_source)
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
@ -975,8 +1074,8 @@ meta_screen_cast_stream_src_finalize (GObject *object)
|
|||||||
if (meta_screen_cast_stream_src_is_enabled (src))
|
if (meta_screen_cast_stream_src_is_enabled (src))
|
||||||
meta_screen_cast_stream_src_disable (src);
|
meta_screen_cast_stream_src_disable (src);
|
||||||
|
|
||||||
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
|
|
||||||
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
g_clear_pointer (&priv->pipewire_stream, pw_stream_destroy);
|
||||||
|
g_clear_pointer (&priv->dmabuf_handles, g_hash_table_destroy);
|
||||||
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
g_clear_pointer (&priv->pipewire_core, pw_core_disconnect);
|
||||||
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
g_clear_pointer (&priv->pipewire_context, pw_context_destroy);
|
||||||
g_source_destroy (&priv->pipewire_source->base);
|
g_source_destroy (&priv->pipewire_source->base);
|
||||||
|
@ -37,6 +37,12 @@
|
|||||||
|
|
||||||
typedef struct _MetaScreenCastStream MetaScreenCastStream;
|
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 ())
|
#define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc,
|
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc,
|
||||||
meta_screen_cast_stream_src,
|
meta_screen_cast_stream_src,
|
||||||
@ -53,17 +59,24 @@ struct _MetaScreenCastStreamSrcClass
|
|||||||
float *frame_rate);
|
float *frame_rate);
|
||||||
void (* enable) (MetaScreenCastStreamSrc *src);
|
void (* enable) (MetaScreenCastStreamSrc *src);
|
||||||
void (* disable) (MetaScreenCastStreamSrc *src);
|
void (* disable) (MetaScreenCastStreamSrc *src);
|
||||||
gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
|
gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data);
|
uint8_t *data,
|
||||||
gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src,
|
GError **error);
|
||||||
CoglFramebuffer *framebuffer);
|
gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src,
|
||||||
|
CoglFramebuffer *framebuffer,
|
||||||
|
GError **error);
|
||||||
|
void (* record_follow_up) (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
|
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
|
||||||
MetaRectangle *crop_rect);
|
MetaRectangle *crop_rect);
|
||||||
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
|
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
|
||||||
struct spa_meta_cursor *spa_meta_cursor);
|
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);
|
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
|
@ -327,8 +327,10 @@ screen_cast_window_damaged (MetaWindowActor *actor,
|
|||||||
MetaScreenCastWindowStreamSrc *window_src)
|
MetaScreenCastWindowStreamSrc *window_src)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (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
|
static void
|
||||||
@ -365,6 +367,7 @@ static void
|
|||||||
sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
||||||
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
if (!is_cursor_in_stream (window_src))
|
if (!is_cursor_in_stream (window_src))
|
||||||
return;
|
return;
|
||||||
@ -372,7 +375,8 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
|
|||||||
if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
|
if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
|
||||||
return;
|
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
|
static void
|
||||||
@ -401,6 +405,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|||||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||||
MetaWindowActor *window_actor;
|
MetaWindowActor *window_actor;
|
||||||
MetaScreenCastStream *stream;
|
MetaScreenCastStream *stream;
|
||||||
|
MetaScreenCastRecordFlag flags;
|
||||||
|
|
||||||
window_actor = meta_window_actor_from_window (get_window (window_src));
|
window_actor = meta_window_actor_from_window (get_window (window_src));
|
||||||
if (!window_actor)
|
if (!window_actor)
|
||||||
@ -438,7 +443,8 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
|||||||
break;
|
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
|
static void
|
||||||
@ -451,8 +457,9 @@ meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data)
|
uint8_t *data,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastWindowStreamSrc *window_src =
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
@ -463,8 +470,9 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
|
||||||
CoglFramebuffer *framebuffer)
|
CoglFramebuffer *framebuffer,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaScreenCastWindowStreamSrc *window_src =
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
META_SCREEN_CAST_WINDOW_STREAM_SRC (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);
|
stream_rect.height = get_stream_height (window_src);
|
||||||
|
|
||||||
if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
|
||||||
&stream_rect,
|
&stream_rect,
|
||||||
framebuffer))
|
framebuffer))
|
||||||
return FALSE;
|
{
|
||||||
|
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);
|
stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
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;
|
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
|
static void
|
||||||
meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
struct spa_meta_cursor *spa_meta_cursor)
|
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->get_specs = meta_screen_cast_window_stream_src_get_specs;
|
||||||
src_class->enable = meta_screen_cast_window_stream_src_enable;
|
src_class->enable = meta_screen_cast_window_stream_src_enable;
|
||||||
src_class->disable = meta_screen_cast_window_stream_src_disable;
|
src_class->disable = meta_screen_cast_window_stream_src_disable;
|
||||||
src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
|
src_class->record_to_buffer =
|
||||||
src_class->blit_to_framebuffer =
|
meta_screen_cast_window_stream_src_record_to_buffer;
|
||||||
meta_screen_cast_window_stream_src_blit_to_framebuffer;
|
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->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
|
||||||
src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
|
src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata;
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,10 @@ typedef enum
|
|||||||
META_STAGE_WATCH_AFTER_PAINT,
|
META_STAGE_WATCH_AFTER_PAINT,
|
||||||
} MetaStageWatchPhase;
|
} MetaStageWatchPhase;
|
||||||
|
|
||||||
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
|
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
|
||||||
ClutterStageView *view,
|
ClutterStageView *view,
|
||||||
gpointer user_data);
|
ClutterPaintContext *paint_context,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
ClutterActor *meta_stage_new (MetaBackend *backend);
|
ClutterActor *meta_stage_new (MetaBackend *backend);
|
||||||
|
|
||||||
|
@ -65,7 +65,6 @@ struct _MetaStage
|
|||||||
ClutterStage parent;
|
ClutterStage parent;
|
||||||
|
|
||||||
GPtrArray *watchers[N_WATCH_MODES];
|
GPtrArray *watchers[N_WATCH_MODES];
|
||||||
ClutterStageView *current_view;
|
|
||||||
|
|
||||||
GList *overlays;
|
GList *overlays;
|
||||||
gboolean is_active;
|
gboolean is_active;
|
||||||
@ -169,6 +168,7 @@ meta_stage_finalize (GObject *object)
|
|||||||
static void
|
static void
|
||||||
notify_watchers_for_mode (MetaStage *stage,
|
notify_watchers_for_mode (MetaStage *stage,
|
||||||
ClutterStageView *view,
|
ClutterStageView *view,
|
||||||
|
ClutterPaintContext *paint_context,
|
||||||
MetaStageWatchPhase watch_phase)
|
MetaStageWatchPhase watch_phase)
|
||||||
{
|
{
|
||||||
GPtrArray *watchers;
|
GPtrArray *watchers;
|
||||||
@ -183,7 +183,7 @@ notify_watchers_for_mode (MetaStage *stage,
|
|||||||
if (watch->view && view != watch->view)
|
if (watch->view && view != watch->view)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
watch->callback (stage, view, watch->user_data);
|
watch->callback (stage, view, paint_context, watch->user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,20 +192,34 @@ meta_stage_paint (ClutterActor *actor,
|
|||||||
ClutterPaintContext *paint_context)
|
ClutterPaintContext *paint_context)
|
||||||
{
|
{
|
||||||
MetaStage *stage = META_STAGE (actor);
|
MetaStage *stage = META_STAGE (actor);
|
||||||
|
ClutterStageView *view;
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context);
|
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context);
|
||||||
|
|
||||||
notify_watchers_for_mode (stage, stage->current_view,
|
view = clutter_paint_context_get_stage_view (paint_context);
|
||||||
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
|
if (view)
|
||||||
|
{
|
||||||
|
notify_watchers_for_mode (stage, view, paint_context,
|
||||||
|
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
|
if (!(clutter_paint_context_get_paint_flags (paint_context) &
|
||||||
|
CLUTTER_PAINT_FLAG_NO_PAINT_SIGNAL))
|
||||||
|
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
|
||||||
|
|
||||||
for (l = stage->overlays; l; l = l->next)
|
if (!(clutter_paint_context_get_paint_flags (paint_context) &
|
||||||
meta_overlay_paint (l->data, paint_context);
|
CLUTTER_PAINT_FLAG_NO_CURSORS))
|
||||||
|
{
|
||||||
|
for (l = stage->overlays; l; l = l->next)
|
||||||
|
meta_overlay_paint (l->data, paint_context);
|
||||||
|
}
|
||||||
|
|
||||||
notify_watchers_for_mode (stage, stage->current_view,
|
if (view)
|
||||||
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
|
{
|
||||||
|
notify_watchers_for_mode (stage, view, paint_context,
|
||||||
|
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -215,13 +229,14 @@ meta_stage_paint_view (ClutterStage *stage,
|
|||||||
{
|
{
|
||||||
MetaStage *meta_stage = META_STAGE (stage);
|
MetaStage *meta_stage = META_STAGE (stage);
|
||||||
|
|
||||||
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
|
notify_watchers_for_mode (meta_stage, view, NULL,
|
||||||
|
META_STAGE_WATCH_BEFORE_PAINT);
|
||||||
|
|
||||||
meta_stage->current_view = view;
|
|
||||||
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view,
|
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view,
|
||||||
redraw_clip);
|
redraw_clip);
|
||||||
|
|
||||||
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
|
notify_watchers_for_mode (meta_stage, view, NULL,
|
||||||
|
META_STAGE_WATCH_AFTER_PAINT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -407,13 +407,14 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
else
|
else
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
|
|
||||||
monitor_crtc_mode->output,
|
|
||||||
META_MONITOR_TRANSFORM_NORMAL,
|
|
||||||
&crtc_x, &crtc_y);
|
|
||||||
|
|
||||||
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
|
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
|
||||||
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
||||||
|
|
||||||
|
meta_monitor_calculate_crtc_pos (monitor, monitor_mode,
|
||||||
|
monitor_crtc_mode->output,
|
||||||
|
transform,
|
||||||
|
&crtc_x, &crtc_y);
|
||||||
|
|
||||||
if (meta_monitor_transform_is_rotated (transform))
|
if (meta_monitor_transform_is_rotated (transform))
|
||||||
{
|
{
|
||||||
crtc_width = monitor_crtc_mode->crtc_mode->height;
|
crtc_width = monitor_crtc_mode->crtc_mode->height;
|
||||||
|
@ -232,14 +232,28 @@ meta_gpu_kms_set_power_save_mode (MetaGpuKms *gpu_kms,
|
|||||||
uint64_t state,
|
uint64_t state,
|
||||||
MetaKmsUpdate *kms_update)
|
MetaKmsUpdate *kms_update)
|
||||||
{
|
{
|
||||||
|
MetaGpu *gpu = META_GPU (gpu_kms);
|
||||||
GList *l;
|
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;
|
MetaOutput *output = l->data;
|
||||||
|
|
||||||
meta_output_kms_set_power_save_mode (output, state, kms_update);
|
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
|
gboolean
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018-2019 Red Hat
|
* Copyright (C) 2018-2019 Red Hat
|
||||||
* Copyright (C) 2019 DisplayLink (UK) Ltd.
|
* Copyright (C) 2019-2020 DisplayLink (UK) Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -660,6 +660,9 @@ process_page_flip (MetaKmsImpl *impl,
|
|||||||
meta_kms_page_flip_data_ref (page_flip_data));
|
meta_kms_page_flip_data_ref (page_flip_data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
meta_kms_page_flip_data_unref (page_flip_data);
|
||||||
|
|
||||||
if (ret == -EBUSY)
|
if (ret == -EBUSY)
|
||||||
{
|
{
|
||||||
CachedModeSet *cached_mode_set;
|
CachedModeSet *cached_mode_set;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2018 Red Hat
|
* Copyright (C) 2018 Red Hat
|
||||||
|
* Copyright 2020 DisplayLink (UK) Ltd.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -383,6 +384,7 @@ meta_kms_add_source_in_impl (MetaKms *kms,
|
|||||||
simple_impl_source->kms = kms;
|
simple_impl_source->kms = kms;
|
||||||
|
|
||||||
g_source_set_callback (source, func, user_data, user_data_destroy);
|
g_source_set_callback (source, func, user_data, user_data_destroy);
|
||||||
|
g_source_set_ready_time (source, 0);
|
||||||
g_source_attach (source, g_main_context_get_thread_default ());
|
g_source_attach (source, g_main_context_get_thread_default ());
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
|
@ -2146,6 +2146,7 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
|
|||||||
case META_RENDERER_NATIVE_MODE_GBM:
|
case META_RENDERER_NATIVE_MODE_GBM:
|
||||||
{
|
{
|
||||||
CoglFramebuffer *dmabuf_fb;
|
CoglFramebuffer *dmabuf_fb;
|
||||||
|
CoglDmaBufHandle *dmabuf_handle;
|
||||||
struct gbm_bo *new_bo;
|
struct gbm_bo *new_bo;
|
||||||
int dmabuf_fd = -1;
|
int dmabuf_fd = -1;
|
||||||
|
|
||||||
@ -2182,8 +2183,11 @@ meta_renderer_native_create_dma_buf (CoglRenderer *cogl_renderer,
|
|||||||
if (!dmabuf_fb)
|
if (!dmabuf_fb)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
|
dmabuf_handle =
|
||||||
(GDestroyNotify) gbm_bo_destroy);
|
cogl_dma_buf_handle_new (dmabuf_fb, dmabuf_fd, new_bo,
|
||||||
|
(GDestroyNotify) gbm_bo_destroy);
|
||||||
|
cogl_object_unref (dmabuf_fb);
|
||||||
|
return dmabuf_handle;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_EGL_DEVICE
|
#ifdef HAVE_EGL_DEVICE
|
||||||
@ -3037,6 +3041,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
|||||||
float scale;
|
float scale;
|
||||||
int onscreen_width;
|
int onscreen_width;
|
||||||
int onscreen_height;
|
int onscreen_height;
|
||||||
|
MetaRectangle view_layout;
|
||||||
MetaRendererView *view;
|
MetaRendererView *view;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
@ -3108,8 +3113,11 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
|||||||
else
|
else
|
||||||
scale = 1.0;
|
scale = 1.0;
|
||||||
|
|
||||||
|
meta_rectangle_from_graphene_rect (&crtc->config->layout,
|
||||||
|
META_ROUNDING_STRATEGY_ROUND,
|
||||||
|
&view_layout);
|
||||||
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||||
"layout", &logical_monitor->rect,
|
"layout", &view_layout,
|
||||||
"scale", scale,
|
"scale", scale,
|
||||||
"framebuffer", onscreen,
|
"framebuffer", onscreen,
|
||||||
"offscreen", offscreen,
|
"offscreen", offscreen,
|
||||||
|
@ -424,6 +424,9 @@ new_absolute_motion_event (MetaSeatNative *seat,
|
|||||||
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
meta_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||||
event->motion.x = x;
|
event->motion.x = x;
|
||||||
event->motion.y = y;
|
event->motion.y = y;
|
||||||
|
meta_input_device_native_translate_coordinates (input_device, stage,
|
||||||
|
&event->motion.x,
|
||||||
|
&event->motion.y);
|
||||||
event->motion.axes = axes;
|
event->motion.axes = axes;
|
||||||
clutter_event_set_device (event, seat->core_pointer);
|
clutter_event_set_device (event, seat->core_pointer);
|
||||||
clutter_event_set_source_device (event, input_device);
|
clutter_event_set_source_device (event, input_device);
|
||||||
@ -1377,35 +1380,6 @@ has_touchscreen (MetaSeatNative *seat)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
has_external_keyboard (MetaSeatNative *seat)
|
|
||||||
{
|
|
||||||
GList *devices, *l;
|
|
||||||
gboolean has_external = FALSE;
|
|
||||||
|
|
||||||
devices = g_udev_client_query_by_subsystem (seat->udev_client, "input");
|
|
||||||
|
|
||||||
for (l = devices; l; l = l->next)
|
|
||||||
{
|
|
||||||
if (!g_udev_device_has_property (l->data, "ID_INPUT_KEYBOARD"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* May be "hid" or something else, we don't care. This property
|
|
||||||
* will not be present in virtual "AT Translated Set 2 keyboard"
|
|
||||||
* devices.
|
|
||||||
*/
|
|
||||||
if (!g_udev_device_has_property (l->data, "ID_TYPE"))
|
|
||||||
break;
|
|
||||||
|
|
||||||
has_external = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free_full (devices, g_object_unref);
|
|
||||||
|
|
||||||
return has_external;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_touch_mode (MetaSeatNative *seat)
|
update_touch_mode (MetaSeatNative *seat)
|
||||||
{
|
{
|
||||||
@ -1418,10 +1392,10 @@ update_touch_mode (MetaSeatNative *seat)
|
|||||||
else if (seat->has_tablet_switch && !seat->tablet_mode_switch_state)
|
else if (seat->has_tablet_switch && !seat->tablet_mode_switch_state)
|
||||||
touch_mode = FALSE;
|
touch_mode = FALSE;
|
||||||
/* If tablet mode is enabled, or if there is no tablet mode switch
|
/* If tablet mode is enabled, or if there is no tablet mode switch
|
||||||
* (eg. kiosk machines), check availability of external keyboards.
|
* (eg. kiosk machines), assume touch-mode.
|
||||||
*/
|
*/
|
||||||
else
|
else
|
||||||
touch_mode = !seat->has_external_keyboard;
|
touch_mode = TRUE;
|
||||||
|
|
||||||
if (seat->touch_mode != touch_mode)
|
if (seat->touch_mode != touch_mode)
|
||||||
{
|
{
|
||||||
@ -1462,12 +1436,7 @@ evdev_add_device (MetaSeatNative *seat,
|
|||||||
|
|
||||||
g_signal_emit_by_name (seat, "device-added", device);
|
g_signal_emit_by_name (seat, "device-added", device);
|
||||||
|
|
||||||
if (type == CLUTTER_KEYBOARD_DEVICE)
|
if (type == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||||
{
|
|
||||||
seat->has_external_keyboard = has_external_keyboard (seat);
|
|
||||||
check_touch_mode = TRUE;
|
|
||||||
}
|
|
||||||
else if (type == CLUTTER_TOUCHSCREEN_DEVICE)
|
|
||||||
{
|
{
|
||||||
seat->has_touchscreen = TRUE;
|
seat->has_touchscreen = TRUE;
|
||||||
check_touch_mode = TRUE;
|
check_touch_mode = TRUE;
|
||||||
@ -1500,12 +1469,7 @@ evdev_remove_device (MetaSeatNative *seat,
|
|||||||
|
|
||||||
device_type = clutter_input_device_get_device_type (device);
|
device_type = clutter_input_device_get_device_type (device);
|
||||||
|
|
||||||
if (device_type == CLUTTER_KEYBOARD_DEVICE)
|
if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||||
{
|
|
||||||
seat->has_external_keyboard = has_external_keyboard (seat);
|
|
||||||
update_touch_mode (seat);
|
|
||||||
}
|
|
||||||
else if (device_type == CLUTTER_TOUCHSCREEN_DEVICE)
|
|
||||||
{
|
{
|
||||||
seat->has_touchscreen = has_touchscreen (seat);
|
seat->has_touchscreen = has_touchscreen (seat);
|
||||||
update_touch_mode (seat);
|
update_touch_mode (seat);
|
||||||
@ -2550,7 +2514,6 @@ meta_seat_native_constructed (GObject *object)
|
|||||||
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
|
xkb_keymap_led_get_index (xkb_keymap, XKB_LED_NAME_SCROLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
seat->has_external_keyboard = has_external_keyboard (seat);
|
|
||||||
seat->has_touchscreen = has_touchscreen (seat);
|
seat->has_touchscreen = has_touchscreen (seat);
|
||||||
update_touch_mode (seat);
|
update_touch_mode (seat);
|
||||||
|
|
||||||
|
@ -120,7 +120,6 @@ struct _MetaSeatNative
|
|||||||
|
|
||||||
GUdevClient *udev_client;
|
GUdevClient *udev_client;
|
||||||
guint tablet_mode_switch_state : 1;
|
guint tablet_mode_switch_state : 1;
|
||||||
guint has_external_keyboard : 1;
|
|
||||||
guint has_touchscreen : 1;
|
guint has_touchscreen : 1;
|
||||||
guint has_tablet_switch : 1;
|
guint has_tablet_switch : 1;
|
||||||
guint touch_mode : 1;
|
guint touch_mode : 1;
|
||||||
|
@ -24,14 +24,75 @@
|
|||||||
|
|
||||||
#include "backends/x11/cm/meta-renderer-x11-cm.h"
|
#include "backends/x11/cm/meta-renderer-x11-cm.h"
|
||||||
|
|
||||||
|
#include "backends/meta-renderer-view.h"
|
||||||
|
|
||||||
struct _MetaRendererX11Cm
|
struct _MetaRendererX11Cm
|
||||||
{
|
{
|
||||||
MetaRendererX11 parent;
|
MetaRendererX11 parent;
|
||||||
|
|
||||||
|
MetaRendererView *screen_view;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
|
G_DEFINE_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
|
||||||
META_TYPE_RENDERER_X11)
|
META_TYPE_RENDERER_X11)
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t view_layout;
|
||||||
|
|
||||||
|
if (renderer_x11_cm->screen_view)
|
||||||
|
return;
|
||||||
|
|
||||||
|
view_layout = (cairo_rectangle_int_t) {
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
renderer_x11_cm->screen_view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||||
|
"layout", &view_layout,
|
||||||
|
NULL);
|
||||||
|
meta_renderer_add_view (META_RENDERER (renderer_x11_cm),
|
||||||
|
renderer_x11_cm->screen_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
cairo_rectangle_int_t view_layout;
|
||||||
|
|
||||||
|
view_layout = (cairo_rectangle_int_t) {
|
||||||
|
.width = width,
|
||||||
|
.height = height,
|
||||||
|
};
|
||||||
|
|
||||||
|
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
|
||||||
|
"layout", &view_layout,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
CoglOnscreen *onscreen)
|
||||||
|
{
|
||||||
|
g_object_set (G_OBJECT (renderer_x11_cm->screen_view),
|
||||||
|
"framebuffer", onscreen,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_renderer_x11_cm_rebuild_views (MetaRenderer *renderer)
|
||||||
|
{
|
||||||
|
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
|
||||||
|
|
||||||
|
g_return_if_fail (!meta_renderer_get_views (renderer));
|
||||||
|
|
||||||
|
meta_renderer_add_view (renderer, renderer_x11_cm->screen_view);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
|
meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
|
||||||
{
|
{
|
||||||
@ -40,4 +101,7 @@ meta_renderer_x11_cm_init (MetaRendererX11Cm *renderer_x11_cm)
|
|||||||
static void
|
static void
|
||||||
meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass)
|
meta_renderer_x11_cm_class_init (MetaRendererX11CmClass *klass)
|
||||||
{
|
{
|
||||||
|
MetaRendererClass *renderer_class = META_RENDERER_CLASS (klass);
|
||||||
|
|
||||||
|
renderer_class->rebuild_views = meta_renderer_x11_cm_rebuild_views;
|
||||||
}
|
}
|
||||||
|
@ -30,4 +30,15 @@ G_DECLARE_FINAL_TYPE (MetaRendererX11Cm, meta_renderer_x11_cm,
|
|||||||
META, RENDERER_X11_CM,
|
META, RENDERER_X11_CM,
|
||||||
MetaRendererX11)
|
MetaRendererX11)
|
||||||
|
|
||||||
|
void meta_renderer_x11_cm_ensure_screen_view (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
|
void meta_renderer_x11_cm_resize (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
int width,
|
||||||
|
int height);
|
||||||
|
|
||||||
|
void meta_renderer_x11_cm_set_onscreen (MetaRendererX11Cm *renderer_x11_cm,
|
||||||
|
CoglOnscreen *onscreen);
|
||||||
|
|
||||||
#endif /* META_RENDERER_X11_CM_H */
|
#endif /* META_RENDERER_X11_CM_H */
|
||||||
|
@ -855,6 +855,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
|||||||
static void
|
static void
|
||||||
meta_backend_x11_init (MetaBackendX11 *x11)
|
meta_backend_x11_init (MetaBackendX11 *x11)
|
||||||
{
|
{
|
||||||
|
XInitThreads ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Display *
|
Display *
|
||||||
|
@ -38,7 +38,6 @@ struct _MetaInputDeviceX11
|
|||||||
float current_y;
|
float current_y;
|
||||||
|
|
||||||
#ifdef HAVE_LIBWACOM
|
#ifdef HAVE_LIBWACOM
|
||||||
WacomDevice *wacom_device;
|
|
||||||
GArray *group_modes;
|
GArray *group_modes;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -93,13 +92,16 @@ meta_input_device_x11_is_grouped (ClutterInputDevice *device,
|
|||||||
ClutterInputDevice *other_device)
|
ClutterInputDevice *other_device)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBWACOM
|
#ifdef HAVE_LIBWACOM
|
||||||
MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device);
|
WacomDevice *wacom_device, *other_wacom_device;
|
||||||
MetaInputDeviceX11 *other_device_x11 = META_INPUT_DEVICE_X11 (other_device);
|
|
||||||
|
|
||||||
if (device_x11->wacom_device &&
|
wacom_device =
|
||||||
other_device_x11->wacom_device &&
|
meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
|
||||||
libwacom_compare (device_x11->wacom_device,
|
other_wacom_device =
|
||||||
other_device_x11->wacom_device,
|
meta_input_device_get_wacom_device (META_INPUT_DEVICE (other_device));
|
||||||
|
|
||||||
|
if (wacom_device && other_wacom_device &&
|
||||||
|
libwacom_compare (wacom_device,
|
||||||
|
other_wacom_device,
|
||||||
WCOMPARE_NORMAL) == 0)
|
WCOMPARE_NORMAL) == 0)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
#endif
|
#endif
|
||||||
@ -122,9 +124,9 @@ meta_input_device_x11_is_grouped (ClutterInputDevice *device,
|
|||||||
static void
|
static void
|
||||||
meta_input_device_x11_finalize (GObject *object)
|
meta_input_device_x11_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBWACOM
|
|
||||||
MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object);
|
MetaInputDeviceX11 *device_xi2 = META_INPUT_DEVICE_X11 (object);
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBWACOM
|
||||||
if (device_xi2->group_modes)
|
if (device_xi2->group_modes)
|
||||||
g_array_unref (device_xi2->group_modes);
|
g_array_unref (device_xi2->group_modes);
|
||||||
#endif
|
#endif
|
||||||
@ -413,9 +415,12 @@ pad_switch_mode (ClutterInputDevice *device,
|
|||||||
{
|
{
|
||||||
MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device);
|
MetaInputDeviceX11 *device_x11 = META_INPUT_DEVICE_X11 (device);
|
||||||
uint32_t n_buttons, n_modes, button_group, next_mode, i;
|
uint32_t n_buttons, n_modes, button_group, next_mode, i;
|
||||||
|
WacomDevice *wacom_device;
|
||||||
GList *switch_buttons = NULL;
|
GList *switch_buttons = NULL;
|
||||||
|
|
||||||
n_buttons = libwacom_get_num_buttons (device_x11->wacom_device);
|
wacom_device =
|
||||||
|
meta_input_device_get_wacom_device (META_INPUT_DEVICE (device));
|
||||||
|
n_buttons = libwacom_get_num_buttons (wacom_device);
|
||||||
|
|
||||||
for (i = 0; i < n_buttons; i++)
|
for (i = 0; i < n_buttons; i++)
|
||||||
{
|
{
|
||||||
|
@ -38,7 +38,10 @@ enum
|
|||||||
PROP_OPCODE,
|
PROP_OPCODE,
|
||||||
PROP_POINTER_ID,
|
PROP_POINTER_ID,
|
||||||
PROP_KEYBOARD_ID,
|
PROP_KEYBOARD_ID,
|
||||||
N_PROPS
|
N_PROPS,
|
||||||
|
|
||||||
|
/* This property is overridden */
|
||||||
|
PROP_TOUCH_MODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaSeatX11
|
struct _MetaSeatX11
|
||||||
@ -54,6 +57,8 @@ struct _MetaSeatX11
|
|||||||
int pointer_id;
|
int pointer_id;
|
||||||
int keyboard_id;
|
int keyboard_id;
|
||||||
int opcode;
|
int opcode;
|
||||||
|
guint has_touchscreens : 1;
|
||||||
|
guint touch_mode : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
static GParamSpec *props[N_PROPS] = { 0 };
|
static GParamSpec *props[N_PROPS] = { 0 };
|
||||||
@ -605,6 +610,20 @@ pad_passive_button_grab (ClutterInputDevice *device)
|
|||||||
g_free (xi_event_mask.mask);
|
g_free (xi_event_mask.mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_touch_mode (MetaSeatX11 *seat_x11)
|
||||||
|
{
|
||||||
|
gboolean touch_mode;
|
||||||
|
|
||||||
|
touch_mode = seat_x11->has_touchscreens;
|
||||||
|
|
||||||
|
if (seat_x11->touch_mode == touch_mode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
seat_x11->touch_mode = touch_mode;
|
||||||
|
g_object_notify (G_OBJECT (seat_x11), "touch-mode");
|
||||||
|
}
|
||||||
|
|
||||||
static ClutterInputDevice *
|
static ClutterInputDevice *
|
||||||
add_device (MetaSeatX11 *seat_x11,
|
add_device (MetaSeatX11 *seat_x11,
|
||||||
ClutterBackend *backend,
|
ClutterBackend *backend,
|
||||||
@ -635,6 +654,8 @@ add_device (MetaSeatX11 *seat_x11,
|
|||||||
info->attachment == seat_x11->keyboard_id))
|
info->attachment == seat_x11->keyboard_id))
|
||||||
{
|
{
|
||||||
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
|
seat_x11->devices = g_list_prepend (seat_x11->devices, device);
|
||||||
|
seat_x11->has_touchscreens |=
|
||||||
|
clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -663,18 +684,38 @@ add_device (MetaSeatX11 *seat_x11,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_touch_mode (seat_x11);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
has_touchscreens (MetaSeatX11 *seat_x11)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = seat_x11->devices; l; l = l->next)
|
||||||
|
{
|
||||||
|
if (clutter_input_device_get_device_type (l->data) == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_device (MetaSeatX11 *seat_x11,
|
remove_device (MetaSeatX11 *seat_x11,
|
||||||
int device_id)
|
int device_id)
|
||||||
{
|
{
|
||||||
ClutterInputDevice *device;
|
ClutterInputDevice *device;
|
||||||
|
gboolean check_touchscreens = FALSE;
|
||||||
|
|
||||||
device = g_hash_table_lookup (seat_x11->devices_by_id,
|
device = g_hash_table_lookup (seat_x11->devices_by_id,
|
||||||
GINT_TO_POINTER (device_id));
|
GINT_TO_POINTER (device_id));
|
||||||
|
|
||||||
|
if (clutter_input_device_get_device_type (device) == CLUTTER_TOUCHSCREEN_DEVICE)
|
||||||
|
check_touchscreens = TRUE;
|
||||||
|
|
||||||
if (device != NULL)
|
if (device != NULL)
|
||||||
{
|
{
|
||||||
if (seat_x11->core_pointer == device)
|
if (seat_x11->core_pointer == device)
|
||||||
@ -695,6 +736,12 @@ remove_device (MetaSeatX11 *seat_x11,
|
|||||||
g_hash_table_remove (seat_x11->devices_by_id,
|
g_hash_table_remove (seat_x11->devices_by_id,
|
||||||
GINT_TO_POINTER (device_id));
|
GINT_TO_POINTER (device_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_touchscreens)
|
||||||
|
{
|
||||||
|
seat_x11->has_touchscreens = has_touchscreens (seat_x11);
|
||||||
|
update_touch_mode (seat_x11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1272,6 +1319,7 @@ meta_seat_x11_set_property (GObject *object,
|
|||||||
case PROP_KEYBOARD_ID:
|
case PROP_KEYBOARD_ID:
|
||||||
seat_x11->keyboard_id = g_value_get_int (value);
|
seat_x11->keyboard_id = g_value_get_int (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TOUCH_MODE:
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -1296,6 +1344,9 @@ meta_seat_x11_get_property (GObject *object,
|
|||||||
case PROP_KEYBOARD_ID:
|
case PROP_KEYBOARD_ID:
|
||||||
g_value_set_int (value, seat_x11->keyboard_id);
|
g_value_set_int (value, seat_x11->keyboard_id);
|
||||||
break;
|
break;
|
||||||
|
case PROP_TOUCH_MODE:
|
||||||
|
g_value_set_boolean (value, seat_x11->touch_mode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -1547,6 +1598,9 @@ meta_seat_x11_class_init (MetaSeatX11Class *klass)
|
|||||||
G_PARAM_CONSTRUCT_ONLY);
|
G_PARAM_CONSTRUCT_ONLY);
|
||||||
|
|
||||||
g_object_class_install_properties (object_class, N_PROPS, props);
|
g_object_class_install_properties (object_class, N_PROPS, props);
|
||||||
|
|
||||||
|
g_object_class_override_property (object_class, PROP_TOUCH_MODE,
|
||||||
|
"touch-mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -26,15 +26,17 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "backends/x11/cm/meta-backend-x11-cm.h"
|
||||||
|
#include "backends/x11/cm/meta-renderer-x11-cm.h"
|
||||||
|
#include "backends/x11/meta-backend-x11.h"
|
||||||
|
#include "backends/x11/meta-seat-x11.h"
|
||||||
|
#include "backends/x11/meta-stage-x11.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
#include "clutter/x11/clutter-x11.h"
|
#include "clutter/x11/clutter-x11.h"
|
||||||
#include "clutter/x11/clutter-backend-x11.h"
|
#include "clutter/x11/clutter-backend-x11.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
#include "core/display-private.h"
|
#include "core/display-private.h"
|
||||||
#include "meta/meta-x11-errors.h"
|
#include "meta/meta-x11-errors.h"
|
||||||
#include "meta-backend-x11.h"
|
|
||||||
#include "meta-seat-x11.h"
|
|
||||||
#include "meta-stage-x11.h"
|
|
||||||
|
|
||||||
#define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
|
#define STAGE_X11_IS_MAPPED(s) ((((MetaStageX11 *) (s))->wm_state & STAGE_X11_WITHDRAWN) == 0)
|
||||||
|
|
||||||
@ -287,8 +289,6 @@ meta_stage_x11_unrealize (ClutterStageWindow *stage_window)
|
|||||||
|
|
||||||
clutter_stage_window_parent_iface->unrealize (stage_window);
|
clutter_stage_window_parent_iface->unrealize (stage_window);
|
||||||
|
|
||||||
g_list_free (stage_x11->legacy_views);
|
|
||||||
g_clear_object (&stage_x11->legacy_view);
|
|
||||||
g_clear_pointer (&stage_x11->onscreen, cogl_object_unref);
|
g_clear_pointer (&stage_x11->onscreen, cogl_object_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -330,10 +330,13 @@ meta_stage_x11_realize (ClutterStageWindow *stage_window)
|
|||||||
stage_cogl,
|
stage_cogl,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
if (stage_x11->legacy_view)
|
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
|
||||||
g_object_set (G_OBJECT (stage_x11->legacy_view),
|
{
|
||||||
"framebuffer", stage_x11->onscreen,
|
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
|
||||||
NULL);
|
MetaRendererX11Cm *renderer_x11_cm = META_RENDERER_X11_CM (renderer);
|
||||||
|
|
||||||
|
meta_renderer_x11_cm_set_onscreen (renderer_x11_cm, stage_x11->onscreen);
|
||||||
|
}
|
||||||
|
|
||||||
/* We just created a window of the size of the actor. No need to fix
|
/* We just created a window of the size of the actor. No need to fix
|
||||||
the size of the stage, just update it. */
|
the size of the stage, just update it. */
|
||||||
@ -522,34 +525,13 @@ meta_stage_x11_can_clip_redraws (ClutterStageWindow *stage_window)
|
|||||||
return stage_x11->clipped_redraws_cool_off == 0;
|
return stage_x11->clipped_redraws_cool_off == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
ensure_legacy_view (ClutterStageWindow *stage_window)
|
|
||||||
{
|
|
||||||
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
|
|
||||||
cairo_rectangle_int_t view_layout;
|
|
||||||
CoglFramebuffer *framebuffer;
|
|
||||||
|
|
||||||
if (stage_x11->legacy_view)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_clutter_stage_window_get_geometry (stage_window, &view_layout);
|
|
||||||
framebuffer = COGL_FRAMEBUFFER (stage_x11->onscreen);
|
|
||||||
stage_x11->legacy_view = g_object_new (CLUTTER_TYPE_STAGE_VIEW_COGL,
|
|
||||||
"layout", &view_layout,
|
|
||||||
"framebuffer", framebuffer,
|
|
||||||
NULL);
|
|
||||||
stage_x11->legacy_views = g_list_append (stage_x11->legacy_views,
|
|
||||||
stage_x11->legacy_view);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GList *
|
static GList *
|
||||||
meta_stage_x11_get_views (ClutterStageWindow *stage_window)
|
meta_stage_x11_get_views (ClutterStageWindow *stage_window)
|
||||||
{
|
{
|
||||||
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
|
MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_window);
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (stage_x11->backend);
|
||||||
|
|
||||||
ensure_legacy_view (stage_window);
|
return meta_renderer_get_views (renderer);
|
||||||
|
|
||||||
return stage_x11->legacy_views;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
@ -581,6 +563,9 @@ meta_stage_x11_class_init (MetaStageX11Class *klass)
|
|||||||
static void
|
static void
|
||||||
meta_stage_x11_init (MetaStageX11 *stage)
|
meta_stage_x11_init (MetaStageX11 *stage)
|
||||||
{
|
{
|
||||||
|
MetaRenderer *renderer;
|
||||||
|
MetaRendererX11Cm *renderer_x11_cm;
|
||||||
|
|
||||||
stage->xwin = None;
|
stage->xwin = None;
|
||||||
stage->xwin_width = 640;
|
stage->xwin_width = 640;
|
||||||
stage->xwin_height = 480;
|
stage->xwin_height = 480;
|
||||||
@ -591,6 +576,19 @@ meta_stage_x11_init (MetaStageX11 *stage)
|
|||||||
stage->accept_focus = TRUE;
|
stage->accept_focus = TRUE;
|
||||||
|
|
||||||
stage->title = NULL;
|
stage->title = NULL;
|
||||||
|
|
||||||
|
stage->backend = meta_get_backend ();
|
||||||
|
g_assert (stage->backend);
|
||||||
|
|
||||||
|
if (META_IS_BACKEND_X11_CM (stage->backend))
|
||||||
|
{
|
||||||
|
renderer = meta_backend_get_renderer (stage->backend);
|
||||||
|
renderer_x11_cm = META_RENDERER_X11_CM (renderer);
|
||||||
|
|
||||||
|
meta_renderer_x11_cm_ensure_screen_view (renderer_x11_cm,
|
||||||
|
stage->xwin_width,
|
||||||
|
stage->xwin_height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -778,16 +776,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
|
|||||||
* X11 compositing manager, we need to reset the legacy
|
* X11 compositing manager, we need to reset the legacy
|
||||||
* stage view, now that it has a new size.
|
* stage view, now that it has a new size.
|
||||||
*/
|
*/
|
||||||
if (stage_x11->legacy_view)
|
if (META_IS_BACKEND_X11_CM (stage_x11->backend))
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t view_layout = {
|
MetaBackend *backend = stage_x11->backend;
|
||||||
.width = stage_width,
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
.height = stage_height
|
MetaRendererX11Cm *renderer_x11_cm =
|
||||||
};
|
META_RENDERER_X11_CM (renderer);
|
||||||
|
|
||||||
g_object_set (G_OBJECT (stage_x11->legacy_view),
|
meta_renderer_x11_cm_resize (renderer_x11_cm,
|
||||||
"layout", &view_layout,
|
stage_width,
|
||||||
NULL);
|
stage_height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -845,12 +843,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
|
|||||||
g_debug ("Client message for stage, win:0x%x",
|
g_debug ("Client message for stage, win:0x%x",
|
||||||
(unsigned int) xevent->xany.window);
|
(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;
|
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||||
event->any.stage = stage;
|
{
|
||||||
res = TRUE;
|
event->any.type = CLUTTER_DELETE;
|
||||||
|
event->any.stage = stage;
|
||||||
|
res = TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
#include "clutter/x11/clutter-x11.h"
|
#include "clutter/x11/clutter-x11.h"
|
||||||
|
|
||||||
@ -51,14 +52,13 @@ struct _MetaStageX11
|
|||||||
{
|
{
|
||||||
ClutterStageCogl parent_instance;
|
ClutterStageCogl parent_instance;
|
||||||
|
|
||||||
|
MetaBackend *backend;
|
||||||
|
|
||||||
CoglOnscreen *onscreen;
|
CoglOnscreen *onscreen;
|
||||||
Window xwin;
|
Window xwin;
|
||||||
gint xwin_width;
|
gint xwin_width;
|
||||||
gint xwin_height; /* FIXME target_width / height */
|
gint xwin_height; /* FIXME target_width / height */
|
||||||
|
|
||||||
ClutterStageView *legacy_view;
|
|
||||||
GList *legacy_views;
|
|
||||||
|
|
||||||
CoglFrameClosure *frame_closure;
|
CoglFrameClosure *frame_closure;
|
||||||
|
|
||||||
gchar *title;
|
gchar *title;
|
||||||
|
@ -167,7 +167,8 @@ meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11
|
|||||||
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
|
"framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
meta_renderer_set_legacy_view (renderer, legacy_view);
|
g_assert (!meta_renderer_get_views (renderer));
|
||||||
|
meta_renderer_add_view (renderer, legacy_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaRendererView *
|
static MetaRendererView *
|
||||||
|
@ -63,7 +63,6 @@
|
|||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
#include "compositor/meta-window-actor-x11.h"
|
#include "compositor/meta-window-actor-x11.h"
|
||||||
#include "compositor/meta-window-actor-wayland.h"
|
|
||||||
#include "compositor/meta-window-actor-private.h"
|
#include "compositor/meta-window-actor-private.h"
|
||||||
#include "compositor/meta-window-group-private.h"
|
#include "compositor/meta-window-group-private.h"
|
||||||
#include "core/display-private.h"
|
#include "core/display-private.h"
|
||||||
@ -82,6 +81,7 @@
|
|||||||
#include "x11/meta-x11-display-private.h"
|
#include "x11/meta-x11-display-private.h"
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
#ifdef HAVE_WAYLAND
|
||||||
|
#include "compositor/meta-window-actor-wayland.h"
|
||||||
#include "wayland/meta-wayland-private.h"
|
#include "wayland/meta-wayland-private.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -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_width (MetaShapedTexture *stex);
|
||||||
int meta_shaped_texture_get_height (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
|
#endif
|
||||||
|
@ -87,6 +87,9 @@ struct _MetaShapedTexture
|
|||||||
/* The region containing only fully opaque pixels */
|
/* The region containing only fully opaque pixels */
|
||||||
cairo_region_t *opaque_region;
|
cairo_region_t *opaque_region;
|
||||||
|
|
||||||
|
/* MetaCullable regions, see that documentation for more details */
|
||||||
|
cairo_region_t *clip_region;
|
||||||
|
|
||||||
gboolean size_invalid;
|
gboolean size_invalid;
|
||||||
MetaMonitorTransform transform;
|
MetaMonitorTransform transform;
|
||||||
gboolean has_viewport_src_rect;
|
gboolean has_viewport_src_rect;
|
||||||
@ -214,6 +217,15 @@ ensure_size_valid (MetaShapedTexture *stex)
|
|||||||
update_size (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
|
static void
|
||||||
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
|
meta_shaped_texture_reset_pipelines (MetaShapedTexture *stex)
|
||||||
{
|
{
|
||||||
@ -239,6 +251,7 @@ meta_shaped_texture_dispose (GObject *object)
|
|||||||
meta_shaped_texture_reset_pipelines (stex);
|
meta_shaped_texture_reset_pipelines (stex);
|
||||||
|
|
||||||
g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
|
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);
|
g_clear_pointer (&stex->snippet, cogl_object_unref);
|
||||||
|
|
||||||
@ -390,17 +403,14 @@ get_unblended_pipeline (MetaShapedTexture *stex,
|
|||||||
CoglContext *ctx)
|
CoglContext *ctx)
|
||||||
{
|
{
|
||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
CoglColor color;
|
|
||||||
|
|
||||||
if (stex->unblended_pipeline)
|
if (stex->unblended_pipeline)
|
||||||
return stex->unblended_pipeline;
|
return stex->unblended_pipeline;
|
||||||
|
|
||||||
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
|
pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx));
|
||||||
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
|
cogl_pipeline_set_layer_combine (pipeline, 0,
|
||||||
cogl_pipeline_set_blend (pipeline,
|
"RGBA = REPLACE (TEXTURE)",
|
||||||
"RGBA = ADD (SRC_COLOR, 0)",
|
NULL);
|
||||||
NULL);
|
|
||||||
cogl_pipeline_set_color (pipeline, &color);
|
|
||||||
|
|
||||||
stex->unblended_pipeline = pipeline;
|
stex->unblended_pipeline = pipeline;
|
||||||
|
|
||||||
@ -585,12 +595,19 @@ do_paint_content (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
if (use_opaque_region)
|
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);
|
cairo_region_subtract (blended_tex_region, stex->opaque_region);
|
||||||
}
|
}
|
||||||
else
|
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
|
/* 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. */
|
/* First, paint the unblended parts, which are part of the opaque region. */
|
||||||
if (use_opaque_region)
|
if (use_opaque_region)
|
||||||
{
|
{
|
||||||
|
cairo_region_t *region;
|
||||||
int n_rects;
|
int n_rects;
|
||||||
int i;
|
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;
|
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_texture (opaque_pipeline, 0, paint_tex);
|
||||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
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++)
|
for (i = 0; i < n_rects; i++)
|
||||||
{
|
{
|
||||||
cairo_rectangle_int_t rect;
|
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,
|
paint_clipped_rectangle_node (stex, root_node,
|
||||||
opaque_pipeline,
|
opaque_pipeline,
|
||||||
&rect, alloc);
|
&rect, alloc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cairo_region_destroy (region);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, go ahead and paint the blended parts. */
|
/* Now, go ahead and paint the blended parts. */
|
||||||
@ -757,6 +787,9 @@ meta_shaped_texture_paint_content (ClutterContent *content,
|
|||||||
CoglTexture *paint_tex = NULL;
|
CoglTexture *paint_tex = NULL;
|
||||||
uint8_t opacity;
|
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
|
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||||
* used together with SGIS_generate_mipmap, however this is very
|
* used together with SGIS_generate_mipmap, however this is very
|
||||||
* rarely supported. Also, even when it is supported there
|
* rarely supported. Also, even when it is supported there
|
||||||
|
@ -34,7 +34,6 @@ typedef struct _MetaSurfaceActorPrivate
|
|||||||
cairo_region_t *input_region;
|
cairo_region_t *input_region;
|
||||||
|
|
||||||
/* MetaCullable regions, see that documentation for more details */
|
/* MetaCullable regions, see that documentation for more details */
|
||||||
cairo_region_t *clip_region;
|
|
||||||
cairo_region_t *unobscured_region;
|
cairo_region_t *unobscured_region;
|
||||||
|
|
||||||
/* Freeze/thaw accounting */
|
/* Freeze/thaw accounting */
|
||||||
@ -58,6 +57,12 @@ enum
|
|||||||
|
|
||||||
static guint signals[LAST_SIGNAL];
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
IN_STAGE_PERSPECTIVE,
|
||||||
|
IN_ACTOR_PERSPECTIVE
|
||||||
|
} ScalePerspectiveType;
|
||||||
|
|
||||||
static cairo_region_t *
|
static cairo_region_t *
|
||||||
effective_unobscured_region (MetaSurfaceActor *surface_actor)
|
effective_unobscured_region (MetaSurfaceActor *surface_actor)
|
||||||
{
|
{
|
||||||
@ -79,18 +84,39 @@ effective_unobscured_region (MetaSurfaceActor *surface_actor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static cairo_region_t*
|
static cairo_region_t*
|
||||||
get_scaled_region (MetaSurfaceActor *surface_actor,
|
get_scaled_region (MetaSurfaceActor *surface_actor,
|
||||||
cairo_region_t *region)
|
cairo_region_t *region,
|
||||||
|
ScalePerspectiveType scale_perspective)
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor;
|
MetaWindowActor *window_actor;
|
||||||
|
cairo_region_t *scaled_region;
|
||||||
int geometry_scale;
|
int geometry_scale;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor));
|
window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor));
|
||||||
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
||||||
|
|
||||||
return meta_region_scale_double (region,
|
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
||||||
1.0 / geometry_scale,
|
cairo_region_translate (region, x, y);
|
||||||
META_ROUNDING_STRATEGY_GROW);
|
|
||||||
|
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
|
static void
|
||||||
@ -120,8 +146,9 @@ set_unobscured_region (MetaSurfaceActor *surface_actor,
|
|||||||
.height = height,
|
.height = height,
|
||||||
};
|
};
|
||||||
|
|
||||||
priv->unobscured_region =
|
priv->unobscured_region = get_scaled_region (surface_actor,
|
||||||
get_scaled_region (surface_actor, unobscured_region);
|
unobscured_region,
|
||||||
|
IN_ACTOR_PERSPECTIVE);
|
||||||
|
|
||||||
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
|
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
|
||||||
}
|
}
|
||||||
@ -134,30 +161,23 @@ set_clip_region (MetaSurfaceActor *surface_actor,
|
|||||||
{
|
{
|
||||||
MetaSurfaceActorPrivate *priv =
|
MetaSurfaceActorPrivate *priv =
|
||||||
meta_surface_actor_get_instance_private (surface_actor);
|
meta_surface_actor_get_instance_private (surface_actor);
|
||||||
|
MetaShapedTexture *stex = priv->texture;
|
||||||
|
|
||||||
g_clear_pointer (&priv->clip_region, cairo_region_destroy);
|
if (clip_region && !cairo_region_is_empty (clip_region))
|
||||||
if (clip_region)
|
|
||||||
{
|
{
|
||||||
if (cairo_region_is_empty (clip_region))
|
cairo_region_t *region;
|
||||||
priv->clip_region = cairo_region_reference (clip_region);
|
|
||||||
else
|
region = get_scaled_region (surface_actor,
|
||||||
priv->clip_region = get_scaled_region (surface_actor, clip_region);
|
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
|
static void
|
||||||
@ -227,7 +247,6 @@ meta_surface_actor_dispose (GObject *object)
|
|||||||
g_clear_object (&priv->texture);
|
g_clear_object (&priv->texture);
|
||||||
|
|
||||||
set_unobscured_region (self, NULL);
|
set_unobscured_region (self, NULL);
|
||||||
set_clip_region (self, NULL);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_surface_actor_parent_class)->dispose (object);
|
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);
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
|
|
||||||
object_class->dispose = meta_surface_actor_dispose;
|
object_class->dispose = meta_surface_actor_dispose;
|
||||||
actor_class->paint = meta_surface_actor_paint;
|
|
||||||
actor_class->pick = meta_surface_actor_pick;
|
actor_class->pick = meta_surface_actor_pick;
|
||||||
actor_class->get_paint_volume = meta_surface_actor_get_paint_volume;
|
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)
|
if (opacity == 0xff)
|
||||||
{
|
{
|
||||||
MetaWindowActor *window_actor;
|
|
||||||
cairo_region_t *scaled_opaque_region;
|
|
||||||
cairo_region_t *opaque_region;
|
cairo_region_t *opaque_region;
|
||||||
int geometry_scale;
|
cairo_region_t *scaled_opaque_region;
|
||||||
float x, y;
|
|
||||||
|
|
||||||
opaque_region = meta_shaped_texture_get_opaque_region (priv->texture);
|
opaque_region = meta_shaped_texture_get_opaque_region (priv->texture);
|
||||||
if (opaque_region)
|
if (opaque_region)
|
||||||
@ -306,14 +321,9 @@ meta_surface_actor_cull_out (MetaCullable *cullable,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
window_actor = meta_window_actor_from_actor (CLUTTER_ACTOR (surface_actor));
|
scaled_opaque_region = get_scaled_region (surface_actor,
|
||||||
geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
|
opaque_region,
|
||||||
clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
|
IN_STAGE_PERSPECTIVE);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (unobscured_region)
|
if (unobscured_region)
|
||||||
cairo_region_subtract (unobscured_region, scaled_opaque_region);
|
cairo_region_subtract (unobscured_region, scaled_opaque_region);
|
||||||
|
@ -85,6 +85,8 @@ struct _MetaWindowActorX11
|
|||||||
cairo_region_t *shape_region;
|
cairo_region_t *shape_region;
|
||||||
/* The region we should clip to when painting the shadow */
|
/* The region we should clip to when painting the shadow */
|
||||||
cairo_region_t *shadow_clip;
|
cairo_region_t *shadow_clip;
|
||||||
|
/* The frame region */
|
||||||
|
cairo_region_t *frame_bounds;
|
||||||
|
|
||||||
/* Extracted size-invariant shape used for shadows */
|
/* Extracted size-invariant shape used for shadows */
|
||||||
MetaWindowShape *shadow_shape;
|
MetaWindowShape *shadow_shape;
|
||||||
@ -702,11 +704,8 @@ set_clip_region_beneath (MetaWindowActorX11 *actor_x11,
|
|||||||
|
|
||||||
if (clip_shadow_under_window (actor_x11))
|
if (clip_shadow_under_window (actor_x11))
|
||||||
{
|
{
|
||||||
cairo_region_t *frame_bounds;
|
if (actor_x11->frame_bounds)
|
||||||
|
cairo_region_subtract (actor_x11->shadow_clip, actor_x11->frame_bounds);
|
||||||
frame_bounds = meta_window_get_frame_bounds (window);
|
|
||||||
if (frame_bounds)
|
|
||||||
cairo_region_subtract (actor_x11->shadow_clip, frame_bounds);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1126,6 +1125,17 @@ update_opaque_region (MetaWindowActorX11 *actor_x11)
|
|||||||
cairo_region_destroy (opaque_region);
|
cairo_region_destroy (opaque_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_frame_bounds (MetaWindowActorX11 *actor_x11)
|
||||||
|
{
|
||||||
|
MetaWindow *window =
|
||||||
|
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11));
|
||||||
|
|
||||||
|
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
|
||||||
|
actor_x11->frame_bounds =
|
||||||
|
cairo_region_copy (meta_window_get_frame_bounds (window));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_regions (MetaWindowActorX11 *actor_x11)
|
update_regions (MetaWindowActorX11 *actor_x11)
|
||||||
{
|
{
|
||||||
@ -1197,6 +1207,7 @@ handle_updates (MetaWindowActorX11 *actor_x11)
|
|||||||
if (!meta_surface_actor_is_visible (surface))
|
if (!meta_surface_actor_is_visible (surface))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
update_frame_bounds (actor_x11);
|
||||||
check_needs_reshape (actor_x11);
|
check_needs_reshape (actor_x11);
|
||||||
check_needs_shadow (actor_x11);
|
check_needs_shadow (actor_x11);
|
||||||
}
|
}
|
||||||
@ -1250,15 +1261,13 @@ meta_window_actor_x11_paint (ClutterActor *actor,
|
|||||||
*/
|
*/
|
||||||
if (!clip && clip_shadow_under_window (actor_x11))
|
if (!clip && clip_shadow_under_window (actor_x11))
|
||||||
{
|
{
|
||||||
cairo_region_t *frame_bounds;
|
|
||||||
cairo_rectangle_int_t bounds;
|
cairo_rectangle_int_t bounds;
|
||||||
|
|
||||||
get_shadow_bounds (actor_x11, appears_focused, &bounds);
|
get_shadow_bounds (actor_x11, appears_focused, &bounds);
|
||||||
clip = cairo_region_create_rectangle (&bounds);
|
clip = cairo_region_create_rectangle (&bounds);
|
||||||
|
|
||||||
frame_bounds = meta_window_get_frame_bounds (window);
|
if (actor_x11->frame_bounds)
|
||||||
if (frame_bounds)
|
cairo_region_subtract (clip, actor_x11->frame_bounds);
|
||||||
cairo_region_subtract (clip, frame_bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
|
||||||
@ -1545,6 +1554,7 @@ meta_window_actor_x11_dispose (GObject *object)
|
|||||||
|
|
||||||
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
|
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
|
||||||
g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy);
|
g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy);
|
||||||
|
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
|
||||||
|
|
||||||
g_clear_pointer (&actor_x11->shadow_class, g_free);
|
g_clear_pointer (&actor_x11->shadow_class, g_free);
|
||||||
g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref);
|
g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref);
|
||||||
@ -1620,8 +1630,8 @@ meta_window_actor_x11_init (MetaWindowActorX11 *self)
|
|||||||
|
|
||||||
self->shadow_factory = meta_shadow_factory_get_default ();
|
self->shadow_factory = meta_shadow_factory_get_default ();
|
||||||
self->shadow_factory_changed_handler_id =
|
self->shadow_factory_changed_handler_id =
|
||||||
g_signal_connect (self->shadow_factory,
|
g_signal_connect_swapped (self->shadow_factory,
|
||||||
"changed",
|
"changed",
|
||||||
G_CALLBACK (invalidate_shadow),
|
G_CALLBACK (invalidate_shadow),
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
@ -1300,6 +1300,7 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
|
|||||||
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
||||||
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
cogl_framebuffer_clear (framebuffer, COGL_BUFFER_BIT_COLOR, &clear_color);
|
||||||
cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
cogl_framebuffer_orthographic (framebuffer, 0, 0, width, height, 0, 1.0);
|
||||||
|
cogl_framebuffer_set_viewport (framebuffer, 0, 0, width, height);
|
||||||
|
|
||||||
meta_rectangle_scale_double (bounds, resource_scale,
|
meta_rectangle_scale_double (bounds, resource_scale,
|
||||||
META_ROUNDING_STRATEGY_GROW,
|
META_ROUNDING_STRATEGY_GROW,
|
||||||
|
@ -2129,7 +2129,7 @@ process_special_modifier_key (MetaDisplay *display,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
else if (event->type == CLUTTER_KEY_PRESS &&
|
else if (event->type == CLUTTER_KEY_PRESS &&
|
||||||
(event->modifier_state & ~(IGNORED_MODIFIERS)) == 0 &&
|
((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
|
||||||
resolved_key_combo_has_keycode (resolved_key_combo,
|
resolved_key_combo_has_keycode (resolved_key_combo,
|
||||||
event->hardware_keycode))
|
event->hardware_keycode))
|
||||||
{
|
{
|
||||||
|
@ -152,6 +152,7 @@ owner_changed_cb (MetaSelection *selection,
|
|||||||
display->saved_clipboard);
|
display->saved_clipboard);
|
||||||
g_set_object (&display->selection_source, new_owner);
|
g_set_object (&display->selection_source, new_owner);
|
||||||
meta_selection_set_owner (selection, selection_type, 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;
|
MetaSelection *selection;
|
||||||
|
|
||||||
|
g_clear_object (&display->selection_source);
|
||||||
g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
|
g_clear_pointer (&display->saved_clipboard, g_bytes_unref);
|
||||||
g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
|
g_clear_pointer (&display->saved_clipboard_mimetype, g_free);
|
||||||
selection = meta_display_get_selection (display);
|
selection = meta_display_get_selection (display);
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Red Hat
|
* Copyright (C) 2020 Red Hat
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -19,16 +17,16 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*
|
*
|
||||||
* Written by:
|
* Written by:
|
||||||
* Jonas Ådahl <jadahl@gmail.com>
|
* Carlos Garnacho <carlosg@gnome.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
#ifndef META_SELECTION_PRIVATE_H
|
||||||
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
#define META_SELECTION_PRIVATE_H
|
||||||
|
|
||||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
|
#include "meta/meta-selection.h"
|
||||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
|
|
||||||
meta_wayland_data_source_primary,
|
|
||||||
META, WAYLAND_DATA_SOURCE_PRIMARY,
|
|
||||||
MetaWaylandDataSource);
|
|
||||||
|
|
||||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */
|
MetaSelectionSource *
|
||||||
|
meta_selection_get_current_owner (MetaSelection *selection,
|
||||||
|
MetaSelectionType selection_type);
|
||||||
|
|
||||||
|
#endif /* META_SELECTION_PRIVATE_H */
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "core/meta-selection-private.h"
|
||||||
#include "meta/meta-selection.h"
|
#include "meta/meta-selection.h"
|
||||||
|
|
||||||
typedef struct TransferRequest TransferRequest;
|
typedef struct TransferRequest TransferRequest;
|
||||||
@ -50,6 +51,9 @@ static guint signals[N_SIGNALS] = { 0 };
|
|||||||
|
|
||||||
G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void read_selection_source_async (GTask *task,
|
||||||
|
TransferRequest *request);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_selection_dispose (GObject *object)
|
meta_selection_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@ -216,6 +220,7 @@ write_cb (GOutputStream *stream,
|
|||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
GTask *task)
|
GTask *task)
|
||||||
{
|
{
|
||||||
|
TransferRequest *request;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
g_output_stream_write_bytes_finish (stream, result, &error);
|
g_output_stream_write_bytes_finish (stream, result, &error);
|
||||||
@ -226,8 +231,17 @@ write_cb (GOutputStream *stream,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_task_return_boolean (task, TRUE);
|
request = g_task_get_task_data (task);
|
||||||
g_object_unref (task);
|
|
||||||
|
if (request->len > 0)
|
||||||
|
{
|
||||||
|
read_selection_source_async (task, request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_task_return_boolean (task, TRUE);
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -246,8 +260,26 @@ read_cb (GInputStream *stream,
|
|||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (g_bytes_get_size (bytes) == 0)
|
||||||
|
{
|
||||||
|
g_task_return_boolean (task, TRUE);
|
||||||
|
g_object_unref (task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
request = g_task_get_task_data (task);
|
request = g_task_get_task_data (task);
|
||||||
|
|
||||||
|
if (request->len < g_bytes_get_size (bytes))
|
||||||
|
{
|
||||||
|
GBytes *copy;
|
||||||
|
|
||||||
|
/* Trim content */
|
||||||
|
copy = g_bytes_new_from_bytes (bytes, 0, request->len);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
bytes = copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
request->len -= g_bytes_get_size (bytes);
|
||||||
g_output_stream_write_bytes_async (request->ostream,
|
g_output_stream_write_bytes_async (request->ostream,
|
||||||
bytes,
|
bytes,
|
||||||
G_PRIORITY_DEFAULT,
|
G_PRIORITY_DEFAULT,
|
||||||
@ -257,6 +289,18 @@ read_cb (GInputStream *stream,
|
|||||||
g_bytes_unref (bytes);
|
g_bytes_unref (bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
read_selection_source_async (GTask *task,
|
||||||
|
TransferRequest *request)
|
||||||
|
{
|
||||||
|
g_input_stream_read_bytes_async (request->istream,
|
||||||
|
(gsize) request->len,
|
||||||
|
G_PRIORITY_DEFAULT,
|
||||||
|
g_task_get_cancellable (task),
|
||||||
|
(GAsyncReadyCallback) read_cb,
|
||||||
|
task);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
source_read_cb (MetaSelectionSource *source,
|
source_read_cb (MetaSelectionSource *source,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
@ -290,12 +334,7 @@ source_read_cb (MetaSelectionSource *source,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_input_stream_read_bytes_async (request->istream,
|
read_selection_source_async (task, request);
|
||||||
(gsize) request->len,
|
|
||||||
G_PRIORITY_DEFAULT,
|
|
||||||
g_task_get_cancellable (task),
|
|
||||||
(GAsyncReadyCallback) read_cb,
|
|
||||||
task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,3 +403,13 @@ meta_selection_transfer_finish (MetaSelection *selection,
|
|||||||
|
|
||||||
return g_task_propagate_boolean (G_TASK (result), error);
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaSelectionSource *
|
||||||
|
meta_selection_get_current_owner (MetaSelection *selection,
|
||||||
|
MetaSelectionType selection_type)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
|
||||||
|
g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
|
||||||
|
|
||||||
|
return selection->owners[selection_type];
|
||||||
|
}
|
||||||
|
@ -3751,6 +3751,8 @@ meta_window_activate_full (MetaWindow *window,
|
|||||||
meta_window_focus (window, timestamp);
|
meta_window_focus (window, timestamp);
|
||||||
else
|
else
|
||||||
meta_workspace_activate_with_focus (window->workspace, window, timestamp);
|
meta_workspace_activate_with_focus (window->workspace, window, timestamp);
|
||||||
|
|
||||||
|
meta_window_check_alive (window, timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function exists since most of the functionality in window_activate
|
/* This function exists since most of the functionality in window_activate
|
||||||
@ -4790,8 +4792,6 @@ meta_window_focus (MetaWindow *window,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_window_check_alive (window, timestamp);
|
|
||||||
|
|
||||||
META_WINDOW_GET_CLASS (window)->focus (window, timestamp);
|
META_WINDOW_GET_CLASS (window)->focus (window, timestamp);
|
||||||
|
|
||||||
if (window->display->event_route == META_EVENT_ROUTE_NORMAL)
|
if (window->display->event_route == META_EVENT_ROUTE_NORMAL)
|
||||||
@ -8349,6 +8349,7 @@ meta_window_handle_ungrabbed_event (MetaWindow *window,
|
|||||||
"Focusing %s due to button %u press (display.c)\n",
|
"Focusing %s due to button %u press (display.c)\n",
|
||||||
window->desc, button);
|
window->desc, button);
|
||||||
meta_window_focus (window, event->any.time);
|
meta_window_focus (window, event->any.time);
|
||||||
|
meta_window_check_alive (window, event->any.time);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* However, do allow terminals to lose focus due to new
|
/* However, do allow terminals to lose focus due to new
|
||||||
|
@ -495,7 +495,22 @@ if have_wayland
|
|||||||
'wayland/meta-wayland-cursor-surface.h',
|
'wayland/meta-wayland-cursor-surface.h',
|
||||||
'wayland/meta-wayland-data-device.c',
|
'wayland/meta-wayland-data-device.c',
|
||||||
'wayland/meta-wayland-data-device.h',
|
'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.c',
|
||||||
'wayland/meta-wayland-dma-buf.h',
|
'wayland/meta-wayland-dma-buf.h',
|
||||||
'wayland/meta-wayland-dnd-surface.c',
|
'wayland/meta-wayland-dnd-surface.c',
|
||||||
@ -790,6 +805,7 @@ if have_wayland
|
|||||||
['linux-dmabuf', 'unstable', 'v1', ],
|
['linux-dmabuf', 'unstable', 'v1', ],
|
||||||
['pointer-constraints', 'unstable', 'v1', ],
|
['pointer-constraints', 'unstable', 'v1', ],
|
||||||
['pointer-gestures', 'unstable', 'v1', ],
|
['pointer-gestures', 'unstable', 'v1', ],
|
||||||
|
['primary-selection', 'unstable', 'v1', ],
|
||||||
['relative-pointer', 'unstable', 'v1', ],
|
['relative-pointer', 'unstable', 'v1', ],
|
||||||
['tablet', 'unstable', 'v2', ],
|
['tablet', 'unstable', 'v2', ],
|
||||||
['text-input', 'unstable', 'v3', ],
|
['text-input', 'unstable', 'v3', ],
|
||||||
|
@ -67,6 +67,9 @@ on_timeout (gpointer data)
|
|||||||
}
|
}
|
||||||
else if (test_num == 2)
|
else if (test_num == 2)
|
||||||
{
|
{
|
||||||
|
ClutterActorBox over_actor_box =
|
||||||
|
CLUTTER_ACTOR_BOX_INIT (0, 0, STAGE_WIDTH, STAGE_HEIGHT);
|
||||||
|
|
||||||
/* Make the actor visible but set a clip so that only some
|
/* Make the actor visible but set a clip so that only some
|
||||||
of the actors are accessible */
|
of the actors are accessible */
|
||||||
clutter_actor_show (over_actor);
|
clutter_actor_show (over_actor);
|
||||||
@ -76,6 +79,11 @@ on_timeout (gpointer data)
|
|||||||
state->actor_width * (ACTORS_X - 4),
|
state->actor_width * (ACTORS_X - 4),
|
||||||
state->actor_height * (ACTORS_Y - 4));
|
state->actor_height * (ACTORS_Y - 4));
|
||||||
|
|
||||||
|
/* Only allocated actors can be picked, so force an allocation
|
||||||
|
* of the overlay actor here.
|
||||||
|
*/
|
||||||
|
clutter_actor_allocate (over_actor, &over_actor_box, 0);
|
||||||
|
|
||||||
if (g_test_verbose ())
|
if (g_test_verbose ())
|
||||||
g_print ("Clipped covering actor:\n");
|
g_print ("Clipped covering actor:\n");
|
||||||
}
|
}
|
||||||
@ -175,10 +183,10 @@ actor_pick (void)
|
|||||||
for (y = 0; y < ACTORS_Y; y++)
|
for (y = 0; y < ACTORS_Y; y++)
|
||||||
for (x = 0; x < ACTORS_X; x++)
|
for (x = 0; x < ACTORS_X; x++)
|
||||||
{
|
{
|
||||||
ClutterColor color = { x * 255 / (ACTORS_X - 1),
|
ClutterColor color = { x * 255 / (ACTORS_X - 1),
|
||||||
y * 255 / (ACTORS_Y - 1),
|
y * 255 / (ACTORS_Y - 1),
|
||||||
128, 255 };
|
128, 255 };
|
||||||
ClutterActor *rect = clutter_rectangle_new_with_color (&color);
|
ClutterActor *rect = clutter_rectangle_new_with_color (&color);
|
||||||
|
|
||||||
clutter_actor_set_position (rect,
|
clutter_actor_set_position (rect,
|
||||||
x * state.actor_width,
|
x * state.actor_width,
|
||||||
@ -187,9 +195,9 @@ actor_pick (void)
|
|||||||
state.actor_width,
|
state.actor_width,
|
||||||
state.actor_height);
|
state.actor_height);
|
||||||
|
|
||||||
clutter_actor_add_child (state.stage, rect);
|
clutter_actor_add_child (state.stage, rect);
|
||||||
|
|
||||||
state.actors[y * ACTORS_X + x] = rect;
|
state.actors[y * ACTORS_X + x] = rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_actor_show (state.stage);
|
clutter_actor_show (state.stage);
|
||||||
|
23
src/tests/monitor-configs/lid-scale.xml
Normal file
23
src/tests/monitor-configs/lid-scale.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<monitors version="2">
|
||||||
|
<configuration>
|
||||||
|
<logicalmonitor>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<primary>yes</primary>
|
||||||
|
<scale>2</scale>
|
||||||
|
<monitor>
|
||||||
|
<monitorspec>
|
||||||
|
<connector>eDP-1</connector>
|
||||||
|
<vendor>MetaProduct's Inc.</vendor>
|
||||||
|
<product>MetaMonitor</product>
|
||||||
|
<serial>0x123456</serial>
|
||||||
|
</monitorspec>
|
||||||
|
<mode>
|
||||||
|
<width>1920</width>
|
||||||
|
<height>1080</height>
|
||||||
|
<rate>60.000495910644531</rate>
|
||||||
|
</mode>
|
||||||
|
</monitor>
|
||||||
|
</logicalmonitor>
|
||||||
|
</configuration>
|
||||||
|
</monitors>
|
@ -2868,6 +2868,116 @@ meta_test_monitor_lid_closed_with_hotplugged_external (void)
|
|||||||
check_monitor_configuration (&test_case);
|
check_monitor_configuration (&test_case);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_monitor_lid_scaled_closed_opened (void)
|
||||||
|
{
|
||||||
|
MonitorTestCase test_case = {
|
||||||
|
.setup = {
|
||||||
|
.modes = {
|
||||||
|
{
|
||||||
|
.width = 1920,
|
||||||
|
.height = 1080,
|
||||||
|
.refresh_rate = 60.000495910644531
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_modes = 1,
|
||||||
|
.outputs = {
|
||||||
|
{
|
||||||
|
.crtc = 0,
|
||||||
|
.modes = { 0 },
|
||||||
|
.n_modes = 1,
|
||||||
|
.preferred_mode = 0,
|
||||||
|
.possible_crtcs = { 0 },
|
||||||
|
.n_possible_crtcs = 1,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
.is_laptop_panel = TRUE
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.n_outputs = 1,
|
||||||
|
.crtcs = {
|
||||||
|
{
|
||||||
|
.current_mode = 0
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.n_crtcs = 1
|
||||||
|
},
|
||||||
|
|
||||||
|
.expect = {
|
||||||
|
.monitors = {
|
||||||
|
{
|
||||||
|
.outputs = { 0 },
|
||||||
|
.n_outputs = 1,
|
||||||
|
.modes = {
|
||||||
|
{
|
||||||
|
.width = 1920,
|
||||||
|
.height = 1080,
|
||||||
|
.refresh_rate = 60.000495910644531,
|
||||||
|
.crtc_modes = {
|
||||||
|
{
|
||||||
|
.output = 0,
|
||||||
|
.crtc_mode = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_modes = 1,
|
||||||
|
.current_mode = 0,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_monitors = 1,
|
||||||
|
.logical_monitors = {
|
||||||
|
{
|
||||||
|
.monitors = { 0 },
|
||||||
|
.n_monitors = 1,
|
||||||
|
.layout = { .x = 0, .y = 0, .width = 960, .height = 540 },
|
||||||
|
.scale = 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_logical_monitors = 1,
|
||||||
|
.primary_logical_monitor = 0,
|
||||||
|
.n_outputs = 1,
|
||||||
|
.crtcs = {
|
||||||
|
{
|
||||||
|
.current_mode = 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_crtcs = 1,
|
||||||
|
.n_tiled_monitors = 0,
|
||||||
|
.screen_width = 960,
|
||||||
|
.screen_height = 540
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MetaMonitorTestSetup *test_setup;
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
|
||||||
|
if (!meta_is_stage_views_enabled ())
|
||||||
|
{
|
||||||
|
g_test_skip ("Not using stage views");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
test_setup = create_monitor_test_setup (&test_case,
|
||||||
|
MONITOR_TEST_FLAG_NONE);
|
||||||
|
set_custom_monitor_config ("lid-scale.xml");
|
||||||
|
emulate_hotplug (test_setup);
|
||||||
|
check_monitor_configuration (&test_case);
|
||||||
|
|
||||||
|
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), TRUE);
|
||||||
|
meta_monitor_manager_lid_is_closed_changed (monitor_manager);
|
||||||
|
|
||||||
|
check_monitor_configuration (&test_case);
|
||||||
|
|
||||||
|
meta_backend_test_set_is_lid_closed (META_BACKEND_TEST (backend), FALSE);
|
||||||
|
meta_monitor_manager_lid_is_closed_changed (monitor_manager);
|
||||||
|
|
||||||
|
check_monitor_configuration (&test_case);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_test_monitor_no_outputs (void)
|
meta_test_monitor_no_outputs (void)
|
||||||
{
|
{
|
||||||
@ -4828,12 +4938,13 @@ meta_test_monitor_custom_second_rotated_tiled_config (void)
|
|||||||
.current_mode = 1,
|
.current_mode = 1,
|
||||||
.transform = META_MONITOR_TRANSFORM_90,
|
.transform = META_MONITOR_TRANSFORM_90,
|
||||||
.x = 1024,
|
.x = 1024,
|
||||||
.y = 400,
|
.y = 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
.current_mode = 1,
|
.current_mode = 1,
|
||||||
.transform = META_MONITOR_TRANSFORM_90,
|
.transform = META_MONITOR_TRANSFORM_90,
|
||||||
.x = 1024,
|
.x = 1024,
|
||||||
|
.y = 400,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.n_crtcs = 3,
|
.n_crtcs = 3,
|
||||||
@ -4859,6 +4970,198 @@ meta_test_monitor_custom_second_rotated_tiled_config (void)
|
|||||||
check_monitor_configuration (&test_case);
|
check_monitor_configuration (&test_case);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_test_monitor_custom_second_rotated_nonnative_tiled_config (void)
|
||||||
|
{
|
||||||
|
MonitorTestCase test_case = {
|
||||||
|
.setup = {
|
||||||
|
.modes = {
|
||||||
|
{
|
||||||
|
.width = 1024,
|
||||||
|
.height = 768,
|
||||||
|
.refresh_rate = 60.000495910644531
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.width = 400,
|
||||||
|
.height = 600,
|
||||||
|
.refresh_rate = 60.000495910644531
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_modes = 2,
|
||||||
|
.outputs = {
|
||||||
|
{
|
||||||
|
.crtc = 0,
|
||||||
|
.modes = { 0 },
|
||||||
|
.n_modes = 1,
|
||||||
|
.preferred_mode = 0,
|
||||||
|
.possible_crtcs = { 0 },
|
||||||
|
.n_possible_crtcs = 1,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.crtc = -1,
|
||||||
|
.modes = { 1 },
|
||||||
|
.n_modes = 1,
|
||||||
|
.preferred_mode = 1,
|
||||||
|
.possible_crtcs = { 1, 2 },
|
||||||
|
.n_possible_crtcs = 2,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
.tile_info = {
|
||||||
|
.group_id = 1,
|
||||||
|
.max_h_tiles = 2,
|
||||||
|
.max_v_tiles = 1,
|
||||||
|
.loc_h_tile = 0,
|
||||||
|
.loc_v_tile = 0,
|
||||||
|
.tile_w = 400,
|
||||||
|
.tile_h = 600
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.crtc = -1,
|
||||||
|
.modes = { 1 },
|
||||||
|
.n_modes = 1,
|
||||||
|
.preferred_mode = 1,
|
||||||
|
.possible_crtcs = { 1, 2 },
|
||||||
|
.n_possible_crtcs = 2,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
.tile_info = {
|
||||||
|
.group_id = 1,
|
||||||
|
.max_h_tiles = 2,
|
||||||
|
.max_v_tiles = 1,
|
||||||
|
.loc_h_tile = 1,
|
||||||
|
.loc_v_tile = 0,
|
||||||
|
.tile_w = 400,
|
||||||
|
.tile_h = 600
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_outputs = 3,
|
||||||
|
.crtcs = {
|
||||||
|
{
|
||||||
|
.current_mode = -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.current_mode = -1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.current_mode = -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_crtcs = 3
|
||||||
|
},
|
||||||
|
|
||||||
|
.expect = {
|
||||||
|
.monitors = {
|
||||||
|
{
|
||||||
|
.outputs = { 0 },
|
||||||
|
.n_outputs = 1,
|
||||||
|
.modes = {
|
||||||
|
{
|
||||||
|
.width = 1024,
|
||||||
|
.height = 768,
|
||||||
|
.refresh_rate = 60.000495910644531,
|
||||||
|
.crtc_modes = {
|
||||||
|
{
|
||||||
|
.output = 0,
|
||||||
|
.crtc_mode = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_modes = 1,
|
||||||
|
.current_mode = 0,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.outputs = { 1, 2 },
|
||||||
|
.n_outputs = 2,
|
||||||
|
.modes = {
|
||||||
|
{
|
||||||
|
.width = 800,
|
||||||
|
.height = 600,
|
||||||
|
.refresh_rate = 60.000495910644531,
|
||||||
|
.crtc_modes = {
|
||||||
|
{
|
||||||
|
.output = 1,
|
||||||
|
.crtc_mode = 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.output = 2,
|
||||||
|
.crtc_mode = 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_modes = 1,
|
||||||
|
.current_mode = 0,
|
||||||
|
.width_mm = 222,
|
||||||
|
.height_mm = 125,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_monitors = 2,
|
||||||
|
.logical_monitors = {
|
||||||
|
{
|
||||||
|
.monitors = { 0 },
|
||||||
|
.n_monitors = 1,
|
||||||
|
.layout = { .x = 0, .y = 256, .width = 1024, .height = 768 },
|
||||||
|
.scale = 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.monitors = { 1 },
|
||||||
|
.n_monitors = 1,
|
||||||
|
.layout = { .x = 1024, .y = 0, .width = 600, .height = 800 },
|
||||||
|
.scale = 1,
|
||||||
|
.transform = META_MONITOR_TRANSFORM_90
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_logical_monitors = 2,
|
||||||
|
.primary_logical_monitor = 0,
|
||||||
|
.n_outputs = 3,
|
||||||
|
.crtcs = {
|
||||||
|
{
|
||||||
|
.current_mode = 0,
|
||||||
|
.y = 256,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.current_mode = 1,
|
||||||
|
.transform = META_MONITOR_TRANSFORM_NORMAL,
|
||||||
|
.x = 1024,
|
||||||
|
.y = 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.current_mode = 1,
|
||||||
|
.transform = META_MONITOR_TRANSFORM_NORMAL,
|
||||||
|
.x = 1024,
|
||||||
|
.y = 400,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
.n_crtcs = 3,
|
||||||
|
.n_tiled_monitors = 1,
|
||||||
|
.screen_width = 1024 + 600,
|
||||||
|
.screen_height = 1024
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MetaMonitorTestSetup *test_setup;
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaMonitorManager *monitor_manager =
|
||||||
|
meta_backend_get_monitor_manager (backend);
|
||||||
|
MetaMonitorManagerTest *monitor_manager_test =
|
||||||
|
META_MONITOR_MANAGER_TEST (monitor_manager);
|
||||||
|
|
||||||
|
meta_monitor_manager_test_set_handles_transforms (monitor_manager_test,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
test_setup = create_monitor_test_setup (&test_case,
|
||||||
|
MONITOR_TEST_FLAG_NONE);
|
||||||
|
set_custom_monitor_config ("second-rotated-tiled.xml");
|
||||||
|
emulate_hotplug (test_setup);
|
||||||
|
check_monitor_configuration (&test_case);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_test_monitor_custom_second_rotated_nonnative_config (void)
|
meta_test_monitor_custom_second_rotated_nonnative_config (void)
|
||||||
{
|
{
|
||||||
@ -6058,6 +6361,8 @@ init_monitor_tests (void)
|
|||||||
meta_test_monitor_lid_closed_no_external);
|
meta_test_monitor_lid_closed_no_external);
|
||||||
add_monitor_test ("/backends/monitor/lid-closed-with-hotplugged-external",
|
add_monitor_test ("/backends/monitor/lid-closed-with-hotplugged-external",
|
||||||
meta_test_monitor_lid_closed_with_hotplugged_external);
|
meta_test_monitor_lid_closed_with_hotplugged_external);
|
||||||
|
add_monitor_test ("/backends/monitor/lid-scaled-closed-opened",
|
||||||
|
meta_test_monitor_lid_scaled_closed_opened);
|
||||||
add_monitor_test ("/backends/monitor/no-outputs",
|
add_monitor_test ("/backends/monitor/no-outputs",
|
||||||
meta_test_monitor_no_outputs);
|
meta_test_monitor_no_outputs);
|
||||||
add_monitor_test ("/backends/monitor/underscanning-config",
|
add_monitor_test ("/backends/monitor/underscanning-config",
|
||||||
@ -6093,6 +6398,8 @@ init_monitor_tests (void)
|
|||||||
meta_test_monitor_custom_second_rotated_config);
|
meta_test_monitor_custom_second_rotated_config);
|
||||||
add_monitor_test ("/backends/monitor/custom/second-rotated-tiled-config",
|
add_monitor_test ("/backends/monitor/custom/second-rotated-tiled-config",
|
||||||
meta_test_monitor_custom_second_rotated_tiled_config);
|
meta_test_monitor_custom_second_rotated_tiled_config);
|
||||||
|
add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-tiled-config",
|
||||||
|
meta_test_monitor_custom_second_rotated_nonnative_tiled_config);
|
||||||
add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-config",
|
add_monitor_test ("/backends/monitor/custom/second-rotated-nonnative-config",
|
||||||
meta_test_monitor_custom_second_rotated_nonnative_config);
|
meta_test_monitor_custom_second_rotated_nonnative_config);
|
||||||
add_monitor_test ("/backends/monitor/custom/interlaced-config",
|
add_monitor_test ("/backends/monitor/custom/interlaced-config",
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "meta/meta-selection-source.h"
|
#include "meta/meta-selection-source.h"
|
||||||
#include "wayland/meta-wayland-data-device.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 ())
|
#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 */
|
File diff suppressed because it is too large
Load Diff
@ -28,42 +28,20 @@
|
|||||||
|
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
#include "meta/meta-selection-source.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"
|
#include "wayland/meta-wayland-types.h"
|
||||||
|
|
||||||
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
|
||||||
typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
|
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
|
struct _MetaWaylandDataDevice
|
||||||
{
|
{
|
||||||
uint32_t selection_serial;
|
uint32_t selection_serial;
|
||||||
uint32_t primary_serial;
|
|
||||||
MetaWaylandDataSource *selection_data_source;
|
MetaWaylandDataSource *selection_data_source;
|
||||||
MetaWaylandDataSource *dnd_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 resource_list;
|
||||||
struct wl_list primary_resource_list;
|
struct wl_list focus_resource_list;
|
||||||
MetaWaylandDragGrab *current_grab;
|
MetaWaylandDragGrab *current_grab;
|
||||||
struct wl_client *focus_client;
|
struct wl_client *focus_client;
|
||||||
|
|
||||||
@ -89,42 +67,7 @@ void meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_de
|
|||||||
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
void meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||||
MetaWaylandDataSource *source,
|
MetaWaylandDataSource *source,
|
||||||
guint32 serial);
|
guint32 serial);
|
||||||
void meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
void meta_wayland_data_device_unset_dnd_selection (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);
|
|
||||||
|
|
||||||
const MetaWaylandDragDestFuncs *
|
const MetaWaylandDragDestFuncs *
|
||||||
meta_wayland_data_device_get_drag_dest_funcs (void);
|
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 */
|
@ -603,7 +603,6 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
|
|||||||
|
|
||||||
meta_wayland_keyboard_end_grab (keyboard);
|
meta_wayland_keyboard_end_grab (keyboard);
|
||||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
|
||||||
|
|
||||||
wl_list_remove (&keyboard->resource_list);
|
wl_list_remove (&keyboard->resource_list);
|
||||||
wl_list_init (&keyboard->resource_list);
|
wl_list_init (&keyboard->resource_list);
|
||||||
@ -917,7 +916,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
|||||||
keyboard_handle_focus_surface_destroy;
|
keyboard_handle_focus_surface_destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_keyboard_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object);
|
||||||
|
|
||||||
|
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass)
|
meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass)
|
||||||
{
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->finalize = meta_wayland_keyboard_finalize;
|
||||||
}
|
}
|
||||||
|
@ -662,8 +662,6 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
|||||||
MetaWaylandSurface *surface =
|
MetaWaylandSurface *surface =
|
||||||
meta_wayland_surface_role_get_surface (surface_role);
|
meta_wayland_surface_role_get_surface (surface_role);
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaRectangle old_geometry;
|
|
||||||
gboolean geometry_changed;
|
|
||||||
|
|
||||||
window = meta_wayland_surface_get_window (surface);
|
window = meta_wayland_surface_get_window (surface);
|
||||||
if (!window)
|
if (!window)
|
||||||
@ -672,8 +670,6 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_geometry = xdg_surface_priv->geometry;
|
|
||||||
|
|
||||||
surface_role_class =
|
surface_role_class =
|
||||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_toplevel_v6_parent_class);
|
||||||
surface_role_class->apply_state (surface_role, pending);
|
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);
|
meta_wayland_window_configuration_free (configuration);
|
||||||
return;
|
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)
|
if (!pending->newly_attached)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* If the window disappeared the surface is not coming back. */
|
old_geometry = xdg_surface_priv->geometry;
|
||||||
if (!window)
|
|
||||||
return;
|
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);
|
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,
|
wl_resource_post_error (surface->resource,
|
||||||
ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
|
ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
|
||||||
"Invalid min/max size");
|
"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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_zxdg_toplevel_v6_apply_state;
|
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;
|
surface_role_class->get_toplevel = meta_wayland_zxdg_toplevel_v6_get_toplevel;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
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)
|
MetaWaylandSurfaceState *pending)
|
||||||
{
|
{
|
||||||
MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role);
|
MetaWaylandZxdgPopupV6 *xdg_popup = META_WAYLAND_ZXDG_POPUP_V6 (surface_role);
|
||||||
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
|
||||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
|
||||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||||
MetaWaylandSurface *surface =
|
|
||||||
meta_wayland_surface_role_get_surface (surface_role);
|
|
||||||
MetaWindow *window;
|
|
||||||
|
|
||||||
if (xdg_popup->setup.parent_surface)
|
if (xdg_popup->setup.parent_surface)
|
||||||
finish_popup_setup (xdg_popup);
|
finish_popup_setup (xdg_popup);
|
||||||
@ -977,12 +993,27 @@ meta_wayland_zxdg_popup_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
surface_role_class =
|
surface_role_class =
|
||||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class);
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_zxdg_popup_v6_parent_class);
|
||||||
surface_role_class->apply_state (surface_role, pending);
|
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);
|
window = meta_wayland_surface_get_window (surface);
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
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)
|
if (!pending->newly_attached)
|
||||||
return;
|
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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_zxdg_popup_v6_apply_state;
|
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;
|
surface_role_class->get_toplevel = meta_wayland_zxdg_popup_v6_get_toplevel;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
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 =
|
MetaWaylandZxdgSurfaceV6 *xdg_surface =
|
||||||
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
META_WAYLAND_ZXDG_SURFACE_V6 (surface_role);
|
||||||
MetaWaylandShellSurface *shell_surface =
|
|
||||||
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
|
||||||
MetaWaylandZxdgSurfaceV6Private *priv =
|
MetaWaylandZxdgSurfaceV6Private *priv =
|
||||||
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
|
meta_wayland_zxdg_surface_v6_get_instance_private (xdg_surface);
|
||||||
MetaWaylandSurface *surface =
|
MetaWaylandSurface *surface =
|
||||||
@ -1370,8 +1401,18 @@ meta_wayland_zxdg_surface_v6_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
|
|
||||||
if (surface->buffer_ref.buffer)
|
if (surface->buffer_ref.buffer)
|
||||||
priv->first_buffer_attached = TRUE;
|
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)
|
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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_zxdg_surface_v6_apply_state;
|
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;
|
surface_role_class->assigned = meta_wayland_zxdg_surface_v6_assigned;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "wayland/meta-wayland-seat.h"
|
#include "wayland/meta-wayland-seat.h"
|
||||||
|
|
||||||
#include "wayland/meta-wayland-data-device.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-private.h"
|
||||||
#include "wayland/meta-wayland-tablet-seat.h"
|
#include "wayland/meta-wayland-tablet-seat.h"
|
||||||
#include "wayland/meta-wayland-versions.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);
|
seat->gtk_text_input = meta_wayland_gtk_text_input_new (seat);
|
||||||
|
|
||||||
meta_wayland_data_device_init (&seat->data_device);
|
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 ());
|
clutter_seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
|
||||||
meta_wayland_seat_update_capabilities (seat, clutter_seat);
|
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_keyboard_set_focus (seat->keyboard, surface);
|
||||||
meta_wayland_data_device_set_keyboard_focus (&seat->data_device);
|
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);
|
tablet_seat = meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
#include "wayland/meta-wayland-data-device.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-input-device.h"
|
||||||
#include "wayland/meta-wayland-keyboard.h"
|
#include "wayland/meta-wayland-keyboard.h"
|
||||||
#include "wayland/meta-wayland-pointer.h"
|
#include "wayland/meta-wayland-pointer.h"
|
||||||
@ -45,6 +47,8 @@ struct _MetaWaylandSeat
|
|||||||
MetaWaylandTouch *touch;
|
MetaWaylandTouch *touch;
|
||||||
|
|
||||||
MetaWaylandDataDevice data_device;
|
MetaWaylandDataDevice data_device;
|
||||||
|
MetaWaylandDataDevicePrimary primary_data_device;
|
||||||
|
MetaWaylandDataDevicePrimaryLegacy primary_legacy_data_device;
|
||||||
|
|
||||||
MetaWaylandGtkTextInput *gtk_text_input;
|
MetaWaylandGtkTextInput *gtk_text_input;
|
||||||
MetaWaylandTextInput *text_input;
|
MetaWaylandTextInput *text_input;
|
||||||
|
@ -113,6 +113,10 @@ static void
|
|||||||
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||||
MetaWaylandSurfaceState *pending);
|
MetaWaylandSurfaceState *pending);
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_surface_role_post_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||||
|
MetaWaylandSurfaceState *pending);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role,
|
meta_wayland_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *surface_role,
|
||||||
MetaLogicalMonitor *logical_monitor);
|
MetaLogicalMonitor *logical_monitor);
|
||||||
@ -757,8 +761,6 @@ cleanup:
|
|||||||
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED],
|
surface_state_signals[SURFACE_STATE_SIGNAL_APPLIED],
|
||||||
0);
|
0);
|
||||||
|
|
||||||
meta_wayland_surface_state_reset (state);
|
|
||||||
|
|
||||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||||
{
|
{
|
||||||
MetaWaylandSubsurface *subsurface;
|
MetaWaylandSubsurface *subsurface;
|
||||||
@ -782,6 +784,11 @@ cleanup:
|
|||||||
meta_window_actor_notify_damaged (toplevel_window_actor);
|
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
|
void
|
||||||
@ -1696,6 +1703,17 @@ meta_wayland_surface_role_pre_apply_state (MetaWaylandSurfaceRole *surface_role
|
|||||||
klass->pre_apply_state (surface_role, pending);
|
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
|
static void
|
||||||
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
meta_wayland_surface_role_apply_state (MetaWaylandSurfaceRole *surface_role,
|
||||||
MetaWaylandSurfaceState *pending)
|
MetaWaylandSurfaceState *pending)
|
||||||
|
@ -58,6 +58,8 @@ struct _MetaWaylandSurfaceRoleClass
|
|||||||
MetaWaylandSurfaceState *pending);
|
MetaWaylandSurfaceState *pending);
|
||||||
void (*apply_state) (MetaWaylandSurfaceRole *surface_role,
|
void (*apply_state) (MetaWaylandSurfaceRole *surface_role,
|
||||||
MetaWaylandSurfaceState *pending);
|
MetaWaylandSurfaceState *pending);
|
||||||
|
void (*post_apply_state) (MetaWaylandSurfaceRole *surface_role,
|
||||||
|
MetaWaylandSurfaceState *pending);
|
||||||
gboolean (*is_on_logical_monitor) (MetaWaylandSurfaceRole *surface_role,
|
gboolean (*is_on_logical_monitor) (MetaWaylandSurfaceRole *surface_role,
|
||||||
MetaLogicalMonitor *logical_monitor);
|
MetaLogicalMonitor *logical_monitor);
|
||||||
MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role);
|
MetaWaylandSurface * (*get_toplevel) (MetaWaylandSurfaceRole *surface_role);
|
||||||
|
@ -37,6 +37,8 @@ typedef struct _MetaWaylandTouch MetaWaylandTouch;
|
|||||||
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
typedef struct _MetaWaylandDragDestFuncs MetaWaylandDragDestFuncs;
|
||||||
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
|
||||||
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
typedef struct _MetaWaylandDataDevice MetaWaylandDataDevice;
|
||||||
|
typedef struct _MetaWaylandDataDevicePrimary MetaWaylandDataDevicePrimary;
|
||||||
|
typedef struct _MetaWaylandDataDevicePrimaryLegacy MetaWaylandDataDevicePrimaryLegacy;
|
||||||
|
|
||||||
typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
|
typedef struct _MetaWaylandTabletManager MetaWaylandTabletManager;
|
||||||
typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat;
|
typedef struct _MetaWaylandTabletSeat MetaWaylandTabletSeat;
|
||||||
|
@ -744,8 +744,6 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
MetaWaylandSurface *surface =
|
MetaWaylandSurface *surface =
|
||||||
meta_wayland_surface_role_get_surface (surface_role);
|
meta_wayland_surface_role_get_surface (surface_role);
|
||||||
MetaWindow *window;
|
MetaWindow *window;
|
||||||
MetaRectangle old_geometry;
|
|
||||||
gboolean geometry_changed;
|
|
||||||
|
|
||||||
window = meta_wayland_surface_get_window (surface);
|
window = meta_wayland_surface_get_window (surface);
|
||||||
if (!window)
|
if (!window)
|
||||||
@ -765,8 +763,6 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_geometry = xdg_surface_priv->geometry;
|
|
||||||
|
|
||||||
surface_role_class =
|
surface_role_class =
|
||||||
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_xdg_toplevel_parent_class);
|
||||||
surface_role_class->apply_state (surface_role, pending);
|
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);
|
meta_wayland_window_configuration_free (configuration);
|
||||||
return;
|
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)
|
if (!pending->newly_attached)
|
||||||
return;
|
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)
|
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);
|
meta_window_wayland_finish_move_resize (window, window_geometry, pending);
|
||||||
}
|
}
|
||||||
else if (pending->dx != 0 || pending->dy != 0)
|
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,
|
wl_resource_post_error (surface->resource,
|
||||||
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
XDG_WM_BASE_ERROR_INVALID_SURFACE_STATE,
|
||||||
"Invalid min/max size");
|
"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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_xdg_toplevel_apply_state;
|
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;
|
surface_role_class->get_toplevel = meta_wayland_xdg_toplevel_get_toplevel;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
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;
|
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||||
MetaWaylandSurface *surface =
|
MetaWaylandSurface *surface =
|
||||||
meta_wayland_surface_role_get_surface (surface_role);
|
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)
|
if (xdg_popup->setup.parent_surface)
|
||||||
finish_popup_setup (xdg_popup);
|
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");
|
"Can't commit buffer to dismissed popup");
|
||||||
return;
|
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);
|
window = meta_wayland_surface_get_window (surface);
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
@ -1130,6 +1162,8 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
if (!surface->buffer_ref.buffer)
|
if (!surface->buffer_ref.buffer)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
surface_role_class->post_apply_state (surface_role, pending);
|
||||||
|
|
||||||
if (pending->has_acked_configure_serial)
|
if (pending->has_acked_configure_serial)
|
||||||
{
|
{
|
||||||
MetaRectangle window_geometry;
|
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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_xdg_popup_apply_state;
|
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;
|
surface_role_class->get_toplevel = meta_wayland_xdg_popup_get_toplevel;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||||
@ -1504,8 +1539,6 @@ meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
MetaWaylandSurfaceState *pending)
|
MetaWaylandSurfaceState *pending)
|
||||||
{
|
{
|
||||||
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
|
||||||
MetaWaylandShellSurface *shell_surface =
|
|
||||||
META_WAYLAND_SHELL_SURFACE (xdg_surface);
|
|
||||||
MetaWaylandXdgSurfacePrivate *priv =
|
MetaWaylandXdgSurfacePrivate *priv =
|
||||||
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
meta_wayland_xdg_surface_get_instance_private (xdg_surface);
|
||||||
MetaWaylandSurface *surface =
|
MetaWaylandSurface *surface =
|
||||||
@ -1526,8 +1559,17 @@ meta_wayland_xdg_surface_apply_state (MetaWaylandSurfaceRole *surface_role,
|
|||||||
|
|
||||||
if (surface->buffer_ref.buffer)
|
if (surface->buffer_ref.buffer)
|
||||||
priv->first_buffer_attached = TRUE;
|
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)
|
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 = META_WAYLAND_SURFACE_ROLE_CLASS (klass);
|
||||||
surface_role_class->apply_state = meta_wayland_xdg_surface_apply_state;
|
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;
|
surface_role_class->assigned = meta_wayland_xdg_surface_assigned;
|
||||||
|
|
||||||
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
shell_surface_class = META_WAYLAND_SHELL_SURFACE_CLASS (klass);
|
||||||
|
@ -395,6 +395,8 @@ meta_wayland_init (void)
|
|||||||
|
|
||||||
meta_wayland_outputs_init (compositor);
|
meta_wayland_outputs_init (compositor);
|
||||||
meta_wayland_data_device_manager_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_subsurfaces_init (compositor);
|
||||||
meta_wayland_shell_init (compositor);
|
meta_wayland_shell_init (compositor);
|
||||||
meta_wayland_pointer_gestures_init (compositor);
|
meta_wayland_pointer_gestures_init (compositor);
|
||||||
|
@ -145,6 +145,8 @@ xdnd_send_enter (MetaXWaylandDnd *dnd,
|
|||||||
gchar **p;
|
gchar **p;
|
||||||
struct wl_array *source_mime_types;
|
struct wl_array *source_mime_types;
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
|
|
||||||
data_source = compositor->seat->data_device.dnd_data_source;
|
data_source = compositor->seat->data_device.dnd_data_source;
|
||||||
xev.xclient.type = ClientMessage;
|
xev.xclient.type = ClientMessage;
|
||||||
xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER];
|
xev.xclient.message_type = xdnd_atoms[ATOM_DND_ENTER];
|
||||||
@ -189,6 +191,9 @@ xdnd_send_enter (MetaXWaylandDnd *dnd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
|
||||||
|
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||||
|
g_critical ("Error sending XdndEnter");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -205,7 +210,9 @@ xdnd_send_leave (MetaXWaylandDnd *dnd,
|
|||||||
xev.xclient.window = dest;
|
xev.xclient.window = dest;
|
||||||
xev.xclient.data.l[0] = x11_display->selection.xwindow;
|
xev.xclient.data.l[0] = x11_display->selection.xwindow;
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
meta_x11_error_trap_pop (x11_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -223,7 +230,7 @@ xdnd_send_position (MetaXWaylandDnd *dnd,
|
|||||||
XEvent xev = { 0 };
|
XEvent xev = { 0 };
|
||||||
|
|
||||||
user_action = meta_wayland_data_source_get_user_action (source);
|
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)
|
if (user_action & actions)
|
||||||
action = user_action;
|
action = user_action;
|
||||||
@ -241,7 +248,11 @@ xdnd_send_position (MetaXWaylandDnd *dnd,
|
|||||||
xev.xclient.data.l[3] = time;
|
xev.xclient.data.l[3] = time;
|
||||||
xev.xclient.data.l[4] = action_to_atom (action);
|
xev.xclient.data.l[4] = action_to_atom (action);
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
|
||||||
|
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||||
|
g_critical ("Error sending XdndPosition");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -261,7 +272,11 @@ xdnd_send_drop (MetaXWaylandDnd *dnd,
|
|||||||
xev.xclient.data.l[0] = x11_display->selection.xwindow;
|
xev.xclient.data.l[0] = x11_display->selection.xwindow;
|
||||||
xev.xclient.data.l[2] = time;
|
xev.xclient.data.l[2] = time;
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
|
||||||
|
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||||
|
g_critical ("Error sending XdndDrop");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -289,7 +304,11 @@ xdnd_send_finished (MetaXWaylandDnd *dnd,
|
|||||||
xev.xclient.data.l[2] = action_to_atom (action);
|
xev.xclient.data.l[2] = action_to_atom (action);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
|
||||||
|
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||||
|
g_critical ("Error sending XdndFinished");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -297,6 +316,7 @@ xdnd_send_status (MetaXWaylandDnd *dnd,
|
|||||||
Window dest,
|
Window dest,
|
||||||
uint32_t action)
|
uint32_t action)
|
||||||
{
|
{
|
||||||
|
MetaX11Display *x11_display = meta_get_display ()->x11_display;
|
||||||
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
||||||
XEvent xev = { 0 };
|
XEvent xev = { 0 };
|
||||||
|
|
||||||
@ -312,7 +332,11 @@ xdnd_send_status (MetaXWaylandDnd *dnd,
|
|||||||
if (xev.xclient.data.l[4])
|
if (xev.xclient.data.l[4])
|
||||||
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
|
xev.xclient.data.l[1] |= 1 << 0; /* Bit 1: dest accepts the drop */
|
||||||
|
|
||||||
|
meta_x11_error_trap_push (x11_display);
|
||||||
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
XSendEvent (xdisplay, dest, False, NoEventMask, &xev);
|
||||||
|
|
||||||
|
if (meta_x11_error_trap_pop_with_return (x11_display) != Success)
|
||||||
|
g_critical ("Error sending Xdndstatus");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -343,6 +367,7 @@ transfer_cb (MetaSelection *selection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_output_stream_close (stream, NULL, NULL);
|
g_output_stream_close (stream, NULL, NULL);
|
||||||
|
g_object_unref (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -60,6 +60,8 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream,
|
|||||||
meta_x11_selection_output_stream,
|
meta_x11_selection_output_stream,
|
||||||
G_TYPE_OUTPUT_STREAM);
|
G_TYPE_OUTPUT_STREAM);
|
||||||
|
|
||||||
|
static size_t get_element_size (int format);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream)
|
meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream)
|
||||||
{
|
{
|
||||||
@ -97,6 +99,9 @@ meta_x11_selection_output_stream_can_flush (MetaX11SelectionOutputStream *stream
|
|||||||
|
|
||||||
if (priv->delete_pending)
|
if (priv->delete_pending)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) &&
|
||||||
|
priv->data->len < get_element_size (priv->format))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -110,7 +115,7 @@ get_max_request_size (MetaX11Display *display)
|
|||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
size = XMaxRequestSize (display->xdisplay);
|
size = XMaxRequestSize (display->xdisplay);
|
||||||
|
|
||||||
return size - 100;
|
return (size - 100) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -120,7 +125,12 @@ meta_x11_selection_output_stream_needs_flush_unlocked (MetaX11SelectionOutputStr
|
|||||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||||
|
|
||||||
if (priv->data->len == 0)
|
if (priv->data->len == 0)
|
||||||
return FALSE;
|
{
|
||||||
|
if (priv->incr)
|
||||||
|
return g_output_stream_is_closing (G_OUTPUT_STREAM (stream));
|
||||||
|
else
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -193,7 +203,8 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|||||||
MetaX11SelectionOutputStreamPrivate *priv =
|
MetaX11SelectionOutputStreamPrivate *priv =
|
||||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
size_t element_size, n_elements;
|
size_t element_size, n_elements, max_size;
|
||||||
|
gboolean first_chunk = FALSE;
|
||||||
int error_code;
|
int error_code;
|
||||||
|
|
||||||
g_assert (!priv->delete_pending);
|
g_assert (!priv->delete_pending);
|
||||||
@ -207,8 +218,12 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|||||||
|
|
||||||
element_size = get_element_size (priv->format);
|
element_size = get_element_size (priv->format);
|
||||||
n_elements = priv->data->len / element_size;
|
n_elements = priv->data->len / element_size;
|
||||||
|
max_size = get_max_request_size (priv->x11_display);
|
||||||
|
|
||||||
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
if (!priv->incr)
|
||||||
|
first_chunk = TRUE;
|
||||||
|
|
||||||
|
if (!priv->incr && priv->data->len > max_size)
|
||||||
{
|
{
|
||||||
XWindowAttributes attrs;
|
XWindowAttributes attrs;
|
||||||
|
|
||||||
@ -224,14 +239,22 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|||||||
XChangeProperty (xdisplay,
|
XChangeProperty (xdisplay,
|
||||||
priv->xwindow,
|
priv->xwindow,
|
||||||
priv->xproperty,
|
priv->xproperty,
|
||||||
XInternAtom (priv->x11_display->xdisplay, "INCR", True),
|
XInternAtom (priv->x11_display->xdisplay, "INCR", False),
|
||||||
32,
|
32,
|
||||||
PropModeReplace,
|
PropModeReplace,
|
||||||
(guchar *) &(long) { n_elements },
|
(guchar *) &(long) { n_elements },
|
||||||
1);
|
1);
|
||||||
|
priv->delete_pending = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
size_t copy_n_elements;
|
||||||
|
|
||||||
|
if (priv->incr && priv->data->len > 0)
|
||||||
|
priv->delete_pending = TRUE;
|
||||||
|
|
||||||
|
copy_n_elements = MIN (n_elements, max_size / element_size);
|
||||||
|
|
||||||
XChangeProperty (xdisplay,
|
XChangeProperty (xdisplay,
|
||||||
priv->xwindow,
|
priv->xwindow,
|
||||||
priv->xproperty,
|
priv->xproperty,
|
||||||
@ -239,15 +262,13 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|||||||
priv->format,
|
priv->format,
|
||||||
PropModeReplace,
|
PropModeReplace,
|
||||||
priv->data->data,
|
priv->data->data,
|
||||||
n_elements);
|
copy_n_elements);
|
||||||
g_byte_array_remove_range (priv->data, 0, n_elements * element_size);
|
g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size);
|
||||||
if (priv->data->len < element_size)
|
|
||||||
priv->flush_requested = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_x11_selection_output_stream_notify_selection (stream);
|
if (first_chunk)
|
||||||
|
meta_x11_selection_output_stream_notify_selection (stream);
|
||||||
|
|
||||||
priv->delete_pending = TRUE;
|
|
||||||
g_cond_broadcast (&priv->cond);
|
g_cond_broadcast (&priv->cond);
|
||||||
g_mutex_unlock (&priv->mutex);
|
g_mutex_unlock (&priv->mutex);
|
||||||
|
|
||||||
@ -257,19 +278,26 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
|||||||
{
|
{
|
||||||
char error_str[100];
|
char error_str[100];
|
||||||
|
|
||||||
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
|
priv->flush_requested = FALSE;
|
||||||
g_task_return_new_error (priv->pending_task,
|
priv->delete_pending = FALSE;
|
||||||
G_IO_ERROR,
|
|
||||||
G_IO_ERROR_BROKEN_PIPE,
|
|
||||||
"Failed to flush selection output stream: %s",
|
|
||||||
error_str);
|
|
||||||
g_clear_object (&priv->pending_task);
|
|
||||||
priv->pipe_error = TRUE;
|
priv->pipe_error = TRUE;
|
||||||
|
|
||||||
|
if (priv->pending_task)
|
||||||
|
{
|
||||||
|
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
|
||||||
|
g_task_return_new_error (priv->pending_task,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_BROKEN_PIPE,
|
||||||
|
"Failed to flush selection output stream: %s",
|
||||||
|
error_str);
|
||||||
|
g_clear_object (&priv->pending_task);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (priv->pending_task)
|
else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending)
|
||||||
{
|
{
|
||||||
size_t result;
|
size_t result;
|
||||||
|
|
||||||
|
priv->flush_requested = FALSE;
|
||||||
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
|
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
|
||||||
g_task_return_int (priv->pending_task, result);
|
g_task_return_int (priv->pending_task, result);
|
||||||
g_clear_object (&priv->pending_task);
|
g_clear_object (&priv->pending_task);
|
||||||
@ -281,12 +309,17 @@ meta_x11_selection_output_stream_invoke_flush (gpointer data)
|
|||||||
{
|
{
|
||||||
MetaX11SelectionOutputStream *stream =
|
MetaX11SelectionOutputStream *stream =
|
||||||
META_X11_SELECTION_OUTPUT_STREAM (data);
|
META_X11_SELECTION_OUTPUT_STREAM (data);
|
||||||
|
MetaX11SelectionOutputStreamPrivate *priv =
|
||||||
|
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||||
|
|
||||||
if (meta_x11_selection_output_stream_needs_flush (stream) &&
|
if (meta_x11_selection_output_stream_needs_flush (stream) &&
|
||||||
meta_x11_selection_output_stream_can_flush (stream))
|
meta_x11_selection_output_stream_can_flush (stream))
|
||||||
meta_x11_selection_output_stream_perform_flush (stream);
|
meta_x11_selection_output_stream_perform_flush (stream);
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
if (priv->delete_pending || priv->data->len > 0)
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
else
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gssize
|
static gssize
|
||||||
@ -354,16 +387,11 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
|||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!meta_x11_selection_output_stream_can_flush (stream))
|
|
||||||
{
|
|
||||||
g_assert (priv->pending_task == NULL);
|
|
||||||
priv->pending_task = task;
|
|
||||||
g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
meta_x11_selection_output_stream_perform_flush (stream);
|
if (meta_x11_selection_output_stream_can_flush (stream))
|
||||||
|
meta_x11_selection_output_stream_perform_flush (stream);
|
||||||
|
|
||||||
g_task_return_int (task, count);
|
g_task_return_int (task, count);
|
||||||
g_object_unref (task);
|
g_object_unref (task);
|
||||||
return;
|
return;
|
||||||
@ -391,7 +419,7 @@ meta_x11_selection_output_request_flush (MetaX11SelectionOutputStream *stream)
|
|||||||
|
|
||||||
g_mutex_lock (&priv->mutex);
|
g_mutex_lock (&priv->mutex);
|
||||||
|
|
||||||
if (priv->data->len >= get_element_size (priv->format))
|
if (priv->data->len > 0)
|
||||||
priv->flush_requested = TRUE;
|
priv->flush_requested = TRUE;
|
||||||
|
|
||||||
needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream);
|
needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream);
|
||||||
@ -466,10 +494,9 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_assert (priv->pending_task == NULL);
|
||||||
|
priv->pending_task = task;
|
||||||
meta_x11_selection_output_stream_perform_flush (stream);
|
meta_x11_selection_output_stream_perform_flush (stream);
|
||||||
g_task_return_boolean (task, TRUE);
|
|
||||||
g_object_unref (task);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
|
|
||||||
|
#include "core/meta-selection-private.h"
|
||||||
|
#include "meta/meta-selection-source-memory.h"
|
||||||
#include "x11/meta-selection-source-x11-private.h"
|
#include "x11/meta-selection-source-x11-private.h"
|
||||||
#include "x11/meta-x11-selection-output-stream-private.h"
|
#include "x11/meta-x11-selection-output-stream-private.h"
|
||||||
#include "x11/meta-x11-selection-private.h"
|
#include "x11/meta-x11-selection-private.h"
|
||||||
@ -296,8 +298,8 @@ source_new_cb (GObject *object,
|
|||||||
source = meta_selection_source_x11_new_finish (res, &error);
|
source = meta_selection_source_x11_new_finish (res, &error);
|
||||||
if (source)
|
if (source)
|
||||||
{
|
{
|
||||||
meta_selection_set_owner (selection, selection_type, source);
|
|
||||||
g_set_object (&x11_display->selection.owners[selection_type], source);
|
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||||
|
meta_selection_set_owner (selection, selection_type, source);
|
||||||
g_object_unref (source);
|
g_object_unref (source);
|
||||||
}
|
}
|
||||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||||
@ -331,16 +333,27 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
|
|||||||
|
|
||||||
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
|
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
|
||||||
|
|
||||||
if (event->owner == None)
|
if (event->owner == None && x11_display->selection.owners[selection_type])
|
||||||
{
|
{
|
||||||
if (x11_display->selection.owners[selection_type])
|
if (event->subtype == XFixesSetSelectionOwnerNotify)
|
||||||
|
{
|
||||||
|
MetaSelectionSource *source;
|
||||||
|
|
||||||
|
/* Replace with an empty owner */
|
||||||
|
source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
|
||||||
|
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||||
|
meta_selection_set_owner (selection, selection_type, source);
|
||||||
|
g_object_unref (source);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
/* An X client went away, clear the selection */
|
/* An X client went away, clear the selection */
|
||||||
meta_selection_unset_owner (selection, selection_type,
|
meta_selection_unset_owner (selection, selection_type,
|
||||||
x11_display->selection.owners[selection_type]);
|
x11_display->selection.owners[selection_type]);
|
||||||
|
g_clear_object (&x11_display->selection.owners[selection_type]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event->owner != x11_display->selection.xwindow)
|
else if (event->owner != None && event->owner != x11_display->selection.xwindow)
|
||||||
{
|
{
|
||||||
SourceNewData *data;
|
SourceNewData *data;
|
||||||
|
|
||||||
@ -374,14 +387,13 @@ meta_x11_selection_handle_event (MetaX11Display *x11_display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
owner_changed_cb (MetaSelection *selection,
|
notify_selection_owner (MetaX11Display *x11_display,
|
||||||
MetaSelectionType selection_type,
|
MetaSelectionType selection_type,
|
||||||
MetaSelectionSource *new_owner,
|
MetaSelectionSource *new_owner)
|
||||||
MetaX11Display *x11_display)
|
|
||||||
{
|
{
|
||||||
Display *xdisplay = x11_display->xdisplay;
|
Display *xdisplay = x11_display->xdisplay;
|
||||||
|
|
||||||
if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner))
|
if (new_owner && new_owner != x11_display->selection.owners[selection_type])
|
||||||
{
|
{
|
||||||
if (x11_display->selection.cancellables[selection_type])
|
if (x11_display->selection.cancellables[selection_type])
|
||||||
{
|
{
|
||||||
@ -404,6 +416,7 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
|||||||
{
|
{
|
||||||
XSetWindowAttributes attributes = { 0 };
|
XSetWindowAttributes attributes = { 0 };
|
||||||
MetaDisplay *display = meta_get_display ();
|
MetaDisplay *display = meta_get_display ();
|
||||||
|
MetaSelection *selection;
|
||||||
guint mask, i;
|
guint mask, i;
|
||||||
|
|
||||||
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
|
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
|
||||||
@ -424,18 +437,24 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
|||||||
XFixesSelectionWindowDestroyNotifyMask |
|
XFixesSelectionWindowDestroyNotifyMask |
|
||||||
XFixesSelectionClientCloseNotifyMask;
|
XFixesSelectionClientCloseNotifyMask;
|
||||||
|
|
||||||
|
selection = meta_display_get_selection (display);
|
||||||
|
|
||||||
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
||||||
{
|
{
|
||||||
|
MetaSelectionSource *owner;
|
||||||
|
|
||||||
XFixesSelectSelectionInput (x11_display->xdisplay,
|
XFixesSelectSelectionInput (x11_display->xdisplay,
|
||||||
x11_display->selection.xwindow,
|
x11_display->selection.xwindow,
|
||||||
selection_to_atom (i, x11_display->xdisplay),
|
selection_to_atom (i, x11_display->xdisplay),
|
||||||
mask);
|
mask);
|
||||||
|
owner = meta_selection_get_current_owner (selection, i);
|
||||||
|
notify_selection_owner (x11_display, i, owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_signal_connect (meta_display_get_selection (display),
|
g_signal_connect_swapped (selection,
|
||||||
"owner-changed",
|
"owner-changed",
|
||||||
G_CALLBACK (owner_changed_cb),
|
G_CALLBACK (notify_selection_owner),
|
||||||
x11_display);
|
x11_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -445,7 +464,7 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display)
|
|||||||
guint i;
|
guint i;
|
||||||
|
|
||||||
g_signal_handlers_disconnect_by_func (meta_display_get_selection (display),
|
g_signal_handlers_disconnect_by_func (meta_display_get_selection (display),
|
||||||
owner_changed_cb,
|
notify_selection_owner,
|
||||||
x11_display);
|
x11_display);
|
||||||
|
|
||||||
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user