Compare commits
147 Commits
citadel
...
wip/textur
Author | SHA1 | Date | |
---|---|---|---|
![]() |
625ea86672 | ||
![]() |
395d463c08 | ||
![]() |
2fc0652886 | ||
![]() |
6ff42c2ab2 | ||
![]() |
f9907d1978 | ||
![]() |
45c5f557bd | ||
![]() |
53d63ea72b | ||
![]() |
f6e8e867b4 | ||
![]() |
a566c6677c | ||
![]() |
cb06e1ef33 | ||
![]() |
a30c8fb83d | ||
![]() |
e3a42dc873 | ||
![]() |
efd7b8987f | ||
![]() |
c96aacabf7 | ||
![]() |
af61b66953 | ||
![]() |
baf11d2471 | ||
![]() |
01c763470e | ||
![]() |
c9065da442 | ||
![]() |
5f8a4f560f | ||
![]() |
47577432e4 | ||
![]() |
4ee9462fcd | ||
![]() |
c275c1de52 | ||
![]() |
a9965bb57a | ||
![]() |
9cc2fa2526 | ||
![]() |
f439b0432d | ||
![]() |
ab39558506 | ||
![]() |
9d72eeeb58 | ||
![]() |
eea0a2b11d | ||
![]() |
bcacaf4562 | ||
![]() |
5ae7a67b36 | ||
![]() |
7d8ff61069 | ||
![]() |
79b3f56bd3 | ||
![]() |
e371bacd7f | ||
![]() |
62fd182272 | ||
![]() |
f48c8c5824 | ||
![]() |
e3d7b3828e | ||
![]() |
6e14403ac8 | ||
![]() |
ec2471a356 | ||
![]() |
30820ab19e | ||
![]() |
58cc091134 | ||
![]() |
0105dca586 | ||
![]() |
17dd4d32da | ||
![]() |
5b95f809ca | ||
![]() |
3934793255 | ||
![]() |
f3655737bc | ||
![]() |
728ed4fe38 | ||
![]() |
bcba6571f0 | ||
![]() |
4525a74e59 | ||
![]() |
0dd58540b2 | ||
![]() |
ac27fca3ef | ||
![]() |
99bbe001f5 | ||
![]() |
30c09c84c4 | ||
![]() |
81c63df853 | ||
![]() |
3104abba57 | ||
![]() |
13eb4f51c7 | ||
![]() |
7969c473ac | ||
![]() |
a83e72d7c1 | ||
![]() |
910c4e9fe7 | ||
![]() |
2fb5b65e94 | ||
![]() |
e00d6c6273 | ||
![]() |
733ab3b2bc | ||
![]() |
a208d7c33e | ||
![]() |
37bbea649b | ||
![]() |
4035955fc0 | ||
![]() |
a8db59908f | ||
![]() |
a477c73a97 | ||
![]() |
ae228c0556 | ||
![]() |
978cb5b21c | ||
![]() |
e792eca2f5 | ||
![]() |
b9614f0797 | ||
![]() |
6d7bbeddd7 | ||
![]() |
68570353fd | ||
![]() |
566cdcc94b | ||
![]() |
37dc2e5b1b | ||
![]() |
66b9150771 | ||
![]() |
34f5bdeea3 | ||
![]() |
ca71b0eb1a | ||
![]() |
ca4209d88a | ||
![]() |
3288edf677 | ||
![]() |
fe1616668e | ||
![]() |
7d01aec48d | ||
![]() |
a41d84db00 | ||
![]() |
e73b321c2e | ||
![]() |
b6dc2052c3 | ||
![]() |
72965aaaf0 | ||
![]() |
2a6782dc10 | ||
![]() |
5142c8c7e7 | ||
![]() |
abc7ad8e9f | ||
![]() |
1a3f9a3323 | ||
![]() |
235c35182b | ||
![]() |
e4661d7870 | ||
![]() |
9d4c7e4e75 | ||
![]() |
47131b1dad | ||
![]() |
51c0130645 | ||
![]() |
2dd9fc17c1 | ||
![]() |
c7a38c3139 | ||
![]() |
7d52be0229 | ||
![]() |
41303bc01b | ||
![]() |
0d188c3898 | ||
![]() |
28eff93143 | ||
![]() |
b380aa72aa | ||
![]() |
920dc9e5a1 | ||
![]() |
32f02010ae | ||
![]() |
889c56c776 | ||
![]() |
67a4cd898e | ||
![]() |
43d6c0ea61 | ||
![]() |
2872bb1f2a | ||
![]() |
1c00cd5ca3 | ||
![]() |
2919a7f25f | ||
![]() |
ca0d56a3a4 | ||
![]() |
a89baa44ab | ||
![]() |
7076a48bcf | ||
![]() |
1b439c42d1 | ||
![]() |
928a40f328 | ||
![]() |
59397266ed | ||
![]() |
d0147591b3 | ||
![]() |
25c7e52ada | ||
![]() |
99d766c044 | ||
![]() |
fcd4c816c4 | ||
![]() |
2a63a47d5a | ||
![]() |
c80e2c9ae5 | ||
![]() |
d3d5eb8e1b | ||
![]() |
4837cec89f | ||
![]() |
32329e6c00 | ||
![]() |
89261be556 | ||
![]() |
e3e76d658b | ||
![]() |
34644b2133 | ||
![]() |
7da4e8cf14 | ||
![]() |
23c3f8bb18 | ||
![]() |
60866e0f85 | ||
![]() |
45c02645f3 | ||
![]() |
e515e37a7e | ||
![]() |
957f4ec69d | ||
![]() |
a98eb107be | ||
![]() |
1851fa2bd0 | ||
![]() |
de7d7bbf3d | ||
![]() |
7ac551cd05 | ||
![]() |
8696a79477 | ||
![]() |
b2f9de98d0 | ||
![]() |
2da2489da5 | ||
![]() |
31779404f0 | ||
![]() |
b096c0ac33 | ||
![]() |
44a7f74dcd | ||
![]() |
3832c6b607 | ||
![]() |
14b7e79d3c | ||
![]() |
e99b0b9368 | ||
![]() |
de294f34bb |
45
NEWS
45
NEWS
@ -1,3 +1,48 @@
|
|||||||
|
3.28.3
|
||||||
|
======
|
||||||
|
* Handle touch events on server-side titlebars [Carlos; #770185]
|
||||||
|
* Fix crash with unhandled mouse buttons on titlebars [Olivier; #160]
|
||||||
|
* Fix Korean Hangul support on wayland [Changwoo; #152]
|
||||||
|
* Fix crash when taking up from suspend [Jonas; #786929]
|
||||||
|
* Fix crash with parent-less modal dialogs [Olivier; #174]
|
||||||
|
* Misc. bug fixes [Olivier, Georges; #83, #112, #150, #104,
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Georges Basile Stavracas Neto,
|
||||||
|
Changwoo Ryu, Marco Trevisan (Treviño)
|
||||||
|
|
||||||
|
3.28.2
|
||||||
|
======
|
||||||
|
* Take inhibitors into account for monitoring idle [Bastien; #705942]
|
||||||
|
* Fix window animations on wayland [Georges; #780292]
|
||||||
|
* Misc. bug fixes [Mario, Jonas, Olivier, Florian; gnome-shell#157, #130,
|
||||||
|
#21, #124, !96, #138, !102, #781471]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, Florian Müllner,
|
||||||
|
Georges Basile Stavracas Neto, Bastien Nocera, Mario Sanchez Prada,
|
||||||
|
Ray Strode, Marco Trevisan (Treviño)
|
||||||
|
|
||||||
|
3.28.1
|
||||||
|
======
|
||||||
|
* Fix various input-method regressions [Carlos; #65, #74, #66]
|
||||||
|
* Fix wayland build on FreeBSD [Ting-Wei; #792280, #792717]
|
||||||
|
* Fix swapped colors in screenshots (again) [Carlos; #72]
|
||||||
|
* Allow building with elogind [Rasmus; !46]
|
||||||
|
* Consider display rotation for cursor [Olivier; #85]
|
||||||
|
* Fall back to non-modifier GBM surfaces [Daniel; #84]
|
||||||
|
* Disable KMS modifiers by default [Jonas; #81]
|
||||||
|
* Misc bug fixes [handsome-feng; !45]
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Jonas Ådahl, Olivier Fourdan, Carlos Garnacho, handsome-feng, Yussuf Khalil,
|
||||||
|
Ting-Wei Lan, Aleksandr Mezin, Alberts Muktupāvels,
|
||||||
|
Georges Basile Stavracas Neto, Benjamin Otte, Daniel Stone, Rasmus Thomsen,
|
||||||
|
Marco Trevisan (Treviño), Daniel van Vugt
|
||||||
|
|
||||||
|
Translators:
|
||||||
|
Emin Tufan Çetin [tr], Dušan Kazik [sk], Matej Urbančič [sl]
|
||||||
|
|
||||||
3.28.0
|
3.28.0
|
||||||
======
|
======
|
||||||
* Fix xdg-foreign regression [Carlos; #63]
|
* Fix xdg-foreign regression [Carlos; #63]
|
||||||
|
@ -692,7 +692,7 @@ Cally_@LIBMUTTER_API_VERSION@_gir_CFLAGS = $(AM_CPPFLAGS) $(CLUTTER_CFLAGS)
|
|||||||
Cally_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
|
Cally_@LIBMUTTER_API_VERSION@_gir_SCANNERFLAGS = \
|
||||||
--warn-all \
|
--warn-all \
|
||||||
--c-include='cally/cally.h' \
|
--c-include='cally/cally.h' \
|
||||||
--pkg-export=mutter-cally-@LIBMUTTER_API_VERSION@ \
|
--pkg-export=mutter-clutter-@LIBMUTTER_API_VERSION@ \
|
||||||
--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
|
--include-uninstalled=$(top_builddir)/clutter/Clutter-@LIBMUTTER_API_VERSION@.gir
|
||||||
|
|
||||||
INTROSPECTION_GIRS += Cally-@LIBMUTTER_API_VERSION@.gir
|
INTROSPECTION_GIRS += Cally-@LIBMUTTER_API_VERSION@.gir
|
||||||
|
@ -1095,7 +1095,7 @@ clutter_event_set_device (ClutterEvent *event,
|
|||||||
{
|
{
|
||||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||||
|
|
||||||
real_event->device = device;
|
g_set_object (&real_event->device, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
@ -1364,8 +1364,8 @@ clutter_event_copy (const ClutterEvent *event)
|
|||||||
{
|
{
|
||||||
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||||
|
|
||||||
new_real_event->device = real_event->device;
|
g_set_object (&new_real_event->device, real_event->device);
|
||||||
new_real_event->source_device = real_event->source_device;
|
g_set_object (&new_real_event->source_device, real_event->source_device);
|
||||||
new_real_event->delta_x = real_event->delta_x;
|
new_real_event->delta_x = real_event->delta_x;
|
||||||
new_real_event->delta_y = real_event->delta_y;
|
new_real_event->delta_y = real_event->delta_y;
|
||||||
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
new_real_event->is_pointer_emulated = real_event->is_pointer_emulated;
|
||||||
@ -1435,6 +1435,14 @@ clutter_event_free (ClutterEvent *event)
|
|||||||
{
|
{
|
||||||
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
_clutter_backend_free_event_data (clutter_get_default_backend (), event);
|
||||||
|
|
||||||
|
if (is_event_allocated (event))
|
||||||
|
{
|
||||||
|
ClutterEventPrivate *real_event = (ClutterEventPrivate *) event;
|
||||||
|
|
||||||
|
g_clear_object (&real_event->device);
|
||||||
|
g_clear_object (&real_event->source_device);
|
||||||
|
}
|
||||||
|
|
||||||
switch (event->type)
|
switch (event->type)
|
||||||
{
|
{
|
||||||
case CLUTTER_BUTTON_PRESS:
|
case CLUTTER_BUTTON_PRESS:
|
||||||
@ -1689,7 +1697,7 @@ clutter_event_set_source_device (ClutterEvent *event,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
real_event = (ClutterEventPrivate *) event;
|
real_event = (ClutterEventPrivate *) event;
|
||||||
real_event->source_device = device;
|
g_set_object (&real_event->source_device, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,6 +353,7 @@ clutter_input_method_notify_key_event (ClutterInputMethod *im,
|
|||||||
copy = clutter_event_copy (event);
|
copy = clutter_event_copy (event);
|
||||||
clutter_event_set_flags (copy, clutter_event_get_flags (event) |
|
clutter_event_set_flags (copy, clutter_event_get_flags (event) |
|
||||||
CLUTTER_EVENT_FLAG_INPUT_METHOD);
|
CLUTTER_EVENT_FLAG_INPUT_METHOD);
|
||||||
|
clutter_event_set_source_device (copy, clutter_event_get_device (copy));
|
||||||
clutter_event_put (copy);
|
clutter_event_put (copy);
|
||||||
clutter_event_free (copy);
|
clutter_event_free (copy);
|
||||||
}
|
}
|
||||||
|
@ -3722,6 +3722,17 @@ clutter_stage_ensure_redraw (ClutterStage *stage)
|
|||||||
_clutter_master_clock_start_running (master_clock);
|
_clutter_master_clock_start_running (master_clock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clutter_stage_is_redraw_queued: (skip)
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
clutter_stage_is_redraw_queued (ClutterStage *stage)
|
||||||
|
{
|
||||||
|
ClutterStagePrivate *priv = stage->priv;
|
||||||
|
|
||||||
|
return priv->redraw_pending;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_stage_queue_redraw:
|
* clutter_stage_queue_redraw:
|
||||||
* @stage: the #ClutterStage
|
* @stage: the #ClutterStage
|
||||||
|
@ -250,6 +250,9 @@ void clutter_stage_ensure_viewport (ClutterStage
|
|||||||
CLUTTER_AVAILABLE_IN_ALL
|
CLUTTER_AVAILABLE_IN_ALL
|
||||||
void clutter_stage_ensure_redraw (ClutterStage *stage);
|
void clutter_stage_ensure_redraw (ClutterStage *stage);
|
||||||
|
|
||||||
|
CLUTTER_AVAILABLE_IN_ALL
|
||||||
|
gboolean clutter_stage_is_redraw_queued (ClutterStage *stage);
|
||||||
|
|
||||||
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
|
#ifdef CLUTTER_ENABLE_EXPERIMENTAL_API
|
||||||
CLUTTER_AVAILABLE_IN_1_14
|
CLUTTER_AVAILABLE_IN_1_14
|
||||||
void clutter_stage_set_sync_delay (ClutterStage *stage,
|
void clutter_stage_set_sync_delay (ClutterStage *stage,
|
||||||
|
@ -2830,6 +2830,10 @@ clutter_text_key_focus_in (ClutterActor *actor)
|
|||||||
if (method && priv->editable)
|
if (method && priv->editable)
|
||||||
{
|
{
|
||||||
clutter_input_method_focus_in (method, priv->input_focus);
|
clutter_input_method_focus_in (method, priv->input_focus);
|
||||||
|
clutter_input_focus_set_content_purpose (priv->input_focus,
|
||||||
|
priv->input_purpose);
|
||||||
|
clutter_input_focus_set_content_hints (priv->input_focus,
|
||||||
|
priv->input_hints);
|
||||||
update_cursor_location (CLUTTER_TEXT (actor));
|
update_cursor_location (CLUTTER_TEXT (actor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4511,6 +4515,27 @@ buffer_deleted_text (ClutterTextBuffer *buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_queue_redraw_or_relayout (ClutterText *self)
|
||||||
|
{
|
||||||
|
ClutterActor *actor = CLUTTER_ACTOR (self);
|
||||||
|
gfloat preferred_width;
|
||||||
|
gfloat preferred_height;
|
||||||
|
|
||||||
|
clutter_text_dirty_cache (self);
|
||||||
|
|
||||||
|
/* we're using our private implementations here to avoid the caching done by ClutterActor */
|
||||||
|
clutter_text_get_preferred_width (actor, -1, NULL, &preferred_width);
|
||||||
|
clutter_text_get_preferred_height (actor, preferred_width, NULL, &preferred_height);
|
||||||
|
|
||||||
|
if (clutter_actor_has_allocation (actor) &&
|
||||||
|
(fabsf (preferred_width - clutter_actor_get_width (actor)) > 0.001 ||
|
||||||
|
fabsf (preferred_height - clutter_actor_get_height (actor)) > 0.001))
|
||||||
|
clutter_actor_queue_relayout (actor);
|
||||||
|
else
|
||||||
|
clutter_text_queue_redraw (actor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
buffer_notify_text (ClutterTextBuffer *buffer,
|
buffer_notify_text (ClutterTextBuffer *buffer,
|
||||||
GParamSpec *spec,
|
GParamSpec *spec,
|
||||||
@ -4518,9 +4543,7 @@ buffer_notify_text (ClutterTextBuffer *buffer,
|
|||||||
{
|
{
|
||||||
g_object_freeze_notify (G_OBJECT (self));
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
|
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
|
g_signal_emit (self, text_signals[TEXT_CHANGED], 0);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
|
||||||
@ -4872,8 +4895,7 @@ clutter_text_set_cursor_visible (ClutterText *self,
|
|||||||
{
|
{
|
||||||
priv->cursor_visible = cursor_visible;
|
priv->cursor_visible = cursor_visible;
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_VISIBLE]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CURSOR_VISIBLE]);
|
||||||
}
|
}
|
||||||
@ -5774,9 +5796,7 @@ clutter_text_set_line_alignment (ClutterText *self,
|
|||||||
{
|
{
|
||||||
priv->alignment = alignment;
|
priv->alignment = alignment;
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
|
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_ALIGNMENT]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_LINE_ALIGNMENT]);
|
||||||
}
|
}
|
||||||
@ -5831,9 +5851,7 @@ clutter_text_set_use_markup (ClutterText *self,
|
|||||||
if (setting)
|
if (setting)
|
||||||
clutter_text_set_markup_internal (self, text);
|
clutter_text_set_markup_internal (self, text);
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
|
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5880,9 +5898,7 @@ clutter_text_set_justify (ClutterText *self,
|
|||||||
{
|
{
|
||||||
priv->justify = justify;
|
priv->justify = justify;
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
|
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_JUSTIFY]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_JUSTIFY]);
|
||||||
}
|
}
|
||||||
@ -6449,8 +6465,7 @@ clutter_text_set_preedit_string (ClutterText *self,
|
|||||||
priv->preedit_set = TRUE;
|
priv->preedit_set = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_text_dirty_cache (self);
|
clutter_text_queue_redraw_or_relayout (self);
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -6512,6 +6527,8 @@ clutter_text_set_input_hints (ClutterText *self,
|
|||||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||||
|
|
||||||
self->priv->input_hints = hints;
|
self->priv->input_hints = hints;
|
||||||
|
|
||||||
|
if (clutter_input_focus_is_focused (self->priv->input_focus))
|
||||||
clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
|
clutter_input_focus_set_content_hints (self->priv->input_focus, hints);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_HINTS]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_HINTS]);
|
||||||
}
|
}
|
||||||
@ -6531,6 +6548,8 @@ clutter_text_set_input_purpose (ClutterText *self,
|
|||||||
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
g_return_if_fail (CLUTTER_IS_TEXT (self));
|
||||||
|
|
||||||
self->priv->input_purpose = purpose;
|
self->priv->input_purpose = purpose;
|
||||||
|
|
||||||
|
if (clutter_input_focus_is_focused (self->priv->input_focus))
|
||||||
clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
|
clutter_input_focus_set_content_purpose (self->priv->input_focus, purpose);
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_PURPOSE]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_INPUT_PURPOSE]);
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,6 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
|||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->motion.time = us2ms (time_us);
|
event->motion.time = us2ms (time_us);
|
||||||
event->motion.stage = stage;
|
event->motion.stage = stage;
|
||||||
event->motion.device = seat->core_pointer;
|
|
||||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
_clutter_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;
|
||||||
@ -332,6 +331,7 @@ new_absolute_motion_event (ClutterInputDevice *input_device,
|
|||||||
&event->motion.x,
|
&event->motion.x,
|
||||||
&event->motion.y);
|
&event->motion.y);
|
||||||
event->motion.axes = axes;
|
event->motion.axes = axes;
|
||||||
|
clutter_event_set_device (event, seat->core_pointer);
|
||||||
clutter_event_set_source_device (event, input_device);
|
clutter_event_set_source_device (event, input_device);
|
||||||
|
|
||||||
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE)
|
||||||
@ -519,7 +519,6 @@ notify_proximity (ClutterInputDevice *input_device,
|
|||||||
|
|
||||||
event->proximity.time = us2ms (time_us);
|
event->proximity.time = us2ms (time_us);
|
||||||
event->proximity.stage = CLUTTER_STAGE (stage);
|
event->proximity.stage = CLUTTER_STAGE (stage);
|
||||||
event->proximity.device = seat->core_pointer;
|
|
||||||
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
clutter_event_set_device_tool (event, device_evdev->last_tool);
|
||||||
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);
|
||||||
@ -793,10 +792,12 @@ evdev_add_device (ClutterDeviceManagerEvdev *manager_evdev,
|
|||||||
if (priv->main_seat->libinput_seat == NULL)
|
if (priv->main_seat->libinput_seat == NULL)
|
||||||
seat = priv->main_seat;
|
seat = priv->main_seat;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
seat = clutter_seat_evdev_new (manager_evdev);
|
seat = clutter_seat_evdev_new (manager_evdev);
|
||||||
|
priv->seats = g_slist_append (priv->seats, seat);
|
||||||
|
}
|
||||||
|
|
||||||
clutter_seat_evdev_set_libinput_seat (seat, libinput_seat);
|
clutter_seat_evdev_set_libinput_seat (seat, libinput_seat);
|
||||||
priv->seats = g_slist_append (priv->seats, seat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
device = _clutter_input_device_evdev_new (manager, seat, libinput_device);
|
device = _clutter_input_device_evdev_new (manager, seat, libinput_device);
|
||||||
@ -919,7 +920,6 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
|
|||||||
ClutterDeviceManagerEvdev *manager_evdev;
|
ClutterDeviceManagerEvdev *manager_evdev;
|
||||||
ClutterDeviceManagerEvdevPrivate *priv;
|
ClutterDeviceManagerEvdevPrivate *priv;
|
||||||
GSList *l;
|
GSList *l;
|
||||||
GSList *device_it;
|
|
||||||
|
|
||||||
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
manager_evdev = CLUTTER_DEVICE_MANAGER_EVDEV (manager);
|
||||||
priv = manager_evdev->priv;
|
priv = manager_evdev->priv;
|
||||||
@ -927,15 +927,11 @@ clutter_device_manager_evdev_get_device (ClutterDeviceManager *manager,
|
|||||||
for (l = priv->seats; l; l = l->next)
|
for (l = priv->seats; l; l = l->next)
|
||||||
{
|
{
|
||||||
ClutterSeatEvdev *seat = l->data;
|
ClutterSeatEvdev *seat = l->data;
|
||||||
|
ClutterInputDevice *device = clutter_seat_evdev_get_device (seat, id);
|
||||||
|
|
||||||
for (device_it = seat->devices; device_it; device_it = device_it->next)
|
if (device)
|
||||||
{
|
|
||||||
ClutterInputDevice *device = device_it->data;
|
|
||||||
|
|
||||||
if (clutter_input_device_get_device_id (device) == id)
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1967,6 +1963,7 @@ clutter_device_manager_evdev_constructed (GObject *gobject)
|
|||||||
xkb_context_unref (ctx);
|
xkb_context_unref (ctx);
|
||||||
|
|
||||||
priv->main_seat = clutter_seat_evdev_new (manager_evdev);
|
priv->main_seat = clutter_seat_evdev_new (manager_evdev);
|
||||||
|
priv->seats = g_slist_append (priv->seats, priv->main_seat);
|
||||||
|
|
||||||
dispatch_libinput (manager_evdev);
|
dispatch_libinput (manager_evdev);
|
||||||
|
|
||||||
|
@ -433,6 +433,8 @@ key_event_is_modifier (ClutterEvent *event)
|
|||||||
case XKB_KEY_Super_R:
|
case XKB_KEY_Super_R:
|
||||||
case XKB_KEY_Hyper_L:
|
case XKB_KEY_Hyper_L:
|
||||||
case XKB_KEY_Hyper_R:
|
case XKB_KEY_Hyper_R:
|
||||||
|
case XKB_KEY_Caps_Lock:
|
||||||
|
case XKB_KEY_Shift_Lock:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
default:
|
default:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -584,6 +586,12 @@ handle_stickykeys_press (ClutterEvent *event,
|
|||||||
}
|
}
|
||||||
|
|
||||||
depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
|
depressed_mods = xkb_state_serialize_mods (seat->xkb, XKB_STATE_MODS_DEPRESSED);
|
||||||
|
/* Ignore the lock modifier mask, that one cannot be sticky, yet the
|
||||||
|
* CAPS_LOCK key itself counts as a modifier as it might be remapped
|
||||||
|
* to some other modifier which can be sticky.
|
||||||
|
*/
|
||||||
|
depressed_mods &= ~CLUTTER_LOCK_MASK;
|
||||||
|
|
||||||
new_latched_mask = device->stickykeys_latched_mask;
|
new_latched_mask = device->stickykeys_latched_mask;
|
||||||
new_locked_mask = device->stickykeys_locked_mask;
|
new_locked_mask = device->stickykeys_locked_mask;
|
||||||
|
|
||||||
@ -1122,6 +1130,10 @@ clutter_input_device_evdev_process_kbd_a11y_event (ClutterEvent *e
|
|||||||
{
|
{
|
||||||
ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
|
ClutterInputDeviceEvdev *device_evdev = CLUTTER_INPUT_DEVICE_EVDEV (device);
|
||||||
|
|
||||||
|
/* Ignore key events injected from IM */
|
||||||
|
if (event->key.flags & CLUTTER_EVENT_FLAG_INPUT_METHOD)
|
||||||
|
goto emit_event;
|
||||||
|
|
||||||
if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
if (!device_evdev->a11y_flags & CLUTTER_A11Y_KEYBOARD_ENABLED)
|
||||||
goto emit_event;
|
goto emit_event;
|
||||||
|
|
||||||
|
@ -385,7 +385,6 @@ new_absolute_motion_event (ClutterSeatEvdev *seat,
|
|||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->motion.time = us2ms (time_us);
|
event->motion.time = us2ms (time_us);
|
||||||
event->motion.stage = stage;
|
event->motion.stage = stage;
|
||||||
event->motion.device = seat->core_pointer;
|
|
||||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
_clutter_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;
|
||||||
@ -631,7 +630,6 @@ notify_scroll (ClutterInputDevice *input_device,
|
|||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->scroll.time = us2ms (time_us);
|
event->scroll.time = us2ms (time_us);
|
||||||
event->scroll.stage = CLUTTER_STAGE (stage);
|
event->scroll.stage = CLUTTER_STAGE (stage);
|
||||||
event->scroll.device = seat->core_pointer;
|
|
||||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||||
|
|
||||||
/* libinput pointer axis events are in pointer motion coordinate space.
|
/* libinput pointer axis events are in pointer motion coordinate space.
|
||||||
@ -684,7 +682,6 @@ notify_discrete_scroll (ClutterInputDevice *input_device,
|
|||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->scroll.time = us2ms (time_us);
|
event->scroll.time = us2ms (time_us);
|
||||||
event->scroll.stage = CLUTTER_STAGE (stage);
|
event->scroll.stage = CLUTTER_STAGE (stage);
|
||||||
event->scroll.device = seat->core_pointer;
|
|
||||||
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
_clutter_xkb_translate_state (event, seat->xkb, seat->button_state);
|
||||||
|
|
||||||
event->scroll.direction = direction;
|
event->scroll.direction = direction;
|
||||||
@ -813,7 +810,6 @@ clutter_seat_evdev_notify_touch_event (ClutterSeatEvdev *seat,
|
|||||||
_clutter_evdev_event_set_time_usec (event, time_us);
|
_clutter_evdev_event_set_time_usec (event, time_us);
|
||||||
event->touch.time = us2ms (time_us);
|
event->touch.time = us2ms (time_us);
|
||||||
event->touch.stage = CLUTTER_STAGE (stage);
|
event->touch.stage = CLUTTER_STAGE (stage);
|
||||||
event->touch.device = seat->core_pointer;
|
|
||||||
event->touch.x = x;
|
event->touch.x = x;
|
||||||
event->touch.y = y;
|
event->touch.y = y;
|
||||||
clutter_input_device_evdev_translate_coordinates (input_device, stage,
|
clutter_input_device_evdev_translate_coordinates (input_device, stage,
|
||||||
@ -858,6 +854,24 @@ clutter_seat_evdev_free (ClutterSeatEvdev *seat)
|
|||||||
g_free (seat);
|
g_free (seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClutterInputDevice *
|
||||||
|
clutter_seat_evdev_get_device (ClutterSeatEvdev *seat,
|
||||||
|
gint id)
|
||||||
|
{
|
||||||
|
ClutterInputDevice *device;
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = seat->devices; l; l = l->next)
|
||||||
|
{
|
||||||
|
device = l->data;
|
||||||
|
|
||||||
|
if (clutter_input_device_get_device_id (device) == id)
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat,
|
clutter_seat_evdev_set_stage (ClutterSeatEvdev *seat,
|
||||||
ClutterStage *stage)
|
ClutterStage *stage)
|
||||||
|
@ -139,6 +139,9 @@ void clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat,
|
|||||||
|
|
||||||
void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
|
void clutter_seat_evdev_sync_leds (ClutterSeatEvdev *seat);
|
||||||
|
|
||||||
|
ClutterInputDevice * clutter_seat_evdev_get_device (ClutterSeatEvdev *seat,
|
||||||
|
gint id);
|
||||||
|
|
||||||
ClutterTouchState * clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat,
|
ClutterTouchState * clutter_seat_evdev_acquire_touch_state (ClutterSeatEvdev *seat,
|
||||||
int device_slot);
|
int device_slot);
|
||||||
|
|
||||||
|
@ -185,6 +185,22 @@ clutter_virtual_input_device_evdev_notify_absolute_motion (ClutterVirtualInputDe
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
translate_to_evdev_button (int button)
|
||||||
|
{
|
||||||
|
switch (button)
|
||||||
|
{
|
||||||
|
case CLUTTER_BUTTON_PRIMARY:
|
||||||
|
return BTN_LEFT;
|
||||||
|
case CLUTTER_BUTTON_SECONDARY:
|
||||||
|
return BTN_RIGHT;
|
||||||
|
case CLUTTER_BUTTON_MIDDLE:
|
||||||
|
return BTN_MIDDLE;
|
||||||
|
default:
|
||||||
|
return button + (BTN_LEFT - 1) - 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *virtual_device,
|
clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||||
uint64_t time_us,
|
uint64_t time_us,
|
||||||
@ -194,30 +210,33 @@ clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *vir
|
|||||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||||
int button_count;
|
int button_count;
|
||||||
|
int evdev_button;
|
||||||
|
|
||||||
if (time_us == CLUTTER_CURRENT_TIME)
|
if (time_us == CLUTTER_CURRENT_TIME)
|
||||||
time_us = g_get_monotonic_time ();
|
time_us = g_get_monotonic_time ();
|
||||||
|
|
||||||
if (get_button_type (button) != EVDEV_BUTTON_TYPE_BUTTON)
|
evdev_button = translate_to_evdev_button (button);
|
||||||
|
|
||||||
|
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||||
{
|
{
|
||||||
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
||||||
button);
|
evdev_button);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
button_count = update_button_count (virtual_evdev, button, button_state);
|
button_count = update_button_count (virtual_evdev, evdev_button, button_state);
|
||||||
if (button_count < 0 || button_count > 1)
|
if (button_count < 0 || button_count > 1)
|
||||||
{
|
{
|
||||||
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", button,
|
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
|
||||||
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
|
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
|
||||||
update_button_count (virtual_evdev, button, 1 - button_state);
|
update_button_count (virtual_evdev, evdev_button, 1 - button_state);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_seat_evdev_notify_button (virtual_evdev->seat,
|
clutter_seat_evdev_notify_button (virtual_evdev->seat,
|
||||||
virtual_evdev->device,
|
virtual_evdev->device,
|
||||||
time_us,
|
time_us,
|
||||||
button,
|
evdev_button,
|
||||||
button_state);
|
button_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,12 +76,12 @@ _clutter_key_event_new_from_evdev (ClutterInputDevice *device,
|
|||||||
else
|
else
|
||||||
sym = XKB_KEY_NoSymbol;
|
sym = XKB_KEY_NoSymbol;
|
||||||
|
|
||||||
event->key.device = core_device;
|
|
||||||
event->key.stage = stage;
|
event->key.stage = stage;
|
||||||
event->key.time = _time;
|
event->key.time = _time;
|
||||||
_clutter_xkb_translate_state (event, xkb_state, button_state);
|
_clutter_xkb_translate_state (event, xkb_state, button_state);
|
||||||
event->key.hardware_keycode = key;
|
event->key.hardware_keycode = key;
|
||||||
event->key.keyval = sym;
|
event->key.keyval = sym;
|
||||||
|
clutter_event_set_device (event, core_device);
|
||||||
clutter_event_set_source_device (event, device);
|
clutter_event_set_source_device (event, device);
|
||||||
|
|
||||||
n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer));
|
n = xkb_keysym_to_utf8 (sym, buffer, sizeof (buffer));
|
||||||
|
@ -92,9 +92,9 @@ static gboolean perf_fake_mouse_cb (gpointer stage)
|
|||||||
event2->crossing.source = stage;
|
event2->crossing.source = stage;
|
||||||
event2->crossing.x = 10;
|
event2->crossing.x = 10;
|
||||||
event2->crossing.y = 10;
|
event2->crossing.y = 10;
|
||||||
event2->crossing.device = device;
|
|
||||||
event2->crossing.related = NULL;
|
event2->crossing.related = NULL;
|
||||||
|
|
||||||
|
clutter_event_set_device (event2, device);
|
||||||
clutter_input_device_update_from_event (device, event2, TRUE);
|
clutter_input_device_update_from_event (device, event2, TRUE);
|
||||||
|
|
||||||
clutter_event_put (event2);
|
clutter_event_put (event2);
|
||||||
@ -104,7 +104,7 @@ static gboolean perf_fake_mouse_cb (gpointer stage)
|
|||||||
|
|
||||||
clutter_actor_get_size (stage, &w, &h);
|
clutter_actor_get_size (stage, &w, &h);
|
||||||
event->motion.stage = stage;
|
event->motion.stage = stage;
|
||||||
event->motion.device = device;
|
clutter_event_set_device (event, device);
|
||||||
|
|
||||||
/* called about every 60fps, and do 10 picks per stage */
|
/* called about every 60fps, and do 10 picks per stage */
|
||||||
for (i = 0; i < 10; i++)
|
for (i = 0; i < 10; i++)
|
||||||
|
@ -452,7 +452,7 @@ libmutter_cogl_@LIBMUTTER_API_VERSION@_la_LDFLAGS = \
|
|||||||
-avoid-version \
|
-avoid-version \
|
||||||
-export-dynamic \
|
-export-dynamic \
|
||||||
-rpath $(mutterlibdir) \
|
-rpath $(mutterlibdir) \
|
||||||
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_pixel_format_get_bytes_per_pixel).*"
|
-export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly|_cogl_atlas_texture_remove_reorganize_callback|_cogl_atlas_texture_add_reorganize_callback|_cogl_texture_get_format|_cogl_texture_foreach_sub_texture_in_region|_cogl_texture_set_region|_cogl_profile_trace_message|_cogl_context_get_default|_cogl_framebuffer_get_stencil_bits|_cogl_clip_stack_push_rectangle|_cogl_framebuffer_get_modelview_stack|_cogl_object_default_unref|_cogl_pipeline_foreach_layer_internal|_cogl_clip_stack_push_primitive|_cogl_buffer_unmap_for_fill_or_fallback|_cogl_framebuffer_draw_primitive|_cogl_debug_instances|_cogl_framebuffer_get_projection_stack|_cogl_pipeline_layer_get_texture|_cogl_buffer_map_for_fill_or_fallback|_cogl_texture_can_hardware_repeat|_cogl_pipeline_prune_to_n_layers|_cogl_primitive_draw|test_|unit_test_|_cogl_winsys_glx_get_vtable|_cogl_winsys_egl_xlib_get_vtable|_cogl_winsys_egl_get_vtable|_cogl_closure_disconnect|_cogl_onscreen_notify_complete|_cogl_onscreen_notify_frame_sync|_cogl_winsys_egl_renderer_connect_common|_cogl_winsys_error_quark|_cogl_set_error|_cogl_poll_renderer_add_fd|_cogl_poll_renderer_add_idle|_cogl_framebuffer_winsys_update_size|_cogl_winsys_egl_make_current|_cogl_winsys_egl_ensure_current|_cogl_pixel_format_get_bytes_per_pixel).*"
|
||||||
|
|
||||||
libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(cogl_sources_c)
|
libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(cogl_sources_c)
|
||||||
nodist_libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)
|
nodist_libmutter_cogl_@LIBMUTTER_API_VERSION@_la_SOURCES = $(BUILT_SOURCES)
|
||||||
|
@ -1043,5 +1043,6 @@ cogl_atlas_texture_vtable =
|
|||||||
_cogl_atlas_texture_get_gl_format,
|
_cogl_atlas_texture_get_gl_format,
|
||||||
_cogl_atlas_texture_get_type,
|
_cogl_atlas_texture_get_type,
|
||||||
NULL, /* is_foreign */
|
NULL, /* is_foreign */
|
||||||
NULL /* set_auto_mipmap */
|
NULL, /* set_auto_mipmap */
|
||||||
|
NULL /* is_get_data_supported */
|
||||||
};
|
};
|
||||||
|
@ -263,6 +263,7 @@ typedef enum _CoglFeatureID
|
|||||||
COGL_FEATURE_ID_TEXTURE_RG,
|
COGL_FEATURE_ID_TEXTURE_RG,
|
||||||
COGL_FEATURE_ID_BUFFER_AGE,
|
COGL_FEATURE_ID_BUFFER_AGE,
|
||||||
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
|
COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
|
||||||
|
COGL_FEATURE_ID_UNSTABLE_TEXTURES,
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
_COGL_N_FEATURE_IDS /*< skip >*/
|
_COGL_N_FEATURE_IDS /*< skip >*/
|
||||||
|
@ -210,6 +210,9 @@ struct _CoglDriverVtable
|
|||||||
int rowstride,
|
int rowstride,
|
||||||
uint8_t *data);
|
uint8_t *data);
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
(* texture_2d_is_get_data_supported) (CoglTexture2D *tex_2d);
|
||||||
|
|
||||||
/* Prepares for drawing by flushing the journal, framebuffer state,
|
/* Prepares for drawing by flushing the journal, framebuffer state,
|
||||||
* pipeline state and attribute state.
|
* pipeline state and attribute state.
|
||||||
*/
|
*/
|
||||||
|
@ -109,7 +109,11 @@ _cogl_object_default_unref (void *object)
|
|||||||
void
|
void
|
||||||
cogl_object_unref (void *obj)
|
cogl_object_unref (void *obj)
|
||||||
{
|
{
|
||||||
void (* unref_func) (void *) = ((CoglObject *) obj)->klass->virt_unref;
|
void (* unref_func) (void *);
|
||||||
|
|
||||||
|
_COGL_RETURN_IF_FAIL (obj != NULL);
|
||||||
|
|
||||||
|
unref_func = ((CoglObject *) obj)->klass->virt_unref;
|
||||||
unref_func (obj);
|
unref_func (obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,6 +454,14 @@ _cogl_sub_texture_get_type (CoglTexture *tex)
|
|||||||
return _cogl_texture_get_type (sub_tex->full_texture);
|
return _cogl_texture_get_type (sub_tex->full_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_sub_texture_is_get_data_supported (CoglTexture *tex)
|
||||||
|
{
|
||||||
|
CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
|
||||||
|
|
||||||
|
return cogl_texture_is_get_data_supported (sub_tex->full_texture);
|
||||||
|
}
|
||||||
|
|
||||||
static const CoglTextureVtable
|
static const CoglTextureVtable
|
||||||
cogl_sub_texture_vtable =
|
cogl_sub_texture_vtable =
|
||||||
{
|
{
|
||||||
@ -476,5 +484,6 @@ cogl_sub_texture_vtable =
|
|||||||
_cogl_sub_texture_get_gl_format,
|
_cogl_sub_texture_get_gl_format,
|
||||||
_cogl_sub_texture_get_type,
|
_cogl_sub_texture_get_type,
|
||||||
NULL, /* is_foreign */
|
NULL, /* is_foreign */
|
||||||
NULL /* set_auto_mipmap */
|
NULL, /* set_auto_mipmap */
|
||||||
|
_cogl_sub_texture_is_get_data_supported
|
||||||
};
|
};
|
||||||
|
@ -1542,5 +1542,6 @@ cogl_texture_2d_sliced_vtable =
|
|||||||
_cogl_texture_2d_sliced_get_gl_format,
|
_cogl_texture_2d_sliced_get_gl_format,
|
||||||
_cogl_texture_2d_sliced_get_type,
|
_cogl_texture_2d_sliced_get_type,
|
||||||
_cogl_texture_2d_sliced_is_foreign,
|
_cogl_texture_2d_sliced_is_foreign,
|
||||||
NULL /* set_auto_mipmap */
|
NULL, /* set_auto_mipmap */
|
||||||
|
NULL /* is_get_data_supported */
|
||||||
};
|
};
|
||||||
|
@ -94,6 +94,15 @@ _cogl_texture_2d_set_auto_mipmap (CoglTexture *tex,
|
|||||||
tex_2d->auto_mipmap = value;
|
tex_2d->auto_mipmap = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglBool
|
||||||
|
_cogl_texture_2d_is_get_data_supported (CoglTexture *tex)
|
||||||
|
{
|
||||||
|
CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
|
||||||
|
CoglContext *ctx = tex->context;
|
||||||
|
|
||||||
|
return ctx->driver_vtable->texture_2d_is_get_data_supported (tex_2d);
|
||||||
|
}
|
||||||
|
|
||||||
CoglTexture2D *
|
CoglTexture2D *
|
||||||
_cogl_texture_2d_create_base (CoglContext *ctx,
|
_cogl_texture_2d_create_base (CoglContext *ctx,
|
||||||
int width,
|
int width,
|
||||||
@ -693,5 +702,6 @@ cogl_texture_2d_vtable =
|
|||||||
_cogl_texture_2d_get_gl_format,
|
_cogl_texture_2d_get_gl_format,
|
||||||
_cogl_texture_2d_get_type,
|
_cogl_texture_2d_get_type,
|
||||||
_cogl_texture_2d_is_foreign,
|
_cogl_texture_2d_is_foreign,
|
||||||
_cogl_texture_2d_set_auto_mipmap
|
_cogl_texture_2d_set_auto_mipmap,
|
||||||
|
_cogl_texture_2d_is_get_data_supported
|
||||||
};
|
};
|
||||||
|
@ -755,5 +755,6 @@ cogl_texture_3d_vtable =
|
|||||||
_cogl_texture_3d_get_gl_format,
|
_cogl_texture_3d_get_gl_format,
|
||||||
_cogl_texture_3d_get_type,
|
_cogl_texture_3d_get_type,
|
||||||
NULL, /* is_foreign */
|
NULL, /* is_foreign */
|
||||||
_cogl_texture_3d_set_auto_mipmap
|
_cogl_texture_3d_set_auto_mipmap,
|
||||||
|
NULL /* is_get_data_supported */
|
||||||
};
|
};
|
||||||
|
@ -149,6 +149,8 @@ struct _CoglTextureVtable
|
|||||||
/* Only needs to be implemented if is_primitive == TRUE */
|
/* Only needs to be implemented if is_primitive == TRUE */
|
||||||
void (* set_auto_mipmap) (CoglTexture *texture,
|
void (* set_auto_mipmap) (CoglTexture *texture,
|
||||||
CoglBool value);
|
CoglBool value);
|
||||||
|
|
||||||
|
CoglBool (* is_get_data_supported) (CoglTexture *texture);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum _CoglTextureSoureType {
|
typedef enum _CoglTextureSoureType {
|
||||||
|
@ -773,5 +773,6 @@ cogl_texture_rectangle_vtable =
|
|||||||
_cogl_texture_rectangle_get_gl_format,
|
_cogl_texture_rectangle_get_gl_format,
|
||||||
_cogl_texture_rectangle_get_type,
|
_cogl_texture_rectangle_get_type,
|
||||||
_cogl_texture_rectangle_is_foreign,
|
_cogl_texture_rectangle_is_foreign,
|
||||||
_cogl_texture_rectangle_set_auto_mipmap
|
_cogl_texture_rectangle_set_auto_mipmap,
|
||||||
|
NULL /* is_get_data_supported */
|
||||||
};
|
};
|
||||||
|
@ -205,6 +205,15 @@ _cogl_texture_is_foreign (CoglTexture *texture)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_is_get_data_supported (CoglTexture *texture)
|
||||||
|
{
|
||||||
|
if (texture->vtable->is_get_data_supported)
|
||||||
|
return texture->vtable->is_get_data_supported (texture);
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
cogl_texture_get_width (CoglTexture *texture)
|
cogl_texture_get_width (CoglTexture *texture)
|
||||||
{
|
{
|
||||||
|
@ -511,6 +511,12 @@ CoglBool
|
|||||||
cogl_texture_allocate (CoglTexture *texture,
|
cogl_texture_allocate (CoglTexture *texture,
|
||||||
CoglError **error);
|
CoglError **error);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* cogl_texture_is_get_data_supported: (skip)
|
||||||
|
*/
|
||||||
|
CoglBool
|
||||||
|
cogl_texture_is_get_data_supported (CoglTexture *texture);
|
||||||
|
|
||||||
COGL_END_DECLS
|
COGL_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_TEXTURE_H__ */
|
#endif /* __COGL_TEXTURE_H__ */
|
||||||
|
@ -398,6 +398,8 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
|
|||||||
* supported with CoglBufferAccess including write support.
|
* supported with CoglBufferAccess including write support.
|
||||||
* @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
|
* @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the
|
||||||
* depth buffer to a texture.
|
* depth buffer to a texture.
|
||||||
|
* @COGL_FEATURE_UNSTABLE_TEXTURES: Whether textures require redrawing on
|
||||||
|
* resume or not.
|
||||||
*
|
*
|
||||||
* Flags for the supported features.
|
* Flags for the supported features.
|
||||||
*
|
*
|
||||||
@ -428,7 +430,8 @@ typedef enum
|
|||||||
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
|
COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
|
||||||
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
|
COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
|
||||||
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),
|
COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23),
|
||||||
COGL_FEATURE_DEPTH_TEXTURE = (1 << 24)
|
COGL_FEATURE_DEPTH_TEXTURE = (1 << 24),
|
||||||
|
COGL_FEATURE_UNSTABLE_TEXTURES = (1 << 25)
|
||||||
} CoglFeatureFlags;
|
} CoglFeatureFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1412,22 +1412,12 @@ _cogl_framebuffer_gl_read_pixels_into_bitmap (CoglFramebuffer *framebuffer,
|
|||||||
if (!cogl_is_offscreen (framebuffer))
|
if (!cogl_is_offscreen (framebuffer))
|
||||||
y = framebuffer_height - y - height;
|
y = framebuffer_height - y - height;
|
||||||
|
|
||||||
required_format = ctx->driver_vtable->pixel_format_to_gl (ctx,
|
required_format = ctx->driver_vtable->pixel_format_to_gl_with_target (ctx,
|
||||||
|
framebuffer->internal_format,
|
||||||
format,
|
format,
|
||||||
&gl_intformat,
|
&gl_intformat,
|
||||||
&gl_format,
|
&gl_format,
|
||||||
&gl_type);
|
&gl_type);
|
||||||
#if HAVE_COGL_GL
|
|
||||||
/* As we are reading pixels, we want to consider the bitmap according to
|
|
||||||
* its real pixel format, not the swizzled channels we pretend face to the
|
|
||||||
* pipeline.
|
|
||||||
*/
|
|
||||||
if ((ctx->driver == COGL_DRIVER_GL || ctx->driver == COGL_DRIVER_GL3) &&
|
|
||||||
(format == COGL_PIXEL_FORMAT_BGRA_8888 ||
|
|
||||||
format == COGL_PIXEL_FORMAT_BGRA_8888_PRE) &&
|
|
||||||
_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_TEXTURE_SWIZZLE))
|
|
||||||
gl_format = GL_BGRA;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* NB: All offscreen rendering is done upside down so there is no need
|
/* NB: All offscreen rendering is done upside down so there is no need
|
||||||
* to flip in this case... */
|
* to flip in this case... */
|
||||||
|
@ -116,4 +116,7 @@ _cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
|
|||||||
int rowstride,
|
int rowstride,
|
||||||
uint8_t *data);
|
uint8_t *data);
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
_cogl_texture_2d_gl_is_get_data_supported (CoglTexture2D *tex_2d);
|
||||||
|
|
||||||
#endif /* _COGL_TEXTURE_2D_GL_PRIVATE_H_ */
|
#endif /* _COGL_TEXTURE_2D_GL_PRIVATE_H_ */
|
||||||
|
@ -470,7 +470,12 @@ allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
|
|||||||
{
|
{
|
||||||
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
CoglTexture *tex = COGL_TEXTURE (tex_2d);
|
||||||
CoglContext *ctx = tex->context;
|
CoglContext *ctx = tex->context;
|
||||||
CoglPixelFormat internal_format = loader->src.egl_image_external.format;
|
CoglPixelFormat external_format;
|
||||||
|
CoglPixelFormat internal_format;
|
||||||
|
|
||||||
|
external_format = loader->src.egl_image_external.format;
|
||||||
|
internal_format = _cogl_texture_determine_internal_format (tex,
|
||||||
|
external_format);
|
||||||
|
|
||||||
_cogl_gl_util_clear_gl_errors (ctx);
|
_cogl_gl_util_clear_gl_errors (ctx);
|
||||||
|
|
||||||
@ -854,13 +859,22 @@ _cogl_texture_2d_gl_get_data (CoglTexture2D *tex_2d,
|
|||||||
width,
|
width,
|
||||||
bpp);
|
bpp);
|
||||||
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
|
_cogl_bind_gl_texture_transient (tex_2d->gl_target,
|
||||||
tex_2d->gl_texture,
|
tex_2d->gl_texture,
|
||||||
tex_2d->is_foreign);
|
tex_2d->is_foreign);
|
||||||
|
|
||||||
ctx->texture_driver->gl_get_tex_image (ctx,
|
ctx->texture_driver->gl_get_tex_image (ctx,
|
||||||
GL_TEXTURE_2D,
|
tex_2d->gl_target,
|
||||||
gl_format,
|
gl_format,
|
||||||
gl_type,
|
gl_type,
|
||||||
data);
|
data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoglBool
|
||||||
|
_cogl_texture_2d_gl_is_get_data_supported (CoglTexture2D *tex_2d)
|
||||||
|
{
|
||||||
|
if (tex_2d->gl_target == GL_TEXTURE_EXTERNAL_OES)
|
||||||
|
return FALSE;
|
||||||
|
else
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -714,6 +714,7 @@ _cogl_driver_gl =
|
|||||||
_cogl_texture_2d_gl_generate_mipmap,
|
_cogl_texture_2d_gl_generate_mipmap,
|
||||||
_cogl_texture_2d_gl_copy_from_bitmap,
|
_cogl_texture_2d_gl_copy_from_bitmap,
|
||||||
_cogl_texture_2d_gl_get_data,
|
_cogl_texture_2d_gl_get_data,
|
||||||
|
_cogl_texture_2d_gl_is_get_data_supported,
|
||||||
_cogl_gl_flush_attributes_state,
|
_cogl_gl_flush_attributes_state,
|
||||||
_cogl_clip_stack_gl_flush,
|
_cogl_clip_stack_gl_flush,
|
||||||
_cogl_buffer_gl_create,
|
_cogl_buffer_gl_create,
|
||||||
|
@ -493,6 +493,7 @@ _cogl_driver_gles =
|
|||||||
_cogl_texture_2d_gl_generate_mipmap,
|
_cogl_texture_2d_gl_generate_mipmap,
|
||||||
_cogl_texture_2d_gl_copy_from_bitmap,
|
_cogl_texture_2d_gl_copy_from_bitmap,
|
||||||
NULL, /* texture_2d_get_data */
|
NULL, /* texture_2d_get_data */
|
||||||
|
NULL, /* texture_2d_is_get_data_supported */
|
||||||
_cogl_gl_flush_attributes_state,
|
_cogl_gl_flush_attributes_state,
|
||||||
_cogl_clip_stack_gl_flush,
|
_cogl_clip_stack_gl_flush,
|
||||||
_cogl_buffer_gl_create,
|
_cogl_buffer_gl_create,
|
||||||
|
@ -82,6 +82,7 @@ _cogl_driver_nop =
|
|||||||
_cogl_texture_2d_nop_generate_mipmap,
|
_cogl_texture_2d_nop_generate_mipmap,
|
||||||
_cogl_texture_2d_nop_copy_from_bitmap,
|
_cogl_texture_2d_nop_copy_from_bitmap,
|
||||||
NULL, /* texture_2d_get_data */
|
NULL, /* texture_2d_get_data */
|
||||||
|
NULL, /* texture_2d_is_get_data_supported */
|
||||||
_cogl_nop_flush_attributes_state,
|
_cogl_nop_flush_attributes_state,
|
||||||
_cogl_clip_stack_nop_flush,
|
_cogl_clip_stack_nop_flush,
|
||||||
};
|
};
|
||||||
|
@ -1180,5 +1180,6 @@ cogl_texture_pixmap_x11_vtable =
|
|||||||
_cogl_texture_pixmap_x11_get_gl_format,
|
_cogl_texture_pixmap_x11_get_gl_format,
|
||||||
_cogl_texture_pixmap_x11_get_type,
|
_cogl_texture_pixmap_x11_get_type,
|
||||||
NULL, /* is_foreign */
|
NULL, /* is_foreign */
|
||||||
NULL /* set_auto_mipmap */
|
NULL, /* set_auto_mipmap */
|
||||||
|
NULL /* is_get_data_supported */
|
||||||
};
|
};
|
||||||
|
@ -181,6 +181,9 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
|
|||||||
EGLSurface read,
|
EGLSurface read,
|
||||||
EGLContext context);
|
EGLContext context);
|
||||||
|
|
||||||
|
EGLBoolean
|
||||||
|
_cogl_winsys_egl_ensure_current (CoglDisplay *display);
|
||||||
|
|
||||||
#ifdef EGL_KHR_image_base
|
#ifdef EGL_KHR_image_base
|
||||||
EGLImageKHR
|
EGLImageKHR
|
||||||
_cogl_egl_create_image (CoglContext *ctx,
|
_cogl_egl_create_image (CoglContext *ctx,
|
||||||
|
@ -309,6 +309,18 @@ _cogl_winsys_egl_make_current (CoglDisplay *display,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLBoolean
|
||||||
|
_cogl_winsys_egl_ensure_current (CoglDisplay *display)
|
||||||
|
{
|
||||||
|
CoglDisplayEGL *egl_display = display->winsys;
|
||||||
|
CoglRendererEGL *egl_renderer = display->renderer->winsys;
|
||||||
|
|
||||||
|
return eglMakeCurrent (egl_renderer->edpy,
|
||||||
|
egl_display->current_draw_surface,
|
||||||
|
egl_display->current_read_surface,
|
||||||
|
egl_display->current_context);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cleanup_context (CoglDisplay *display)
|
cleanup_context (CoglDisplay *display)
|
||||||
{
|
{
|
||||||
@ -490,6 +502,7 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error)
|
|||||||
CoglRenderer *renderer = context->display->renderer;
|
CoglRenderer *renderer = context->display->renderer;
|
||||||
CoglDisplayEGL *egl_display = context->display->winsys;
|
CoglDisplayEGL *egl_display = context->display->winsys;
|
||||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||||
|
CoglGpuInfo *info;
|
||||||
|
|
||||||
context->winsys = g_new0 (CoglContextEGL, 1);
|
context->winsys = g_new0 (CoglContextEGL, 1);
|
||||||
|
|
||||||
@ -502,6 +515,16 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error)
|
|||||||
if (!_cogl_context_update_features (context, error))
|
if (!_cogl_context_update_features (context, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
info = &context->gpu;
|
||||||
|
|
||||||
|
if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
||||||
|
{
|
||||||
|
context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
|
||||||
|
COGL_FLAGS_SET (context->features,
|
||||||
|
COGL_FEATURE_ID_UNSTABLE_TEXTURES,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION)
|
if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION)
|
||||||
{
|
{
|
||||||
COGL_FLAGS_SET (context->winsys_features,
|
COGL_FLAGS_SET (context->winsys_features,
|
||||||
|
@ -832,12 +832,15 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|||||||
{
|
{
|
||||||
CoglGLXDisplay *glx_display = context->display->winsys;
|
CoglGLXDisplay *glx_display = context->display->winsys;
|
||||||
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
|
CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
|
||||||
|
CoglGpuInfo *info;
|
||||||
|
|
||||||
_COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE);
|
_COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE);
|
||||||
|
|
||||||
if (!_cogl_context_update_features (context, error))
|
if (!_cogl_context_update_features (context, error))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
info = &context->gpu;
|
||||||
|
|
||||||
memcpy (context->winsys_features,
|
memcpy (context->winsys_features,
|
||||||
glx_renderer->base_winsys_features,
|
glx_renderer->base_winsys_features,
|
||||||
sizeof (context->winsys_features));
|
sizeof (context->winsys_features));
|
||||||
@ -850,7 +853,6 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|||||||
|
|
||||||
if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer)
|
if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer)
|
||||||
{
|
{
|
||||||
CoglGpuInfo *info = &context->gpu;
|
|
||||||
CoglGpuInfoArchitecture arch = info->architecture;
|
CoglGpuInfoArchitecture arch = info->architecture;
|
||||||
|
|
||||||
COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
|
COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
|
||||||
@ -899,7 +901,6 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CoglGpuInfo *info = &context->gpu;
|
|
||||||
if (glx_display->have_vblank_counter &&
|
if (glx_display->have_vblank_counter &&
|
||||||
context->display->renderer->xlib_enable_threaded_swap_wait &&
|
context->display->renderer->xlib_enable_threaded_swap_wait &&
|
||||||
info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
||||||
@ -921,6 +922,14 @@ update_winsys_features (CoglContext *context, CoglError **error)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA)
|
||||||
|
{
|
||||||
|
context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES;
|
||||||
|
COGL_FLAGS_SET (context->features,
|
||||||
|
COGL_FEATURE_ID_UNSTABLE_TEXTURES,
|
||||||
|
TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/* We'll manually handle queueing dirty events in response to
|
/* We'll manually handle queueing dirty events in response to
|
||||||
* Expose events from X */
|
* Expose events from X */
|
||||||
COGL_FLAGS_SET (context->private_features,
|
COGL_FLAGS_SET (context->private_features,
|
||||||
|
30
configure.ac
30
configure.ac
@ -2,7 +2,7 @@ AC_PREREQ(2.62)
|
|||||||
|
|
||||||
m4_define([mutter_major_version], [3])
|
m4_define([mutter_major_version], [3])
|
||||||
m4_define([mutter_minor_version], [28])
|
m4_define([mutter_minor_version], [28])
|
||||||
m4_define([mutter_micro_version], [0])
|
m4_define([mutter_micro_version], [3])
|
||||||
|
|
||||||
m4_define([mutter_version],
|
m4_define([mutter_version],
|
||||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||||
@ -245,7 +245,7 @@ AC_ARG_ENABLE(remote-desktop,
|
|||||||
enable_remote_desktop=no
|
enable_remote_desktop=no
|
||||||
)
|
)
|
||||||
AS_IF([test "$enable_remote_desktop" = "yes"], [
|
AS_IF([test "$enable_remote_desktop" = "yes"], [
|
||||||
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libpipewire-0.1 >= 0.1.8"
|
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libpipewire-0.2 >= 0.2.5"
|
||||||
AC_DEFINE([HAVE_REMOTE_DESKTOP],[1], [Defined if screen cast and remote desktop support is enabled])
|
AC_DEFINE([HAVE_REMOTE_DESKTOP],[1], [Defined if screen cast and remote desktop support is enabled])
|
||||||
])
|
])
|
||||||
AM_CONDITIONAL([HAVE_REMOTE_DESKTOP],[test "$enable_remote_desktop" = "yes"])
|
AM_CONDITIONAL([HAVE_REMOTE_DESKTOP],[test "$enable_remote_desktop" = "yes"])
|
||||||
@ -262,7 +262,19 @@ AC_SUBST(XWAYLAND_PATH)
|
|||||||
|
|
||||||
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
|
||||||
|
|
||||||
MUTTER_NATIVE_BACKEND_MODULES="libdrm >= 2.4.83 libsystemd libinput >= 1.4 gudev-1.0 gbm >= 17.1"
|
PKG_CHECK_MODULES(ELOGIND, [libelogind], [have_elogind=yes], [have_elogind=no])
|
||||||
|
|
||||||
|
if test x$have_elogind = xyes; then
|
||||||
|
logind_provider="libelogind"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PKG_CHECK_MODULES(SYSTEMD, [libsystemd], [have_systemd=yes], [have_systemd=no])
|
||||||
|
|
||||||
|
if test x$have_systemd = xyes -o -z "$logind_provider"; then
|
||||||
|
logind_provider="libsystemd"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MUTTER_NATIVE_BACKEND_MODULES="libdrm $logind_provider libinput >= 1.4 gudev-1.0 gbm >= 10.3"
|
||||||
|
|
||||||
AC_ARG_ENABLE(native-backend,
|
AC_ARG_ENABLE(native-backend,
|
||||||
AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
|
AS_HELP_STRING([--disable-native-backend], [disable mutter native (KMS) backend]),,
|
||||||
@ -278,13 +290,24 @@ AS_IF([test "$have_native_backend" = "yes"], [
|
|||||||
])
|
])
|
||||||
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
|
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test "$have_native_backend" = "yes"])
|
||||||
|
|
||||||
|
MUTTER_WAYLAND_EGLSTREAM_MODULES="wayland-eglstream-protocols"
|
||||||
|
|
||||||
AC_ARG_ENABLE(egl-device,
|
AC_ARG_ENABLE(egl-device,
|
||||||
AS_HELP_STRING([--enable-egl-device], [enable support for EGLDevice on top of KMS]),,
|
AS_HELP_STRING([--enable-egl-device], [enable support for EGLDevice on top of KMS]),,
|
||||||
enable_egl_device=no
|
enable_egl_device=no
|
||||||
|
have_wayland_eglstream=no
|
||||||
)
|
)
|
||||||
AS_IF([test "$enable_egl_device" = "yes"], [
|
AS_IF([test "$enable_egl_device" = "yes"], [
|
||||||
AC_DEFINE([HAVE_EGL_DEVICE],[1], [Defined if EGLDevice support is enabled])
|
AC_DEFINE([HAVE_EGL_DEVICE],[1], [Defined if EGLDevice support is enabled])
|
||||||
|
PKG_CHECK_EXISTS([$MUTTER_WAYLAND_EGLSTREAM_MODULES], [have_wayland_eglstream=yes], [have_wayland_eglstream=no])
|
||||||
])
|
])
|
||||||
|
AS_IF([test "$have_wayland_eglstream" = "yes"], [
|
||||||
|
AC_DEFINE([HAVE_WAYLAND_EGLSTREAM],[1],[Defined if Wayland EGLStream protocols are available])
|
||||||
|
PKG_CHECK_MODULES(WAYLAND_EGLSTREAM, [$MUTTER_WAYLAND_EGLSTREAM_MODULES],
|
||||||
|
[ac_wayland_eglstream_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir $MUTTER_WAYLAND_EGLSTREAM_MODULES`])
|
||||||
|
AC_SUBST(WAYLAND_EGLSTREAM_DATADIR, $ac_wayland_eglstream_pkgdatadir)
|
||||||
|
])
|
||||||
|
AM_CONDITIONAL([HAVE_WAYLAND_EGLSTREAM],[test "$have_wayland_eglstream" = "yes"])
|
||||||
|
|
||||||
MUTTER_WAYLAND_MODULES="wayland-server >= 1.13.0"
|
MUTTER_WAYLAND_MODULES="wayland-server >= 1.13.0"
|
||||||
|
|
||||||
@ -537,6 +560,7 @@ mutter-$VERSION
|
|||||||
Introspection: ${found_introspection}
|
Introspection: ${found_introspection}
|
||||||
Session management: ${found_sm}
|
Session management: ${found_sm}
|
||||||
Wayland: ${have_wayland}
|
Wayland: ${have_wayland}
|
||||||
|
Wayland EGLStream: ${have_wayland_eglstream}
|
||||||
Native (KMS) backend: ${have_native_backend}
|
Native (KMS) backend: ${have_native_backend}
|
||||||
EGLDevice: ${enable_egl_device}
|
EGLDevice: ${enable_egl_device}
|
||||||
Remote desktop: ${enable_remote_desktop}
|
Remote desktop: ${enable_remote_desktop}
|
||||||
|
@ -120,10 +120,6 @@
|
|||||||
framebuffers instead of window content,
|
framebuffers instead of window content,
|
||||||
to manage HiDPI monitors. Does not
|
to manage HiDPI monitors. Does not
|
||||||
require a restart.
|
require a restart.
|
||||||
• “remote-desktop” — enables remote desktop support. To support
|
|
||||||
remote desktop with screen sharing,
|
|
||||||
“screen-cast” must also be enabled.
|
|
||||||
• “screen-cast” — enables screen cast support.
|
|
||||||
</description>
|
</description>
|
||||||
</key>
|
</key>
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@
|
|||||||
gettext-domain="@GETTEXT_DOMAIN@">
|
gettext-domain="@GETTEXT_DOMAIN@">
|
||||||
|
|
||||||
<key name="xwayland-allow-grabs" type="b">
|
<key name="xwayland-allow-grabs" type="b">
|
||||||
<default>false</default>
|
<default>true</default>
|
||||||
<summary>Allow grabs with Xwayland</summary>
|
<summary>Allow grabs with Xwayland</summary>
|
||||||
<description>
|
<description>
|
||||||
Allow keyboard grabs issued by X11 applications running in Xwayland
|
Allow keyboard grabs issued by X11 applications running in Xwayland
|
||||||
@ -73,7 +73,7 @@
|
|||||||
</key>
|
</key>
|
||||||
|
|
||||||
<key name="xwayland-grab-access-rules" type="as">
|
<key name="xwayland-grab-access-rules" type="as">
|
||||||
<default>[]</default>
|
<default>['@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@']</default>
|
||||||
<summary>Xwayland applications allowed to issue keyboard grabs</summary>
|
<summary>Xwayland applications allowed to issue keyboard grabs</summary>
|
||||||
<description>
|
<description>
|
||||||
List the resource names or resource class of X11 windows either
|
List the resource names or resource class of X11 windows either
|
||||||
|
23
po/sl.po
23
po/sl.po
@ -10,8 +10,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: 2018-03-05 19:32+0000\n"
|
"POT-Creation-Date: 2018-04-03 20:43+0000\n"
|
||||||
"PO-Revision-Date: 2018-03-06 22:02+0100\n"
|
"PO-Revision-Date: 2018-04-09 20:28+0200\n"
|
||||||
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
|
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
|
||||||
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
|
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
|
||||||
"Language: sl_SI\n"
|
"Language: sl_SI\n"
|
||||||
@ -21,7 +21,7 @@ msgstr ""
|
|||||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n"
|
||||||
"%100==4 ? 3 : 0);\n"
|
"%100==4 ? 3 : 0);\n"
|
||||||
"X-Poedit-SourceCharset: utf-8\n"
|
"X-Poedit-SourceCharset: utf-8\n"
|
||||||
"X-Generator: Poedit 2.0.4\n"
|
"X-Generator: Poedit 2.0.6\n"
|
||||||
|
|
||||||
#: data/50-mutter-navigation.xml:6
|
#: data/50-mutter-navigation.xml:6
|
||||||
msgid "Navigation"
|
msgid "Navigation"
|
||||||
@ -481,7 +481,7 @@ msgstr "Ponovno omogoči tipkovne bližnjice"
|
|||||||
|
|
||||||
#: 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 grabs with Xwayland"
|
||||||
msgstr ""
|
msgstr "Dovoli zajemanje z XWayland"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -491,10 +491,14 @@ msgid ""
|
|||||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
"window or be among the applications white-listed in key “xwayland-grab-"
|
||||||
"access-rules”."
|
"access-rules”."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Upošteva zajeme s tipkovnico, ki jih sprožijo programi X11, zagnani v okolju "
|
||||||
|
"Xwayland. Če naj se programski zajem upošteva, mora odjemalec ali poslati "
|
||||||
|
"specifično sporočilo X11 na korensko okno ali pa mora biti zaveden na "
|
||||||
|
"seznamu programov v ključu »xwayland-garb-access-rules«."
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
||||||
msgid "Xwayland applications allowed to issue keyboard grabs"
|
msgid "Xwayland applications allowed to issue keyboard grabs"
|
||||||
msgstr ""
|
msgstr "Program XWayland ima dovoljenje za zajemanje s tipkovnico"
|
||||||
|
|
||||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
||||||
msgid ""
|
msgid ""
|
||||||
@ -509,6 +513,15 @@ msgid ""
|
|||||||
"using the specific keyboard shortcut defined by the keybinding key “restore-"
|
"using the specific keyboard shortcut defined by the keybinding key “restore-"
|
||||||
"shortcuts”."
|
"shortcuts”."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Seznam imen ali razredov virov oken X11, ki lahko sprožijo zajeme v okolju "
|
||||||
|
"Xwayland. Ime oziroma razred vira podanega okna X11 je mogoče pridobiti z "
|
||||||
|
"ukazom »xprop WM_CLASS«. Uporaba pomožnih znakov » * « in » ? « je podprta. "
|
||||||
|
"Vrednosti, ki se začnejo z znakom » ! « so uvrščeni na črni seznam. Ta "
|
||||||
|
"seznam je obravnavan prednostno pred belim seznamom in prekliče zajeme na "
|
||||||
|
"seznamu sistema. Privzeti seznam vključuje ključ: "
|
||||||
|
"»@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@« Uporabniki lahko prekinejo obstoječi "
|
||||||
|
"zajem z uporabo posebne tipkovne bližnjice, določene s tipkovnim ključem "
|
||||||
|
"»restore-shortcuts«."
|
||||||
|
|
||||||
#. TRANSLATORS: This string refers to a button that switches between
|
#. TRANSLATORS: This string refers to a button that switches between
|
||||||
#. * different modes.
|
#. * different modes.
|
||||||
|
@ -14,6 +14,7 @@ stackingdir = $(pkgdatadir)/tests/stacking
|
|||||||
dist_stacking_DATA = \
|
dist_stacking_DATA = \
|
||||||
tests/stacking/basic-x11.metatest \
|
tests/stacking/basic-x11.metatest \
|
||||||
tests/stacking/basic-wayland.metatest \
|
tests/stacking/basic-wayland.metatest \
|
||||||
|
tests/stacking/closed-transient.metatest \
|
||||||
tests/stacking/minimized.metatest \
|
tests/stacking/minimized.metatest \
|
||||||
tests/stacking/mixed-windows.metatest \
|
tests/stacking/mixed-windows.metatest \
|
||||||
tests/stacking/set-parent.metatest \
|
tests/stacking/set-parent.metatest \
|
||||||
|
@ -91,6 +91,12 @@ mutter_built_sources += \
|
|||||||
gtk-text-input-protocol.c \
|
gtk-text-input-protocol.c \
|
||||||
gtk-text-input-server-protocol.h \
|
gtk-text-input-server-protocol.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
if HAVE_WAYLAND_EGLSTREAM
|
||||||
|
mutter_built_sources += \
|
||||||
|
wayland-eglstream-controller-server-protocol.h \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
wayland_protocols = \
|
wayland_protocols = \
|
||||||
@ -114,6 +120,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
|
|||||||
backends/meta-cursor-tracker-private.h \
|
backends/meta-cursor-tracker-private.h \
|
||||||
backends/meta-cursor-renderer.c \
|
backends/meta-cursor-renderer.c \
|
||||||
backends/meta-cursor-renderer.h \
|
backends/meta-cursor-renderer.h \
|
||||||
|
backends/meta-cursor-sprite-xcursor.c \
|
||||||
|
backends/meta-cursor-sprite-xcursor.h \
|
||||||
backends/meta-dnd-private.h \
|
backends/meta-dnd-private.h \
|
||||||
backends/meta-egl.c \
|
backends/meta-egl.c \
|
||||||
backends/meta-egl.h \
|
backends/meta-egl.h \
|
||||||
@ -151,16 +159,22 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
|
|||||||
backends/meta-output.h \
|
backends/meta-output.h \
|
||||||
backends/meta-pointer-constraint.c \
|
backends/meta-pointer-constraint.c \
|
||||||
backends/meta-pointer-constraint.h \
|
backends/meta-pointer-constraint.h \
|
||||||
|
backends/meta-screen-cast-window.c \
|
||||||
|
backends/meta-screen-cast-window.h \
|
||||||
backends/meta-settings.c \
|
backends/meta-settings.c \
|
||||||
backends/meta-settings-private.h \
|
backends/meta-settings-private.h \
|
||||||
backends/meta-stage.h \
|
backends/meta-stage-private.h \
|
||||||
backends/meta-stage.c \
|
backends/meta-stage.c \
|
||||||
backends/meta-renderer.c \
|
backends/meta-renderer.c \
|
||||||
backends/meta-renderer.h \
|
backends/meta-renderer.h \
|
||||||
backends/meta-renderer-view.c \
|
backends/meta-renderer-view.c \
|
||||||
backends/meta-renderer-view.h \
|
backends/meta-renderer-view.h \
|
||||||
|
backends/meta-remote-access-controller.c \
|
||||||
|
backends/meta-remote-access-controller-private.h \
|
||||||
|
meta/meta-remote-access-controller.h \
|
||||||
backends/edid-parse.c \
|
backends/edid-parse.c \
|
||||||
backends/edid.h \
|
backends/edid.h \
|
||||||
|
backends/gsm-inhibitor-flag.h \
|
||||||
backends/x11/meta-backend-x11.c \
|
backends/x11/meta-backend-x11.c \
|
||||||
backends/x11/meta-backend-x11.h \
|
backends/x11/meta-backend-x11.h \
|
||||||
backends/x11/meta-barrier-x11.c \
|
backends/x11/meta-barrier-x11.c \
|
||||||
@ -175,6 +189,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
|
|||||||
backends/x11/meta-gpu-xrandr.h \
|
backends/x11/meta-gpu-xrandr.h \
|
||||||
backends/x11/cm/meta-backend-x11-cm.c \
|
backends/x11/cm/meta-backend-x11-cm.c \
|
||||||
backends/x11/cm/meta-backend-x11-cm.h \
|
backends/x11/cm/meta-backend-x11-cm.h \
|
||||||
|
backends/x11/cm/meta-cursor-sprite-xfixes.c \
|
||||||
|
backends/x11/cm/meta-cursor-sprite-xfixes.h \
|
||||||
backends/x11/cm/meta-renderer-x11-cm.c \
|
backends/x11/cm/meta-renderer-x11-cm.c \
|
||||||
backends/x11/cm/meta-renderer-x11-cm.h \
|
backends/x11/cm/meta-renderer-x11-cm.h \
|
||||||
backends/x11/nested/meta-backend-x11-nested.c \
|
backends/x11/nested/meta-backend-x11-nested.c \
|
||||||
@ -183,8 +199,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
|
|||||||
backends/x11/nested/meta-cursor-renderer-x11-nested.h \
|
backends/x11/nested/meta-cursor-renderer-x11-nested.h \
|
||||||
backends/x11/nested/meta-renderer-x11-nested.c \
|
backends/x11/nested/meta-renderer-x11-nested.c \
|
||||||
backends/x11/nested/meta-renderer-x11-nested.h \
|
backends/x11/nested/meta-renderer-x11-nested.h \
|
||||||
backends/x11/meta-idle-monitor-xsync.c \
|
|
||||||
backends/x11/meta-idle-monitor-xsync.h \
|
|
||||||
backends/x11/meta-input-settings-x11.c \
|
backends/x11/meta-input-settings-x11.c \
|
||||||
backends/x11/meta-input-settings-x11.h \
|
backends/x11/meta-input-settings-x11.h \
|
||||||
backends/x11/meta-monitor-manager-xrandr.c \
|
backends/x11/meta-monitor-manager-xrandr.c \
|
||||||
@ -247,7 +261,7 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
|
|||||||
compositor/meta-window-actor.c \
|
compositor/meta-window-actor.c \
|
||||||
compositor/meta-window-actor-private.h \
|
compositor/meta-window-actor-private.h \
|
||||||
compositor/meta-window-group.c \
|
compositor/meta-window-group.c \
|
||||||
compositor/meta-window-group.h \
|
compositor/meta-window-group-private.h \
|
||||||
compositor/meta-window-shape.c \
|
compositor/meta-window-shape.c \
|
||||||
compositor/region-utils.c \
|
compositor/region-utils.c \
|
||||||
compositor/region-utils.h \
|
compositor/region-utils.h \
|
||||||
@ -358,6 +372,10 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
|||||||
backends/meta-screen-cast-monitor-stream.h \
|
backends/meta-screen-cast-monitor-stream.h \
|
||||||
backends/meta-screen-cast-monitor-stream-src.c \
|
backends/meta-screen-cast-monitor-stream-src.c \
|
||||||
backends/meta-screen-cast-monitor-stream-src.h \
|
backends/meta-screen-cast-monitor-stream-src.h \
|
||||||
|
backends/meta-screen-cast-window-stream-src.c \
|
||||||
|
backends/meta-screen-cast-window-stream-src.h \
|
||||||
|
backends/meta-screen-cast-window-stream.c \
|
||||||
|
backends/meta-screen-cast-window-stream.h \
|
||||||
backends/meta-screen-cast-session.c \
|
backends/meta-screen-cast-session.c \
|
||||||
backends/meta-screen-cast-session.h \
|
backends/meta-screen-cast-session.h \
|
||||||
backends/meta-screen-cast-stream.c \
|
backends/meta-screen-cast-stream.c \
|
||||||
@ -371,6 +389,8 @@ if HAVE_WAYLAND
|
|||||||
libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
||||||
compositor/meta-surface-actor-wayland.c \
|
compositor/meta-surface-actor-wayland.c \
|
||||||
compositor/meta-surface-actor-wayland.h \
|
compositor/meta-surface-actor-wayland.h \
|
||||||
|
wayland/meta-cursor-sprite-wayland.c \
|
||||||
|
wayland/meta-cursor-sprite-wayland.h \
|
||||||
wayland/meta-wayland.c \
|
wayland/meta-wayland.c \
|
||||||
wayland/meta-wayland.h \
|
wayland/meta-wayland.h \
|
||||||
wayland/meta-wayland-private.h \
|
wayland/meta-wayland-private.h \
|
||||||
@ -432,10 +452,10 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
|||||||
wayland/meta-wayland-touch.h \
|
wayland/meta-wayland-touch.h \
|
||||||
wayland/meta-wayland-surface.c \
|
wayland/meta-wayland-surface.c \
|
||||||
wayland/meta-wayland-surface.h \
|
wayland/meta-wayland-surface.h \
|
||||||
wayland/meta-wayland-surface-role-cursor.c \
|
wayland/meta-wayland-cursor-surface.c \
|
||||||
wayland/meta-wayland-surface-role-cursor.h \
|
wayland/meta-wayland-cursor-surface.h \
|
||||||
wayland/meta-wayland-surface-role-tablet-cursor.c \
|
wayland/meta-wayland-tablet-cursor-surface.c \
|
||||||
wayland/meta-wayland-surface-role-tablet-cursor.h \
|
wayland/meta-wayland-tablet-cursor-surface.h \
|
||||||
wayland/meta-wayland-actor-surface.c \
|
wayland/meta-wayland-actor-surface.c \
|
||||||
wayland/meta-wayland-actor-surface.h \
|
wayland/meta-wayland-actor-surface.h \
|
||||||
wayland/meta-wayland-subsurface.c \
|
wayland/meta-wayland-subsurface.c \
|
||||||
@ -487,8 +507,6 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \
|
|||||||
backends/native/meta-default-modes.h \
|
backends/native/meta-default-modes.h \
|
||||||
backends/native/meta-gpu-kms.c \
|
backends/native/meta-gpu-kms.c \
|
||||||
backends/native/meta-gpu-kms.h \
|
backends/native/meta-gpu-kms.h \
|
||||||
backends/native/meta-idle-monitor-native.c \
|
|
||||||
backends/native/meta-idle-monitor-native.h \
|
|
||||||
backends/native/meta-input-settings-native.c \
|
backends/native/meta-input-settings-native.c \
|
||||||
backends/native/meta-input-settings-native.h \
|
backends/native/meta-input-settings-native.h \
|
||||||
backends/native/meta-monitor-manager-kms.c \
|
backends/native/meta-monitor-manager-kms.c \
|
||||||
@ -543,10 +561,13 @@ libmutterinclude_headers = \
|
|||||||
meta/meta-idle-monitor.h \
|
meta/meta-idle-monitor.h \
|
||||||
meta/meta-plugin.h \
|
meta/meta-plugin.h \
|
||||||
meta/meta-monitor-manager.h \
|
meta/meta-monitor-manager.h \
|
||||||
|
meta/meta-remote-access-controller.h \
|
||||||
meta/meta-settings.h \
|
meta/meta-settings.h \
|
||||||
meta/meta-shaped-texture.h \
|
meta/meta-shaped-texture.h \
|
||||||
meta/meta-shadow-factory.h \
|
meta/meta-shadow-factory.h \
|
||||||
|
meta/meta-stage.h \
|
||||||
meta/meta-window-actor.h \
|
meta/meta-window-actor.h \
|
||||||
|
meta/meta-window-group.h \
|
||||||
meta/meta-window-shape.h \
|
meta/meta-window-shape.h \
|
||||||
meta/prefs.h \
|
meta/prefs.h \
|
||||||
meta/screen.h \
|
meta/screen.h \
|
||||||
@ -761,3 +782,5 @@ endef
|
|||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) code $< $@
|
||||||
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
%-server-protocol.h : $(srcdir)/wayland/protocol/%.xml
|
||||||
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
|
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
|
||||||
|
%-server-protocol.h : $(WAYLAND_EGLSTREAM_DATADIR)/%.xml
|
||||||
|
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header $< $@
|
||||||
|
36
src/backends/gsm-inhibitor-flag.h
Normal file
36
src/backends/gsm-inhibitor-flag.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Red Hat, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GSM_INHIBITOR_FLAG_H__
|
||||||
|
#define __GSM_INHIBITOR_FLAG_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GSM_INHIBITOR_FLAG_LOGOUT = 1 << 0,
|
||||||
|
GSM_INHIBITOR_FLAG_SWITCH_USER = 1 << 1,
|
||||||
|
GSM_INHIBITOR_FLAG_SUSPEND = 1 << 2,
|
||||||
|
GSM_INHIBITOR_FLAG_IDLE = 1 << 3,
|
||||||
|
GSM_INHIBITOR_FLAG_AUTOMOUNT = 1 << 4
|
||||||
|
} GsmInhibitorFlag;
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSM_INHIBITOR_FLAG_H__ */
|
@ -59,8 +59,6 @@ struct _MetaBackendClass
|
|||||||
|
|
||||||
void (* post_init) (MetaBackend *backend);
|
void (* post_init) (MetaBackend *backend);
|
||||||
|
|
||||||
MetaIdleMonitor * (* create_idle_monitor) (MetaBackend *backend,
|
|
||||||
int device_id);
|
|
||||||
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend,
|
MetaMonitorManager * (* create_monitor_manager) (MetaBackend *backend,
|
||||||
GError **error);
|
GError **error);
|
||||||
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
|
MetaCursorRenderer * (* create_cursor_renderer) (MetaBackend *backend);
|
||||||
|
@ -34,11 +34,13 @@
|
|||||||
#include "meta-input-settings-private.h"
|
#include "meta-input-settings-private.h"
|
||||||
#include "backends/x11/meta-backend-x11.h"
|
#include "backends/x11/meta-backend-x11.h"
|
||||||
#include "meta-cursor-tracker-private.h"
|
#include "meta-cursor-tracker-private.h"
|
||||||
#include "meta-stage.h"
|
#include "meta-stage-private.h"
|
||||||
|
#include "meta-dbus-login1.h"
|
||||||
|
|
||||||
#ifdef HAVE_REMOTE_DESKTOP
|
#ifdef HAVE_REMOTE_DESKTOP
|
||||||
#include "backends/meta-dbus-session-watcher.h"
|
#include "backends/meta-dbus-session-watcher.h"
|
||||||
#include "backends/meta-screen-cast.h"
|
#include "backends/meta-screen-cast.h"
|
||||||
|
#include "backends/meta-remote-access-controller-private.h"
|
||||||
#include "backends/meta-remote-desktop.h"
|
#include "backends/meta-remote-desktop.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -58,7 +60,8 @@ enum
|
|||||||
KEYMAP_CHANGED,
|
KEYMAP_CHANGED,
|
||||||
KEYMAP_LAYOUT_GROUP_CHANGED,
|
KEYMAP_LAYOUT_GROUP_CHANGED,
|
||||||
LAST_DEVICE_CHANGED,
|
LAST_DEVICE_CHANGED,
|
||||||
|
SUSPENDING,
|
||||||
|
RESUMING,
|
||||||
N_SIGNALS
|
N_SIGNALS
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,6 +95,7 @@ struct _MetaBackendPrivate
|
|||||||
MetaEgl *egl;
|
MetaEgl *egl;
|
||||||
MetaSettings *settings;
|
MetaSettings *settings;
|
||||||
#ifdef HAVE_REMOTE_DESKTOP
|
#ifdef HAVE_REMOTE_DESKTOP
|
||||||
|
MetaRemoteAccessController *remote_access_controller;
|
||||||
MetaDbusSessionWatcher *dbus_session_watcher;
|
MetaDbusSessionWatcher *dbus_session_watcher;
|
||||||
MetaScreenCast *screen_cast;
|
MetaScreenCast *screen_cast;
|
||||||
MetaRemoteDesktop *remote_desktop;
|
MetaRemoteDesktop *remote_desktop;
|
||||||
@ -110,12 +114,23 @@ struct _MetaBackendPrivate
|
|||||||
|
|
||||||
MetaPointerConstraint *client_pointer_constraint;
|
MetaPointerConstraint *client_pointer_constraint;
|
||||||
MetaDnd *dnd;
|
MetaDnd *dnd;
|
||||||
|
|
||||||
|
UpClient *up_client;
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GDBusConnection *system_bus;
|
||||||
|
|
||||||
|
Login1Manager *logind_proxy;
|
||||||
|
int inhibit_sleep_fd;
|
||||||
};
|
};
|
||||||
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
typedef struct _MetaBackendPrivate MetaBackendPrivate;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
initable_iface_init (GInitableIface *initable_iface);
|
initable_iface_init (GInitableIface *initable_iface);
|
||||||
|
|
||||||
|
|
||||||
|
static void prepare_for_sleep_cb (MetaBackend *backend,
|
||||||
|
gboolean suspending);
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
|
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT,
|
||||||
G_ADD_PRIVATE (MetaBackend)
|
G_ADD_PRIVATE (MetaBackend)
|
||||||
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
||||||
@ -134,8 +149,14 @@ meta_backend_finalize (GObject *object)
|
|||||||
g_clear_object (&priv->remote_desktop);
|
g_clear_object (&priv->remote_desktop);
|
||||||
g_clear_object (&priv->screen_cast);
|
g_clear_object (&priv->screen_cast);
|
||||||
g_clear_object (&priv->dbus_session_watcher);
|
g_clear_object (&priv->dbus_session_watcher);
|
||||||
|
g_clear_object (&priv->remote_access_controller);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
g_object_unref (priv->up_client);
|
||||||
|
g_cancellable_cancel (priv->cancellable);
|
||||||
|
g_clear_object (&priv->cancellable);
|
||||||
|
g_clear_object (&priv->system_bus);
|
||||||
|
|
||||||
if (priv->device_update_idle_id)
|
if (priv->device_update_idle_id)
|
||||||
g_source_remove (priv->device_update_idle_id);
|
g_source_remove (priv->device_update_idle_id);
|
||||||
|
|
||||||
@ -158,7 +179,7 @@ meta_backend_sync_screen_size (MetaBackend *backend)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
center_pointer (MetaBackend *backend)
|
reset_pointer_position (MetaBackend *backend)
|
||||||
{
|
{
|
||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||||
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
||||||
@ -167,9 +188,11 @@ center_pointer (MetaBackend *backend)
|
|||||||
primary =
|
primary =
|
||||||
meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
||||||
|
|
||||||
|
/* Move the pointer out of the way to avoid hovering over reactive
|
||||||
|
* elements (e.g. users list at login) causing undesired behaviour. */
|
||||||
meta_backend_warp_pointer (backend,
|
meta_backend_warp_pointer (backend,
|
||||||
primary->rect.x + primary->rect.width / 2,
|
primary->rect.x + primary->rect.width * 0.9,
|
||||||
primary->rect.y + primary->rect.height / 2);
|
primary->rect.y + primary->rect.height * 0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -192,7 +215,7 @@ meta_backend_monitors_changed (MetaBackend *backend)
|
|||||||
!priv->is_pointer_position_initialized) &&
|
!priv->is_pointer_position_initialized) &&
|
||||||
!meta_monitor_manager_is_headless (monitor_manager))
|
!meta_monitor_manager_is_headless (monitor_manager))
|
||||||
{
|
{
|
||||||
center_pointer (backend);
|
reset_pointer_position (backend);
|
||||||
priv->is_pointer_position_initialized = TRUE;
|
priv->is_pointer_position_initialized = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,7 +245,9 @@ static MetaIdleMonitor *
|
|||||||
meta_backend_create_idle_monitor (MetaBackend *backend,
|
meta_backend_create_idle_monitor (MetaBackend *backend,
|
||||||
int device_id)
|
int device_id)
|
||||||
{
|
{
|
||||||
return META_BACKEND_GET_CLASS (backend)->create_idle_monitor (backend, device_id);
|
return g_object_new (META_TYPE_IDLE_MONITOR,
|
||||||
|
"device-id", device_id,
|
||||||
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -402,28 +427,6 @@ meta_backend_create_input_settings (MetaBackend *backend)
|
|||||||
return META_BACKEND_GET_CLASS (backend)->create_input_settings (backend);
|
return META_BACKEND_GET_CLASS (backend)->create_input_settings (backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_REMOTE_DESKTOP
|
|
||||||
static gboolean
|
|
||||||
is_screen_cast_enabled (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
||||||
|
|
||||||
return meta_settings_is_experimental_feature_enabled (
|
|
||||||
settings,
|
|
||||||
META_EXPERIMENTAL_FEATURE_SCREEN_CAST);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_remote_desktop_enabled (MetaBackend *backend)
|
|
||||||
{
|
|
||||||
MetaSettings *settings = meta_backend_get_settings (backend);
|
|
||||||
|
|
||||||
return meta_settings_is_experimental_feature_enabled (
|
|
||||||
settings,
|
|
||||||
META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_REMOTE_DESKTOP */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_backend_real_post_init (MetaBackend *backend)
|
meta_backend_real_post_init (MetaBackend *backend)
|
||||||
{
|
{
|
||||||
@ -456,16 +459,17 @@ meta_backend_real_post_init (MetaBackend *backend)
|
|||||||
priv->input_settings = meta_backend_create_input_settings (backend);
|
priv->input_settings = meta_backend_create_input_settings (backend);
|
||||||
|
|
||||||
#ifdef HAVE_REMOTE_DESKTOP
|
#ifdef HAVE_REMOTE_DESKTOP
|
||||||
|
priv->remote_access_controller =
|
||||||
|
g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER, NULL);
|
||||||
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
|
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
|
||||||
if (is_screen_cast_enabled (backend))
|
priv->screen_cast = meta_screen_cast_new (backend,
|
||||||
priv->screen_cast = meta_screen_cast_new (priv->dbus_session_watcher);
|
priv->dbus_session_watcher);
|
||||||
if (is_remote_desktop_enabled (backend))
|
|
||||||
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
|
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
|
||||||
#endif /* HAVE_REMOTE_DESKTOP */
|
#endif /* HAVE_REMOTE_DESKTOP */
|
||||||
|
|
||||||
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
|
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
|
||||||
{
|
{
|
||||||
center_pointer (backend);
|
reset_pointer_position (backend);
|
||||||
priv->is_pointer_position_initialized = TRUE;
|
priv->is_pointer_position_initialized = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -547,31 +551,25 @@ meta_backend_class_init (MetaBackendClass *klass)
|
|||||||
0,
|
0,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 1, G_TYPE_INT);
|
G_TYPE_NONE, 1, G_TYPE_INT);
|
||||||
|
signals[SUSPENDING] =
|
||||||
|
g_signal_new ("suspending",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
signals[RESUMING] =
|
||||||
|
g_signal_new ("resuming",
|
||||||
|
G_TYPE_FROM_CLASS (object_class),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS");
|
mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS");
|
||||||
stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0;
|
stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
experimental_features_changed (MetaSettings *settings,
|
|
||||||
MetaExperimentalFeature old_experimental_features,
|
|
||||||
MetaBackend *backend)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_REMOTE_DESKTOP
|
|
||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
|
||||||
|
|
||||||
if (is_screen_cast_enabled (backend) && !priv->screen_cast)
|
|
||||||
priv->screen_cast = meta_screen_cast_new (priv->dbus_session_watcher);
|
|
||||||
else if (!is_screen_cast_enabled (backend))
|
|
||||||
g_clear_object (&priv->screen_cast);
|
|
||||||
|
|
||||||
if (is_remote_desktop_enabled (backend) && !priv->remote_desktop)
|
|
||||||
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
|
|
||||||
else if (!is_remote_desktop_enabled (backend))
|
|
||||||
g_clear_object (&priv->remote_desktop);
|
|
||||||
#endif /* HAVE_REMOTE_DESKTOP */
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaMonitorManager *
|
static MetaMonitorManager *
|
||||||
meta_backend_create_monitor_manager (MetaBackend *backend,
|
meta_backend_create_monitor_manager (MetaBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -590,6 +588,119 @@ meta_backend_create_renderer (MetaBackend *backend,
|
|||||||
return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
|
return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lid_is_closed_changed_cb (UpClient *client,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
if (up_client_get_lid_is_closed (client))
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
inhibit_sleep (MetaBackend *backend)
|
||||||
|
{
|
||||||
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||||
|
g_autoptr (GVariant) fd_variant = NULL;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
if (priv->inhibit_sleep_fd >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!login1_manager_call_inhibit_sync (priv->logind_proxy,
|
||||||
|
"sleep",
|
||||||
|
"Display Server",
|
||||||
|
"Prepare for suspend",
|
||||||
|
"delay",
|
||||||
|
&fd_variant,
|
||||||
|
priv->cancellable,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
g_warning ("Failed to inhibit sleep: %s", error->message);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->inhibit_sleep_fd = g_variant_get_handle (fd_variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninhibit_sleep (MetaBackend *backend)
|
||||||
|
{
|
||||||
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||||
|
|
||||||
|
close (priv->inhibit_sleep_fd);
|
||||||
|
priv->inhibit_sleep_fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prepare_for_sleep_cb (MetaBackend *backend,
|
||||||
|
gboolean suspending)
|
||||||
|
{
|
||||||
|
if (suspending) {
|
||||||
|
g_signal_emit (backend, signals[SUSPENDING], 0);
|
||||||
|
uninhibit_sleep (backend);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
inhibit_sleep (backend);
|
||||||
|
g_signal_emit (backend, signals[RESUMING], 0);
|
||||||
|
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Login1Manager *
|
||||||
|
get_logind_proxy (GCancellable *cancellable,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
Login1Manager *proxy;
|
||||||
|
|
||||||
|
proxy =
|
||||||
|
login1_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||||
|
"org.freedesktop.login1",
|
||||||
|
"/org/freedesktop/login1",
|
||||||
|
cancellable, error);
|
||||||
|
if (!proxy)
|
||||||
|
g_prefix_error (error, "Could not get logind proxy: ");
|
||||||
|
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
system_bus_gotten_cb (GObject *object,
|
||||||
|
GAsyncResult *res,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = META_BACKEND (user_data);
|
||||||
|
MetaBackendPrivate *priv;
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
GDBusConnection *bus;
|
||||||
|
|
||||||
|
bus = g_bus_get_finish (res, NULL);
|
||||||
|
if (!bus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv = meta_backend_get_instance_private (user_data);
|
||||||
|
priv->system_bus = bus;
|
||||||
|
priv->logind_proxy = get_logind_proxy (priv->cancellable, &error);
|
||||||
|
priv->inhibit_sleep_fd = -1;
|
||||||
|
|
||||||
|
if (!priv->logind_proxy)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to get logind proxy: %s", error->message);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inhibit_sleep (backend);
|
||||||
|
g_signal_connect_object (priv->logind_proxy,
|
||||||
|
"prepare-for-sleep",
|
||||||
|
G_CALLBACK (prepare_for_sleep_cb),
|
||||||
|
user_data,
|
||||||
|
G_CONNECT_SWAPPED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_backend_initable_init (GInitable *initable,
|
meta_backend_initable_init (GInitable *initable,
|
||||||
GCancellable *cancellable,
|
GCancellable *cancellable,
|
||||||
@ -599,9 +710,6 @@ meta_backend_initable_init (GInitable *initable,
|
|||||||
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||||
|
|
||||||
priv->settings = meta_settings_new (backend);
|
priv->settings = meta_settings_new (backend);
|
||||||
g_signal_connect (priv->settings, "experimental-features-changed",
|
|
||||||
G_CALLBACK (experimental_features_changed),
|
|
||||||
backend);
|
|
||||||
|
|
||||||
priv->egl = g_object_new (META_TYPE_EGL, NULL);
|
priv->egl = g_object_new (META_TYPE_EGL, NULL);
|
||||||
|
|
||||||
@ -619,6 +727,16 @@ meta_backend_initable_init (GInitable *initable,
|
|||||||
|
|
||||||
priv->dnd = g_object_new (META_TYPE_DND, NULL);
|
priv->dnd = g_object_new (META_TYPE_DND, NULL);
|
||||||
|
|
||||||
|
priv->up_client = up_client_new ();
|
||||||
|
g_signal_connect (priv->up_client, "notify::lid-is-closed",
|
||||||
|
G_CALLBACK (lid_is_closed_changed_cb), NULL);
|
||||||
|
|
||||||
|
priv->cancellable = g_cancellable_new ();
|
||||||
|
g_bus_get (G_BUS_TYPE_SYSTEM,
|
||||||
|
priv->cancellable,
|
||||||
|
system_bus_gotten_cb,
|
||||||
|
backend);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,6 +861,24 @@ meta_backend_get_remote_desktop (MetaBackend *backend)
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_REMOTE_DESKTOP */
|
#endif /* HAVE_REMOTE_DESKTOP */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_backend_get_remote_access_controller:
|
||||||
|
* @backend: A #MetaBackend
|
||||||
|
*
|
||||||
|
* Return Value: (transfer none): The #MetaRemoteAccessController
|
||||||
|
*/
|
||||||
|
MetaRemoteAccessController *
|
||||||
|
meta_backend_get_remote_access_controller (MetaBackend *backend)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_REMOTE_DESKTOP
|
||||||
|
MetaBackendPrivate *priv = meta_backend_get_instance_private (backend);
|
||||||
|
|
||||||
|
return priv->remote_access_controller;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_backend_grab_device: (skip)
|
* meta_backend_grab_device: (skip)
|
||||||
*/
|
*/
|
||||||
|
@ -33,7 +33,10 @@
|
|||||||
#include <cogl/cogl.h>
|
#include <cogl/cogl.h>
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
#include "meta-stage.h"
|
#include "meta-stage-private.h"
|
||||||
|
|
||||||
|
G_DEFINE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor,
|
||||||
|
G_TYPE_OBJECT)
|
||||||
|
|
||||||
struct _MetaCursorRendererPrivate
|
struct _MetaCursorRendererPrivate
|
||||||
{
|
{
|
||||||
@ -44,6 +47,8 @@ struct _MetaCursorRendererPrivate
|
|||||||
MetaOverlay *stage_overlay;
|
MetaOverlay *stage_overlay;
|
||||||
gboolean handled_by_backend;
|
gboolean handled_by_backend;
|
||||||
guint post_paint_func_id;
|
guint post_paint_func_id;
|
||||||
|
|
||||||
|
GList *hw_cursor_inhibitors;
|
||||||
};
|
};
|
||||||
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
typedef struct _MetaCursorRendererPrivate MetaCursorRendererPrivate;
|
||||||
|
|
||||||
@ -55,6 +60,21 @@ static guint signals[LAST_SIGNAL];
|
|||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRenderer, meta_cursor_renderer, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_hw_cursor_inhibitor_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
|
||||||
|
MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
MetaHwCursorInhibitorInterface *iface =
|
||||||
|
META_HW_CURSOR_INHIBITOR_GET_IFACE (inhibitor);
|
||||||
|
|
||||||
|
return iface->is_cursor_sprite_inhibited (inhibitor, cursor_sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_hw_cursor_inhibitor_default_init (MetaHwCursorInhibitorInterface *iface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
@ -193,7 +213,7 @@ meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_cursor (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer);
|
||||||
@ -237,7 +257,7 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
|||||||
return;
|
return;
|
||||||
priv->displayed_cursor = cursor_sprite;
|
priv->displayed_cursor = cursor_sprite;
|
||||||
|
|
||||||
update_cursor (renderer, cursor_sprite);
|
meta_cursor_renderer_update_cursor (renderer, cursor_sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -246,7 +266,7 @@ meta_cursor_renderer_force_update (MetaCursorRenderer *renderer)
|
|||||||
MetaCursorRendererPrivate *priv =
|
MetaCursorRendererPrivate *priv =
|
||||||
meta_cursor_renderer_get_instance_private (renderer);
|
meta_cursor_renderer_get_instance_private (renderer);
|
||||||
|
|
||||||
update_cursor (renderer, priv->displayed_cursor);
|
meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -261,7 +281,19 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
|||||||
priv->current_x = x;
|
priv->current_x = x;
|
||||||
priv->current_y = y;
|
priv->current_y = y;
|
||||||
|
|
||||||
update_cursor (renderer, priv->displayed_cursor);
|
meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterPoint
|
||||||
|
meta_cursor_renderer_get_position (MetaCursorRenderer *renderer)
|
||||||
|
{
|
||||||
|
MetaCursorRendererPrivate *priv =
|
||||||
|
meta_cursor_renderer_get_instance_private (renderer);
|
||||||
|
|
||||||
|
return (ClutterPoint) {
|
||||||
|
.x = priv->current_x,
|
||||||
|
.y = priv->current_y
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaCursorSprite *
|
MetaCursorSprite *
|
||||||
@ -272,27 +304,44 @@ meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer)
|
|||||||
return priv->displayed_cursor;
|
return priv->displayed_cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void
|
void
|
||||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_add_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite,
|
MetaHwCursorInhibitor *inhibitor)
|
||||||
struct wl_resource *buffer)
|
|
||||||
{
|
{
|
||||||
|
MetaCursorRendererPrivate *priv =
|
||||||
|
meta_cursor_renderer_get_instance_private (renderer);
|
||||||
|
|
||||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
|
priv->hw_cursor_inhibitors = g_list_prepend (priv->hw_cursor_inhibitors,
|
||||||
|
inhibitor);
|
||||||
if (renderer_class->realize_cursor_from_wl_buffer)
|
|
||||||
renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_remove_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite,
|
MetaHwCursorInhibitor *inhibitor)
|
||||||
XcursorImage *xc_image)
|
|
||||||
{
|
{
|
||||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
|
MetaCursorRendererPrivate *priv =
|
||||||
|
meta_cursor_renderer_get_instance_private (renderer);
|
||||||
|
|
||||||
if (renderer_class->realize_cursor_from_xcursor)
|
priv->hw_cursor_inhibitors = g_list_remove (priv->hw_cursor_inhibitors,
|
||||||
renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image);
|
inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_cursor_renderer_is_hw_cursors_inhibited (MetaCursorRenderer *renderer,
|
||||||
|
MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
MetaCursorRendererPrivate *priv =
|
||||||
|
meta_cursor_renderer_get_instance_private (renderer);
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = priv->hw_cursor_inhibitors; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaHwCursorInhibitor *inhibitor = l->data;
|
||||||
|
|
||||||
|
if (meta_hw_cursor_inhibitor_is_cursor_sprite_inhibited (inhibitor,
|
||||||
|
cursor_sprite))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,22 @@
|
|||||||
#define META_CURSOR_RENDERER_H
|
#define META_CURSOR_RENDERER_H
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
#include <wayland-server.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <meta/screen.h>
|
#include <meta/screen.h>
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
|
|
||||||
|
#define META_TYPE_HW_CURSOR_INHIBITOR (meta_hw_cursor_inhibitor_get_type ())
|
||||||
|
G_DECLARE_INTERFACE (MetaHwCursorInhibitor, meta_hw_cursor_inhibitor,
|
||||||
|
META, HW_CURSOR_INHIBITOR, GObject)
|
||||||
|
|
||||||
|
struct _MetaHwCursorInhibitorInterface
|
||||||
|
{
|
||||||
|
GTypeInterface parent_iface;
|
||||||
|
|
||||||
|
gboolean (* is_cursor_sprite_inhibited) (MetaHwCursorInhibitor *inhibitor,
|
||||||
|
MetaCursorSprite *cursor_sprite);
|
||||||
|
};
|
||||||
|
|
||||||
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
|
#define META_TYPE_CURSOR_RENDERER (meta_cursor_renderer_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer,
|
G_DECLARE_DERIVABLE_TYPE (MetaCursorRenderer, meta_cursor_renderer,
|
||||||
META, CURSOR_RENDERER, GObject);
|
META, CURSOR_RENDERER, GObject);
|
||||||
@ -44,14 +52,6 @@ struct _MetaCursorRendererClass
|
|||||||
|
|
||||||
gboolean (* update_cursor) (MetaCursorRenderer *renderer,
|
gboolean (* update_cursor) (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite);
|
MetaCursorSprite *cursor_sprite);
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer,
|
|
||||||
MetaCursorSprite *cursor_sprite,
|
|
||||||
struct wl_resource *buffer);
|
|
||||||
#endif
|
|
||||||
void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer,
|
|
||||||
MetaCursorSprite *cursor_sprite,
|
|
||||||
XcursorImage *xc_image);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MetaCursorRenderer * meta_cursor_renderer_new (void);
|
MetaCursorRenderer * meta_cursor_renderer_new (void);
|
||||||
@ -62,22 +62,22 @@ void meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer,
|
|||||||
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
void meta_cursor_renderer_set_position (MetaCursorRenderer *renderer,
|
||||||
float x,
|
float x,
|
||||||
float y);
|
float y);
|
||||||
|
ClutterPoint meta_cursor_renderer_get_position (MetaCursorRenderer *renderer);
|
||||||
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
|
void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
|
||||||
|
|
||||||
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||||
|
|
||||||
ClutterRect meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
|
void meta_cursor_renderer_add_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||||
|
MetaHwCursorInhibitor *inhibitor);
|
||||||
|
|
||||||
|
void meta_cursor_renderer_remove_hw_cursor_inhibitor (MetaCursorRenderer *renderer,
|
||||||
|
MetaHwCursorInhibitor *inhibitor);
|
||||||
|
|
||||||
|
gboolean meta_cursor_renderer_is_hw_cursors_inhibited (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite);
|
MetaCursorSprite *cursor_sprite);
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
ClutterRect meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer,
|
||||||
void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
MetaCursorSprite *cursor_sprite);
|
||||||
MetaCursorSprite *cursor_sprite,
|
|
||||||
struct wl_resource *buffer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
|
||||||
MetaCursorSprite *cursor_sprite,
|
|
||||||
XcursorImage *xc_image);
|
|
||||||
|
|
||||||
void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite);
|
MetaCursorSprite *cursor_sprite);
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
#include "meta-cursor-renderer.h"
|
#include "meta-cursor-renderer.h"
|
||||||
|
#include "backends/x11/cm/meta-cursor-sprite-xfixes.h"
|
||||||
|
|
||||||
struct _MetaCursorTracker {
|
struct _MetaCursorTracker {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
@ -46,7 +47,7 @@ struct _MetaCursorTracker {
|
|||||||
MetaCursorSprite *root_cursor;
|
MetaCursorSprite *root_cursor;
|
||||||
|
|
||||||
/* The cursor from the X11 server. */
|
/* The cursor from the X11 server. */
|
||||||
MetaCursorSprite *xfixes_cursor;
|
MetaCursorSpriteXfixes *xfixes_cursor;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaCursorTrackerClass {
|
struct _MetaCursorTrackerClass {
|
||||||
|
@ -40,14 +40,15 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
#include <gdk/gdkx.h>
|
#include <gdk/gdkx.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
|
|
||||||
#include "meta-backend-private.h"
|
#include "meta-backend-private.h"
|
||||||
|
#include "backends/x11/cm/meta-cursor-sprite-xfixes.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CURSOR_CHANGED,
|
CURSOR_CHANGED,
|
||||||
|
CURSOR_MOVED,
|
||||||
LAST_SIGNAL
|
LAST_SIGNAL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,11 +118,15 @@ change_cursor_renderer (MetaCursorTracker *tracker)
|
|||||||
static void
|
static void
|
||||||
sync_cursor (MetaCursorTracker *tracker)
|
sync_cursor (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
if (update_displayed_cursor (tracker))
|
gboolean cursor_changed = FALSE;
|
||||||
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
|
||||||
|
cursor_changed = update_displayed_cursor (tracker);
|
||||||
|
|
||||||
if (update_effective_cursor (tracker))
|
if (update_effective_cursor (tracker))
|
||||||
change_cursor_renderer (tracker);
|
change_cursor_renderer (tracker);
|
||||||
|
|
||||||
|
if (cursor_changed)
|
||||||
|
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -158,6 +163,15 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
|
|||||||
0,
|
0,
|
||||||
NULL, NULL, NULL,
|
NULL, NULL, NULL,
|
||||||
G_TYPE_NONE, 0);
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
signals[CURSOR_MOVED] = g_signal_new ("cursor-moved",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 2,
|
||||||
|
G_TYPE_FLOAT,
|
||||||
|
G_TYPE_FLOAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,75 +232,14 @@ static void
|
|||||||
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
ensure_xfixes_cursor (MetaCursorTracker *tracker)
|
||||||
{
|
{
|
||||||
MetaDisplay *display = meta_get_display ();
|
MetaDisplay *display = meta_get_display ();
|
||||||
XFixesCursorImage *cursor_image;
|
g_autoptr (GError) error = NULL;
|
||||||
CoglTexture2D *sprite;
|
|
||||||
guint8 *cursor_data;
|
|
||||||
gboolean free_cursor_data;
|
|
||||||
CoglContext *ctx;
|
|
||||||
CoglError *error = NULL;
|
|
||||||
|
|
||||||
if (tracker->xfixes_cursor)
|
if (tracker->xfixes_cursor)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cursor_image = XFixesGetCursorImage (display->xdisplay);
|
tracker->xfixes_cursor = meta_cursor_sprite_xfixes_new (display, &error);
|
||||||
if (!cursor_image)
|
if (!tracker->xfixes_cursor)
|
||||||
return;
|
g_warning ("Failed to create XFIXES cursor: %s", error->message);
|
||||||
|
|
||||||
/* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit
|
|
||||||
* quantities as arrays of long; we need to convert on 64 bit */
|
|
||||||
if (sizeof(long) == 4)
|
|
||||||
{
|
|
||||||
cursor_data = (guint8 *)cursor_image->pixels;
|
|
||||||
free_cursor_data = FALSE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
guint32 *cursor_words;
|
|
||||||
gulong *p;
|
|
||||||
guint32 *q;
|
|
||||||
|
|
||||||
cursor_words = g_new (guint32, cursor_image->width * cursor_image->height);
|
|
||||||
cursor_data = (guint8 *)cursor_words;
|
|
||||||
|
|
||||||
p = cursor_image->pixels;
|
|
||||||
q = cursor_words;
|
|
||||||
for (j = 0; j < cursor_image->height; j++)
|
|
||||||
for (i = 0; i < cursor_image->width; i++)
|
|
||||||
*(q++) = *(p++);
|
|
||||||
|
|
||||||
free_cursor_data = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
||||||
sprite = cogl_texture_2d_new_from_data (ctx,
|
|
||||||
cursor_image->width,
|
|
||||||
cursor_image->height,
|
|
||||||
CLUTTER_CAIRO_FORMAT_ARGB32,
|
|
||||||
cursor_image->width * 4, /* stride */
|
|
||||||
cursor_data,
|
|
||||||
&error);
|
|
||||||
|
|
||||||
if (free_cursor_data)
|
|
||||||
g_free (cursor_data);
|
|
||||||
|
|
||||||
if (error != NULL)
|
|
||||||
{
|
|
||||||
meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message);
|
|
||||||
cogl_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sprite != NULL)
|
|
||||||
{
|
|
||||||
MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new ();
|
|
||||||
meta_cursor_sprite_set_texture (cursor_sprite,
|
|
||||||
COGL_TEXTURE (sprite),
|
|
||||||
cursor_image->xhot,
|
|
||||||
cursor_image->yhot);
|
|
||||||
cogl_object_unref (sprite);
|
|
||||||
tracker->xfixes_cursor = cursor_sprite;
|
|
||||||
}
|
|
||||||
XFree (cursor_image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,7 +261,7 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ensure_xfixes_cursor (tracker);
|
ensure_xfixes_cursor (tracker);
|
||||||
cursor_sprite = tracker->xfixes_cursor;
|
cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor_sprite)
|
if (cursor_sprite)
|
||||||
@ -345,7 +298,7 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ensure_xfixes_cursor (tracker);
|
ensure_xfixes_cursor (tracker);
|
||||||
cursor_sprite = tracker->xfixes_cursor;
|
cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor_sprite)
|
if (cursor_sprite)
|
||||||
@ -395,6 +348,8 @@ meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
|
|||||||
g_assert (meta_is_wayland_compositor ());
|
g_assert (meta_is_wayland_compositor ());
|
||||||
|
|
||||||
meta_cursor_renderer_set_position (cursor_renderer, new_x, new_y);
|
meta_cursor_renderer_set_position (cursor_renderer, new_x, new_y);
|
||||||
|
|
||||||
|
g_signal_emit (tracker, signals[CURSOR_MOVED], 0, new_x, new_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -23,19 +23,12 @@
|
|||||||
|
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
|
|
||||||
#include <meta/errors.h>
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "cogl/cogl.h"
|
||||||
|
#include "meta/common.h"
|
||||||
|
|
||||||
#include "display-private.h"
|
enum
|
||||||
#include "screen-private.h"
|
{
|
||||||
#include "meta-backend-private.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PREPARE_AT,
|
PREPARE_AT,
|
||||||
TEXTURE_CHANGED,
|
TEXTURE_CHANGED,
|
||||||
|
|
||||||
@ -44,316 +37,148 @@ enum {
|
|||||||
|
|
||||||
static guint signals[LAST_SIGNAL];
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
struct _MetaCursorSprite
|
typedef struct _MetaCursorSpritePrivate
|
||||||
{
|
{
|
||||||
GObject parent;
|
GObject parent;
|
||||||
|
|
||||||
MetaCursor cursor;
|
|
||||||
|
|
||||||
CoglTexture2D *texture;
|
CoglTexture2D *texture;
|
||||||
float texture_scale;
|
float texture_scale;
|
||||||
int hot_x, hot_y;
|
int hot_x, hot_y;
|
||||||
|
} MetaCursorSpritePrivate;
|
||||||
|
|
||||||
int current_frame;
|
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCursorSprite,
|
||||||
XcursorImages *xcursor_images;
|
meta_cursor_sprite,
|
||||||
|
G_TYPE_OBJECT)
|
||||||
int theme_scale;
|
|
||||||
gboolean theme_dirty;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
translate_meta_cursor (MetaCursor cursor)
|
|
||||||
{
|
|
||||||
switch (cursor)
|
|
||||||
{
|
|
||||||
case META_CURSOR_DEFAULT:
|
|
||||||
return "left_ptr";
|
|
||||||
case META_CURSOR_NORTH_RESIZE:
|
|
||||||
return "top_side";
|
|
||||||
case META_CURSOR_SOUTH_RESIZE:
|
|
||||||
return "bottom_side";
|
|
||||||
case META_CURSOR_WEST_RESIZE:
|
|
||||||
return "left_side";
|
|
||||||
case META_CURSOR_EAST_RESIZE:
|
|
||||||
return "right_side";
|
|
||||||
case META_CURSOR_SE_RESIZE:
|
|
||||||
return "bottom_right_corner";
|
|
||||||
case META_CURSOR_SW_RESIZE:
|
|
||||||
return "bottom_left_corner";
|
|
||||||
case META_CURSOR_NE_RESIZE:
|
|
||||||
return "top_right_corner";
|
|
||||||
case META_CURSOR_NW_RESIZE:
|
|
||||||
return "top_left_corner";
|
|
||||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
|
||||||
return "fleur";
|
|
||||||
case META_CURSOR_BUSY:
|
|
||||||
return "watch";
|
|
||||||
case META_CURSOR_DND_IN_DRAG:
|
|
||||||
return "dnd-none";
|
|
||||||
case META_CURSOR_DND_MOVE:
|
|
||||||
return "dnd-move";
|
|
||||||
case META_CURSOR_DND_COPY:
|
|
||||||
return "dnd-copy";
|
|
||||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
|
||||||
return "dnd-none";
|
|
||||||
case META_CURSOR_POINTING_HAND:
|
|
||||||
return "hand2";
|
|
||||||
case META_CURSOR_CROSSHAIR:
|
|
||||||
return "crosshair";
|
|
||||||
case META_CURSOR_IBEAM:
|
|
||||||
return "xterm";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor
|
|
||||||
meta_cursor_create_x_cursor (Display *xdisplay,
|
|
||||||
MetaCursor cursor)
|
|
||||||
{
|
|
||||||
return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
|
|
||||||
}
|
|
||||||
|
|
||||||
static XcursorImages *
|
|
||||||
load_cursor_on_client (MetaCursor cursor, int scale)
|
|
||||||
{
|
|
||||||
return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
|
|
||||||
meta_prefs_get_cursor_theme (),
|
|
||||||
meta_prefs_get_cursor_size () * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self,
|
|
||||||
XcursorImage *xc_image)
|
|
||||||
{
|
|
||||||
MetaBackend *meta_backend = meta_get_backend ();
|
|
||||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
|
||||||
uint width, height, rowstride;
|
|
||||||
CoglPixelFormat cogl_format;
|
|
||||||
ClutterBackend *clutter_backend;
|
|
||||||
CoglContext *cogl_context;
|
|
||||||
CoglTexture2D *texture;
|
|
||||||
CoglError *error = NULL;
|
|
||||||
|
|
||||||
g_assert (self->texture == NULL);
|
|
||||||
|
|
||||||
width = xc_image->width;
|
|
||||||
height = xc_image->height;
|
|
||||||
rowstride = width * 4;
|
|
||||||
|
|
||||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
|
|
||||||
#else
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
clutter_backend = clutter_get_default_backend ();
|
|
||||||
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
|
||||||
texture = cogl_texture_2d_new_from_data (cogl_context,
|
|
||||||
width, height,
|
|
||||||
cogl_format,
|
|
||||||
rowstride,
|
|
||||||
(uint8_t *) xc_image->pixels,
|
|
||||||
&error);
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
meta_warning ("Failed to allocate cursor texture: %s\n", error->message);
|
|
||||||
cogl_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_cursor_sprite_set_texture (self, COGL_TEXTURE (texture),
|
|
||||||
xc_image->xhot, xc_image->yhot);
|
|
||||||
|
|
||||||
if (texture)
|
|
||||||
cogl_object_unref (texture);
|
|
||||||
|
|
||||||
meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
|
|
||||||
}
|
|
||||||
|
|
||||||
static XcursorImage *
|
|
||||||
meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *self)
|
|
||||||
{
|
|
||||||
return self->xcursor_images->images[self->current_frame];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
|
|
||||||
{
|
|
||||||
XcursorImage *image;
|
|
||||||
|
|
||||||
if (!meta_cursor_sprite_is_animated (self))
|
|
||||||
return;
|
|
||||||
|
|
||||||
self->current_frame++;
|
|
||||||
|
|
||||||
if (self->current_frame >= self->xcursor_images->nimage)
|
|
||||||
self->current_frame = 0;
|
|
||||||
|
|
||||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->texture, cogl_object_unref);
|
|
||||||
meta_cursor_sprite_load_from_xcursor_image (self, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
guint
|
|
||||||
meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self)
|
|
||||||
{
|
|
||||||
if (!meta_cursor_sprite_is_animated (self))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return self->xcursor_images->images[self->current_frame]->delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_cursor_sprite_is_animated (MetaCursorSprite *self)
|
meta_cursor_sprite_is_animated (MetaCursorSprite *sprite)
|
||||||
{
|
{
|
||||||
return (self->xcursor_images &&
|
MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
|
||||||
self->xcursor_images->nimage > 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaCursorSprite *
|
if (klass->is_animated)
|
||||||
meta_cursor_sprite_new (void)
|
return klass->is_animated (sprite);
|
||||||
{
|
else
|
||||||
return g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_sprite_load_from_theme (MetaCursorSprite *self)
|
|
||||||
{
|
|
||||||
XcursorImage *image;
|
|
||||||
|
|
||||||
g_assert (self->cursor != META_CURSOR_NONE);
|
|
||||||
|
|
||||||
self->theme_dirty = FALSE;
|
|
||||||
|
|
||||||
/* We might be reloading with a different scale. If so clear the old data. */
|
|
||||||
if (self->xcursor_images)
|
|
||||||
{
|
|
||||||
g_clear_pointer (&self->texture, cogl_object_unref);
|
|
||||||
XcursorImagesDestroy (self->xcursor_images);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->current_frame = 0;
|
|
||||||
self->xcursor_images = load_cursor_on_client (self->cursor,
|
|
||||||
self->theme_scale);
|
|
||||||
if (!self->xcursor_images)
|
|
||||||
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
|
|
||||||
|
|
||||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
|
||||||
meta_cursor_sprite_load_from_xcursor_image (self, image);
|
|
||||||
}
|
|
||||||
|
|
||||||
MetaCursorSprite *
|
|
||||||
meta_cursor_sprite_from_theme (MetaCursor cursor)
|
|
||||||
{
|
|
||||||
MetaCursorSprite *self;
|
|
||||||
|
|
||||||
self = meta_cursor_sprite_new ();
|
|
||||||
|
|
||||||
self->cursor = cursor;
|
|
||||||
self->theme_dirty = TRUE;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_sprite_set_texture (MetaCursorSprite *self,
|
meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite)
|
||||||
|
{
|
||||||
|
return META_CURSOR_SPRITE_GET_CLASS (sprite)->tick_frame (sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite)
|
||||||
|
{
|
||||||
|
return META_CURSOR_SPRITE_GET_CLASS (sprite)->get_current_frame_time (sprite);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite)
|
||||||
|
{
|
||||||
|
MetaCursorSpritePrivate *priv =
|
||||||
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
|
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_cursor_sprite_set_texture (MetaCursorSprite *sprite,
|
||||||
CoglTexture *texture,
|
CoglTexture *texture,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y)
|
int hot_y)
|
||||||
{
|
{
|
||||||
if (self->texture == COGL_TEXTURE_2D (texture) &&
|
MetaCursorSpritePrivate *priv =
|
||||||
self->hot_x == hot_x &&
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
self->hot_y == hot_y)
|
|
||||||
|
if (priv->texture == COGL_TEXTURE_2D (texture) &&
|
||||||
|
priv->hot_x == hot_x &&
|
||||||
|
priv->hot_y == hot_y)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
g_clear_pointer (&self->texture, cogl_object_unref);
|
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||||
if (texture)
|
if (texture)
|
||||||
self->texture = cogl_object_ref (texture);
|
priv->texture = cogl_object_ref (texture);
|
||||||
self->hot_x = hot_x;
|
priv->hot_x = hot_x;
|
||||||
self->hot_y = hot_y;
|
priv->hot_y = hot_y;
|
||||||
|
|
||||||
g_signal_emit (self, signals[TEXTURE_CHANGED], 0);
|
g_signal_emit (sprite, signals[TEXTURE_CHANGED], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
|
meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite,
|
||||||
float scale)
|
float scale)
|
||||||
{
|
{
|
||||||
self->texture_scale = scale;
|
MetaCursorSpritePrivate *priv =
|
||||||
}
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
void
|
priv->texture_scale = scale;
|
||||||
meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
|
|
||||||
int theme_scale)
|
|
||||||
{
|
|
||||||
if (self->theme_scale != theme_scale)
|
|
||||||
self->theme_dirty = TRUE;
|
|
||||||
self->theme_scale = theme_scale;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CoglTexture *
|
CoglTexture *
|
||||||
meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self)
|
meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite)
|
||||||
{
|
{
|
||||||
return COGL_TEXTURE (self->texture);
|
MetaCursorSpritePrivate *priv =
|
||||||
}
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
MetaCursor
|
return COGL_TEXTURE (priv->texture);
|
||||||
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
|
|
||||||
{
|
|
||||||
return self->cursor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
|
meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite,
|
||||||
int *hot_x,
|
int *hot_x,
|
||||||
int *hot_y)
|
int *hot_y)
|
||||||
{
|
{
|
||||||
*hot_x = self->hot_x;
|
MetaCursorSpritePrivate *priv =
|
||||||
*hot_y = self->hot_y;
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
|
*hot_x = priv->hot_x;
|
||||||
|
*hot_y = priv->hot_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self)
|
meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite)
|
||||||
{
|
{
|
||||||
return self->texture_scale;
|
MetaCursorSpritePrivate *priv =
|
||||||
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
|
return priv->texture_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
|
meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
|
||||||
int x,
|
int x,
|
||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
g_signal_emit (self, signals[PREPARE_AT], 0, x, y);
|
g_signal_emit (sprite, signals[PREPARE_AT], 0, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_cursor_sprite_realize_texture (MetaCursorSprite *self)
|
meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite)
|
||||||
{
|
{
|
||||||
if (self->theme_dirty)
|
MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
|
||||||
meta_cursor_sprite_load_from_theme (self);
|
|
||||||
|
if (klass->realize_texture)
|
||||||
|
klass->realize_texture (sprite);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_sprite_init (MetaCursorSprite *self)
|
meta_cursor_sprite_init (MetaCursorSprite *sprite)
|
||||||
{
|
{
|
||||||
self->texture_scale = 1.0f;
|
MetaCursorSpritePrivate *priv =
|
||||||
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
|
priv->texture_scale = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_sprite_finalize (GObject *object)
|
meta_cursor_sprite_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaCursorSprite *self = META_CURSOR_SPRITE (object);
|
MetaCursorSprite *sprite = META_CURSOR_SPRITE (object);
|
||||||
|
MetaCursorSpritePrivate *priv =
|
||||||
|
meta_cursor_sprite_get_instance_private (sprite);
|
||||||
|
|
||||||
if (self->xcursor_images)
|
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||||
XcursorImagesDestroy (self->xcursor_images);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->texture, cogl_object_unref);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
@ -25,51 +25,50 @@
|
|||||||
#include <meta/common.h>
|
#include <meta/common.h>
|
||||||
#include <meta/boxes.h>
|
#include <meta/boxes.h>
|
||||||
|
|
||||||
typedef struct _MetaCursorSprite MetaCursorSprite;
|
|
||||||
|
|
||||||
#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
|
#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (MetaCursorSprite,
|
G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite,
|
||||||
meta_cursor_sprite,
|
meta_cursor_sprite,
|
||||||
META, CURSOR_SPRITE,
|
META, CURSOR_SPRITE,
|
||||||
GObject);
|
GObject)
|
||||||
|
|
||||||
MetaCursorSprite * meta_cursor_sprite_new (void);
|
struct _MetaCursorSpriteClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
MetaCursorSprite * meta_cursor_sprite_from_theme (MetaCursor cursor);
|
void (* realize_texture) (MetaCursorSprite *sprite);
|
||||||
|
gboolean (* is_animated) (MetaCursorSprite *sprite);
|
||||||
|
void (* tick_frame) (MetaCursorSprite *sprite);
|
||||||
|
unsigned int (* get_current_frame_time) (MetaCursorSprite *sprite);
|
||||||
|
};
|
||||||
|
|
||||||
|
void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
|
||||||
void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self,
|
|
||||||
int scale);
|
|
||||||
|
|
||||||
MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self);
|
|
||||||
|
|
||||||
Cursor meta_cursor_create_x_cursor (Display *xdisplay,
|
|
||||||
MetaCursor cursor);
|
|
||||||
|
|
||||||
void meta_cursor_sprite_prepare_at (MetaCursorSprite *self,
|
|
||||||
int x,
|
int x,
|
||||||
int y);
|
int y);
|
||||||
|
|
||||||
void meta_cursor_sprite_realize_texture (MetaCursorSprite *self);
|
void meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
void meta_cursor_sprite_set_texture (MetaCursorSprite *self,
|
void meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
|
void meta_cursor_sprite_set_texture (MetaCursorSprite *sprite,
|
||||||
CoglTexture *texture,
|
CoglTexture *texture,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y);
|
int hot_y);
|
||||||
|
|
||||||
void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self,
|
void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite,
|
||||||
float scale);
|
float scale);
|
||||||
|
|
||||||
CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self);
|
CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
|
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite,
|
||||||
int *hot_x,
|
int *hot_x,
|
||||||
int *hot_y);
|
int *hot_y);
|
||||||
|
|
||||||
float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self);
|
float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self);
|
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *sprite);
|
||||||
void meta_cursor_sprite_tick_frame (MetaCursorSprite *self);
|
|
||||||
guint meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self);
|
void meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
|
unsigned int meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite);
|
||||||
|
|
||||||
#endif /* META_CURSOR_H */
|
#endif /* META_CURSOR_H */
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "meta-idle-monitor-dbus.h"
|
#include "meta-idle-monitor-dbus.h"
|
||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
|
#include <backends/meta-idle-monitor-private.h>
|
||||||
#include "meta-dbus-idle-monitor.h"
|
#include "meta-dbus-idle-monitor.h"
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <clutter/clutter.h>
|
||||||
@ -43,6 +44,26 @@ handle_get_idletime (MetaDBusIdleMonitor *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
handle_reset_idletime (MetaDBusIdleMonitor *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
if (!g_getenv ("MUTTER_DEBUG_RESET_IDLETIME"))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error_literal (invocation,
|
||||||
|
G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_UNKNOWN_METHOD,
|
||||||
|
"No such method");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ());
|
||||||
|
meta_dbus_idle_monitor_complete_reset_idletime (skeleton, invocation);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
MetaDBusIdleMonitor *dbus_monitor;
|
MetaDBusIdleMonitor *dbus_monitor;
|
||||||
MetaIdleMonitor *monitor;
|
MetaIdleMonitor *monitor;
|
||||||
@ -173,6 +194,8 @@ create_monitor_skeleton (GDBusObjectManagerServer *manager,
|
|||||||
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
|
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
|
||||||
g_signal_connect_object (skeleton, "handle-remove-watch",
|
g_signal_connect_object (skeleton, "handle-remove-watch",
|
||||||
G_CALLBACK (handle_remove_watch), monitor, 0);
|
G_CALLBACK (handle_remove_watch), monitor, 0);
|
||||||
|
g_signal_connect_object (skeleton, "handle-reset-idletime",
|
||||||
|
G_CALLBACK (handle_reset_idletime), monitor, 0);
|
||||||
g_signal_connect_object (skeleton, "handle-get-idletime",
|
g_signal_connect_object (skeleton, "handle-get-idletime",
|
||||||
G_CALLBACK (handle_get_idletime), monitor, 0);
|
G_CALLBACK (handle_get_idletime), monitor, 0);
|
||||||
|
|
||||||
|
@ -26,9 +26,6 @@
|
|||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
#include <X11/extensions/sync.h>
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
MetaIdleMonitor *monitor;
|
MetaIdleMonitor *monitor;
|
||||||
@ -38,28 +35,26 @@ typedef struct
|
|||||||
GDestroyNotify notify;
|
GDestroyNotify notify;
|
||||||
guint64 timeout_msec;
|
guint64 timeout_msec;
|
||||||
int idle_source_id;
|
int idle_source_id;
|
||||||
|
GSource *timeout_source;
|
||||||
} MetaIdleMonitorWatch;
|
} MetaIdleMonitorWatch;
|
||||||
|
|
||||||
struct _MetaIdleMonitor
|
struct _MetaIdleMonitor
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GDBusProxy *session_proxy;
|
||||||
|
gboolean inhibited;
|
||||||
GHashTable *watches;
|
GHashTable *watches;
|
||||||
int device_id;
|
int device_id;
|
||||||
|
guint64 last_event_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MetaIdleMonitorClass
|
struct _MetaIdleMonitorClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
gint64 (*get_idletime) (MetaIdleMonitor *monitor);
|
|
||||||
MetaIdleMonitorWatch * (*make_watch) (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
|
void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch);
|
||||||
|
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_PRIVATE_H */
|
#endif /* META_IDLE_MONITOR_PRIVATE_H */
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include <meta/util.h>
|
#include <meta/util.h>
|
||||||
#include <meta/main.h>
|
#include <meta/main.h>
|
||||||
#include <meta/meta-idle-monitor.h>
|
#include <meta/meta-idle-monitor.h>
|
||||||
|
#include "gsm-inhibitor-flag.h"
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
#include "meta-idle-monitor-dbus.h"
|
#include "meta-idle-monitor-dbus.h"
|
||||||
#include "meta-backend-private.h"
|
#include "meta-backend-private.h"
|
||||||
@ -87,6 +88,7 @@ meta_idle_monitor_dispose (GObject *object)
|
|||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
|
||||||
|
|
||||||
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
|
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
|
||||||
|
g_clear_object (&monitor->session_proxy);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
|
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
@ -151,9 +153,118 @@ meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
|
|||||||
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
|
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_watch (gpointer data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) data;
|
||||||
|
MetaIdleMonitor *monitor = watch->monitor;
|
||||||
|
|
||||||
|
g_object_ref (monitor);
|
||||||
|
|
||||||
|
if (watch->idle_source_id)
|
||||||
|
{
|
||||||
|
g_source_remove (watch->idle_source_id);
|
||||||
|
watch->idle_source_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (watch->notify != NULL)
|
||||||
|
watch->notify (watch->user_data);
|
||||||
|
|
||||||
|
if (watch->timeout_source != NULL)
|
||||||
|
g_source_destroy (watch->timeout_source);
|
||||||
|
|
||||||
|
g_object_unref (monitor);
|
||||||
|
g_slice_free (MetaIdleMonitorWatch, watch);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_inhibited_watch (gpointer key,
|
||||||
|
gpointer value,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor = user_data;
|
||||||
|
MetaIdleMonitorWatch *watch = value;
|
||||||
|
|
||||||
|
if (!watch->timeout_source)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (monitor->inhibited)
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (watch->timeout_source, -1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (watch->timeout_source,
|
||||||
|
monitor->last_event_time +
|
||||||
|
watch->timeout_msec * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_inhibited (MetaIdleMonitor *monitor,
|
||||||
|
gboolean inhibited)
|
||||||
|
{
|
||||||
|
if (inhibited == monitor->inhibited)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_hash_table_foreach (monitor->watches,
|
||||||
|
update_inhibited_watch,
|
||||||
|
monitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_idle_monitor_inhibited_actions_changed (GDBusProxy *session,
|
||||||
|
GVariant *changed,
|
||||||
|
char **invalidated,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitor *monitor = user_data;
|
||||||
|
GVariant *v;
|
||||||
|
|
||||||
|
v = g_variant_lookup_value (changed, "InhibitedActions", G_VARIANT_TYPE_UINT32);
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
gboolean inhibited;
|
||||||
|
|
||||||
|
inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
|
||||||
|
g_variant_unref (v);
|
||||||
|
|
||||||
|
if (!inhibited)
|
||||||
|
monitor->last_event_time = g_get_monotonic_time ();
|
||||||
|
update_inhibited (monitor, inhibited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||||
{
|
{
|
||||||
|
GVariant *v;
|
||||||
|
|
||||||
|
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
|
||||||
|
monitor->last_event_time = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
/* Monitor inhibitors */
|
||||||
|
monitor->session_proxy =
|
||||||
|
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
|
||||||
|
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||||
|
NULL,
|
||||||
|
"org.gnome.SessionManager",
|
||||||
|
"/org/gnome/SessionManager",
|
||||||
|
"org.gnome.SessionManager",
|
||||||
|
NULL,
|
||||||
|
NULL);
|
||||||
|
if (!monitor->session_proxy)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_signal_connect (monitor->session_proxy, "g-properties-changed",
|
||||||
|
G_CALLBACK (meta_idle_monitor_inhibited_actions_changed),
|
||||||
|
monitor);
|
||||||
|
|
||||||
|
v = g_dbus_proxy_get_cached_property (monitor->session_proxy,
|
||||||
|
"InhibitedActions");
|
||||||
|
monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
|
||||||
|
g_variant_unref (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -185,6 +296,36 @@ meta_idle_monitor_get_for_device (int device_id)
|
|||||||
return meta_backend_get_idle_monitor (backend, device_id);
|
return meta_backend_get_idle_monitor (backend, device_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static guint32
|
||||||
|
get_next_watch_serial (void)
|
||||||
|
{
|
||||||
|
static guint32 serial = 0;
|
||||||
|
|
||||||
|
g_atomic_int_inc (&serial);
|
||||||
|
|
||||||
|
return serial;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
idle_monitor_dispatch_timeout (GSource *source,
|
||||||
|
GSourceFunc callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data;
|
||||||
|
|
||||||
|
_meta_idle_monitor_watch_fire (watch);
|
||||||
|
g_source_set_ready_time (watch->timeout_source, -1);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GSourceFuncs idle_monitor_source_funcs = {
|
||||||
|
.prepare = NULL,
|
||||||
|
.check = NULL,
|
||||||
|
.dispatch = idle_monitor_dispatch_timeout,
|
||||||
|
.finalize = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
static MetaIdleMonitorWatch *
|
||||||
make_watch (MetaIdleMonitor *monitor,
|
make_watch (MetaIdleMonitor *monitor,
|
||||||
guint64 timeout_msec,
|
guint64 timeout_msec,
|
||||||
@ -194,11 +335,32 @@ make_watch (MetaIdleMonitor *monitor,
|
|||||||
{
|
{
|
||||||
MetaIdleMonitorWatch *watch;
|
MetaIdleMonitorWatch *watch;
|
||||||
|
|
||||||
watch = META_IDLE_MONITOR_GET_CLASS (monitor)->make_watch (monitor,
|
watch = g_slice_new0 (MetaIdleMonitorWatch);
|
||||||
timeout_msec,
|
|
||||||
callback,
|
watch->monitor = monitor;
|
||||||
user_data,
|
watch->id = get_next_watch_serial ();
|
||||||
notify);
|
watch->callback = callback;
|
||||||
|
watch->user_data = user_data;
|
||||||
|
watch->notify = notify;
|
||||||
|
watch->timeout_msec = timeout_msec;
|
||||||
|
|
||||||
|
if (timeout_msec != 0)
|
||||||
|
{
|
||||||
|
GSource *source = g_source_new (&idle_monitor_source_funcs,
|
||||||
|
sizeof (GSource));
|
||||||
|
|
||||||
|
g_source_set_callback (source, NULL, watch, NULL);
|
||||||
|
if (!monitor->inhibited)
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (source,
|
||||||
|
monitor->last_event_time +
|
||||||
|
timeout_msec * 1000);
|
||||||
|
}
|
||||||
|
g_source_attach (source, NULL);
|
||||||
|
g_source_unref (source);
|
||||||
|
|
||||||
|
watch->timeout_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
g_hash_table_insert (monitor->watches,
|
g_hash_table_insert (monitor->watches,
|
||||||
GUINT_TO_POINTER (watch->id),
|
GUINT_TO_POINTER (watch->id),
|
||||||
@ -314,5 +476,39 @@ meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
|
|||||||
gint64
|
gint64
|
||||||
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
|
||||||
{
|
{
|
||||||
return META_IDLE_MONITOR_GET_CLASS (monitor)->get_idletime (monitor);
|
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
|
||||||
|
{
|
||||||
|
GList *node, *watch_ids;
|
||||||
|
|
||||||
|
monitor->last_event_time = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
watch_ids = g_hash_table_get_keys (monitor->watches);
|
||||||
|
|
||||||
|
for (node = watch_ids; node != NULL; node = node->next)
|
||||||
|
{
|
||||||
|
guint watch_id = GPOINTER_TO_UINT (node->data);
|
||||||
|
MetaIdleMonitorWatch *watch;
|
||||||
|
|
||||||
|
watch = g_hash_table_lookup (monitor->watches,
|
||||||
|
GUINT_TO_POINTER (watch_id));
|
||||||
|
if (!watch)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (watch->timeout_msec == 0)
|
||||||
|
{
|
||||||
|
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_source_set_ready_time (watch->timeout_source,
|
||||||
|
monitor->last_event_time +
|
||||||
|
watch->timeout_msec * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (watch_ids);
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1088,7 @@ meta_input_settings_changed_cb (GSettings *settings,
|
|||||||
update_device_natural_scroll (input_settings, NULL);
|
update_device_natural_scroll (input_settings, NULL);
|
||||||
else if (strcmp (key, "tap-to-click") == 0)
|
else if (strcmp (key, "tap-to-click") == 0)
|
||||||
update_touchpad_tap_enabled (input_settings, NULL);
|
update_touchpad_tap_enabled (input_settings, NULL);
|
||||||
else if (strcmp (key, "tap-and_drag") == 0)
|
else if (strcmp (key, "tap-and-drag") == 0)
|
||||||
update_touchpad_tap_and_drag_enabled (input_settings, NULL);
|
update_touchpad_tap_and_drag_enabled (input_settings, NULL);
|
||||||
else if (strcmp(key, "disable-while-typing") == 0)
|
else if (strcmp(key, "disable-while-typing") == 0)
|
||||||
update_touchpad_disable_while_typing (input_settings, NULL);
|
update_touchpad_disable_while_typing (input_settings, NULL);
|
||||||
|
@ -100,11 +100,12 @@ static MetaMonitorTransform
|
|||||||
derive_monitor_transform (MetaMonitor *monitor)
|
derive_monitor_transform (MetaMonitor *monitor)
|
||||||
{
|
{
|
||||||
MetaOutput *main_output;
|
MetaOutput *main_output;
|
||||||
|
MetaMonitorTransform transform;
|
||||||
|
|
||||||
main_output = meta_monitor_get_main_output (monitor);
|
main_output = meta_monitor_get_main_output (monitor);
|
||||||
|
transform = meta_output_get_assigned_crtc (main_output)->transform;
|
||||||
|
|
||||||
return meta_monitor_crtc_to_logical_transform (monitor,
|
return meta_monitor_crtc_to_logical_transform (monitor, transform);
|
||||||
main_output->crtc->transform);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaLogicalMonitor *
|
MetaLogicalMonitor *
|
||||||
@ -145,7 +146,7 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
|
|||||||
|
|
||||||
is_presentation = logical_monitor->is_presentation;
|
is_presentation = logical_monitor->is_presentation;
|
||||||
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
|
logical_monitor->monitors = g_list_append (logical_monitor->monitors,
|
||||||
monitor);
|
g_object_ref (monitor));
|
||||||
|
|
||||||
for (l = logical_monitor->monitors; l; l = l->next)
|
for (l = logical_monitor->monitors; l; l = l->next)
|
||||||
{
|
{
|
||||||
@ -157,10 +158,12 @@ meta_logical_monitor_add_monitor (MetaLogicalMonitor *logical_monitor,
|
|||||||
for (l_output = outputs; l_output; l_output = l_output->next)
|
for (l_output = outputs; l_output; l_output = l_output->next)
|
||||||
{
|
{
|
||||||
MetaOutput *output = l_output->data;
|
MetaOutput *output = l_output->data;
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
is_presentation = is_presentation && output->is_presentation;
|
is_presentation = is_presentation && output->is_presentation;
|
||||||
if (output->crtc)
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
output->crtc->logical_monitor = logical_monitor;
|
if (crtc)
|
||||||
|
crtc->logical_monitor = logical_monitor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +223,7 @@ foreach_crtc (MetaMonitor *monitor,
|
|||||||
ForeachCrtcData *data = user_data;
|
ForeachCrtcData *data = user_data;
|
||||||
|
|
||||||
data->func (data->logical_monitor,
|
data->func (data->logical_monitor,
|
||||||
monitor_crtc_mode->output->crtc,
|
meta_output_get_assigned_crtc (monitor_crtc_mode->output),
|
||||||
data->user_data);
|
data->user_data);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -254,13 +257,17 @@ meta_logical_monitor_init (MetaLogicalMonitor *logical_monitor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_logical_monitor_finalize (GObject *object)
|
meta_logical_monitor_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object);
|
MetaLogicalMonitor *logical_monitor = META_LOGICAL_MONITOR (object);
|
||||||
|
|
||||||
g_list_free (logical_monitor->monitors);
|
if (logical_monitor->monitors)
|
||||||
|
{
|
||||||
|
g_list_free_full (logical_monitor->monitors, g_object_unref);
|
||||||
|
logical_monitor->monitors = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_logical_monitor_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_logical_monitor_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -268,7 +275,7 @@ meta_logical_monitor_class_init (MetaLogicalMonitorClass *klass)
|
|||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
object_class->finalize = meta_logical_monitor_finalize;
|
object_class->dispose = meta_logical_monitor_dispose;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -486,7 +486,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|||||||
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
|
output = ((MetaOutput**)crtc_info->outputs->pdata)[j];
|
||||||
|
|
||||||
output->is_dirty = TRUE;
|
output->is_dirty = TRUE;
|
||||||
output->crtc = crtc;
|
meta_output_assign_crtc (output, crtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,7 +531,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->crtc = NULL;
|
meta_output_unassign_crtc (output);
|
||||||
output->is_primary = FALSE;
|
output->is_primary = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,6 +89,9 @@ static gboolean
|
|||||||
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
|
meta_monitor_manager_is_config_complete (MetaMonitorManager *manager,
|
||||||
MetaMonitorsConfig *config);
|
MetaMonitorsConfig *config);
|
||||||
|
|
||||||
|
static MetaMonitor *
|
||||||
|
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager);
|
||||||
|
|
||||||
MetaBackend *
|
MetaBackend *
|
||||||
meta_monitor_manager_get_backend (MetaMonitorManager *manager)
|
meta_monitor_manager_get_backend (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
@ -198,13 +201,17 @@ calculate_monitor_scale (MetaMonitorManager *manager,
|
|||||||
static float
|
static float
|
||||||
derive_calculated_global_scale (MetaMonitorManager *manager)
|
derive_calculated_global_scale (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
MetaMonitor *primary_monitor;
|
MetaMonitor *monitor = NULL;
|
||||||
|
|
||||||
primary_monitor = meta_monitor_manager_get_primary_monitor (manager);
|
monitor = meta_monitor_manager_get_primary_monitor (manager);
|
||||||
if (!primary_monitor)
|
|
||||||
|
if (!monitor || !meta_monitor_is_active (monitor))
|
||||||
|
monitor = meta_monitor_manager_get_active_monitor (manager);
|
||||||
|
|
||||||
|
if (!monitor)
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
|
||||||
return calculate_monitor_scale (manager, primary_monitor);
|
return calculate_monitor_scale (manager, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float
|
static float
|
||||||
@ -1032,12 +1039,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
NULL /* properties */);
|
NULL /* properties */);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (l = combined_outputs; l; l = l->next)
|
for (l = combined_outputs, i = 0; l; l = l->next, i++)
|
||||||
{
|
{
|
||||||
MetaOutput *output = l->data;
|
MetaOutput *output = l->data;
|
||||||
GVariantBuilder crtcs, modes, clones, properties;
|
GVariantBuilder crtcs, modes, clones, properties;
|
||||||
GBytes *edid;
|
GBytes *edid;
|
||||||
char *edid_file;
|
char *edid_file;
|
||||||
|
MetaCrtc *crtc;
|
||||||
int crtc_index;
|
int crtc_index;
|
||||||
|
|
||||||
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
|
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
|
||||||
@ -1131,8 +1139,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
output->tile_info.tile_h));
|
output->tile_info.tile_h));
|
||||||
}
|
}
|
||||||
|
|
||||||
crtc_index = output->crtc ? g_list_index (combined_crtcs, output->crtc)
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
: -1;
|
crtc_index = crtc ? g_list_index (combined_crtcs, crtc) : -1;
|
||||||
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
|
||||||
i, /* ID */
|
i, /* ID */
|
||||||
(gint64)output->winsys_id,
|
(gint64)output->winsys_id,
|
||||||
@ -2382,6 +2390,12 @@ meta_monitor_manager_get_laptop_panel (MetaMonitorManager *manager)
|
|||||||
return find_monitor (manager, meta_monitor_is_laptop_panel);
|
return find_monitor (manager, meta_monitor_is_laptop_panel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaMonitor *
|
||||||
|
meta_monitor_manager_get_active_monitor (MetaMonitorManager *manager)
|
||||||
|
{
|
||||||
|
return find_monitor (manager, meta_monitor_is_active);
|
||||||
|
}
|
||||||
|
|
||||||
MetaMonitor *
|
MetaMonitor *
|
||||||
meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager,
|
meta_monitor_manager_get_monitor_from_connector (MetaMonitorManager *manager,
|
||||||
const char *connector)
|
const char *connector)
|
||||||
@ -2894,11 +2908,7 @@ meta_monitor_manager_get_monitor_for_connector (MetaMonitorManager *manager,
|
|||||||
|
|
||||||
if (meta_monitor_is_active (monitor) &&
|
if (meta_monitor_is_active (monitor) &&
|
||||||
g_str_equal (connector, meta_monitor_get_connector (monitor)))
|
g_str_equal (connector, meta_monitor_get_connector (monitor)))
|
||||||
{
|
return meta_monitor_get_logical_monitor (monitor)->number;
|
||||||
MetaOutput *main_output = meta_monitor_get_main_output (monitor);
|
|
||||||
|
|
||||||
return main_output->crtc->logical_monitor->number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -203,11 +203,9 @@ meta_monitor_get_main_output (MetaMonitor *monitor)
|
|||||||
gboolean
|
gboolean
|
||||||
meta_monitor_is_active (MetaMonitor *monitor)
|
meta_monitor_is_active (MetaMonitor *monitor)
|
||||||
{
|
{
|
||||||
MetaOutput *output;
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
||||||
|
|
||||||
output = meta_monitor_get_main_output (monitor);
|
return !!priv->current_mode;
|
||||||
|
|
||||||
return output->crtc && output->crtc->current_mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -385,6 +383,21 @@ meta_monitor_crtc_to_logical_transform (MetaMonitor *monitor,
|
|||||||
return new_transform;
|
return new_transform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_monitor_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MetaMonitor *monitor = META_MONITOR (object);
|
||||||
|
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
||||||
|
|
||||||
|
if (priv->outputs)
|
||||||
|
{
|
||||||
|
g_list_free_full (priv->outputs, g_object_unref);
|
||||||
|
priv->outputs = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_monitor_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_finalize (GObject *object)
|
meta_monitor_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@ -393,7 +406,6 @@ meta_monitor_finalize (GObject *object)
|
|||||||
|
|
||||||
g_hash_table_destroy (priv->mode_ids);
|
g_hash_table_destroy (priv->mode_ids);
|
||||||
g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
|
g_list_free_full (priv->modes, (GDestroyNotify) meta_monitor_mode_free);
|
||||||
g_clear_pointer (&priv->outputs, g_list_free);
|
|
||||||
meta_monitor_spec_free (priv->spec);
|
meta_monitor_spec_free (priv->spec);
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_monitor_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_monitor_parent_class)->finalize (object);
|
||||||
@ -412,6 +424,7 @@ meta_monitor_class_init (MetaMonitorClass *klass)
|
|||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = meta_monitor_dispose;
|
||||||
object_class->finalize = meta_monitor_finalize;
|
object_class->finalize = meta_monitor_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,6 +506,7 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
|
|||||||
for (i = 0; i < output->n_modes; i++)
|
for (i = 0; i < output->n_modes; i++)
|
||||||
{
|
{
|
||||||
MetaCrtcMode *crtc_mode = output->modes[i];
|
MetaCrtcMode *crtc_mode = output->modes[i];
|
||||||
|
MetaCrtc *crtc;
|
||||||
MetaMonitorMode *mode;
|
MetaMonitorMode *mode;
|
||||||
gboolean replace;
|
gboolean replace;
|
||||||
|
|
||||||
@ -526,7 +540,9 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
|
|||||||
|
|
||||||
if (crtc_mode == output->preferred_mode)
|
if (crtc_mode == output->preferred_mode)
|
||||||
monitor_priv->preferred_mode = mode;
|
monitor_priv->preferred_mode = mode;
|
||||||
if (output->crtc && crtc_mode == output->crtc->current_mode)
|
|
||||||
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
if (crtc && crtc_mode == crtc->current_mode)
|
||||||
monitor_priv->current_mode = mode;
|
monitor_priv->current_mode = mode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -545,7 +561,7 @@ meta_monitor_normal_new (MetaGpu *gpu,
|
|||||||
|
|
||||||
monitor_priv->gpu = gpu;
|
monitor_priv->gpu = gpu;
|
||||||
|
|
||||||
monitor_priv->outputs = g_list_append (NULL, output);
|
monitor_priv->outputs = g_list_append (NULL, g_object_ref (output));
|
||||||
monitor_priv->winsys_id = output->winsys_id;
|
monitor_priv->winsys_id = output->winsys_id;
|
||||||
meta_monitor_generate_spec (monitor);
|
meta_monitor_generate_spec (monitor);
|
||||||
|
|
||||||
@ -568,13 +584,15 @@ meta_monitor_normal_derive_layout (MetaMonitor *monitor,
|
|||||||
MetaRectangle *layout)
|
MetaRectangle *layout)
|
||||||
{
|
{
|
||||||
MetaOutput *output;
|
MetaOutput *output;
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
output = meta_monitor_get_main_output (monitor);
|
output = meta_monitor_get_main_output (monitor);
|
||||||
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
*layout = (MetaRectangle) {
|
*layout = (MetaRectangle) {
|
||||||
.x = output->crtc->rect.x,
|
.x = crtc->rect.x,
|
||||||
.y = output->crtc->rect.y,
|
.y = crtc->rect.y,
|
||||||
.width = output->crtc->rect.width,
|
.width = crtc->rect.width,
|
||||||
.height = output->crtc->rect.height
|
.height = crtc->rect.height
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,7 +676,8 @@ add_tiled_monitor_outputs (MetaGpu *gpu,
|
|||||||
g_warn_if_fail (output->subpixel_order ==
|
g_warn_if_fail (output->subpixel_order ==
|
||||||
monitor_tiled->origin_output->subpixel_order);
|
monitor_tiled->origin_output->subpixel_order);
|
||||||
|
|
||||||
monitor_priv->outputs = g_list_append (monitor_priv->outputs, output);
|
monitor_priv->outputs = g_list_append (monitor_priv->outputs,
|
||||||
|
g_object_ref (output));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,12 +783,13 @@ is_monitor_mode_assigned (MetaMonitor *monitor,
|
|||||||
{
|
{
|
||||||
MetaOutput *output = l->data;
|
MetaOutput *output = l->data;
|
||||||
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
|
MetaMonitorCrtcMode *monitor_crtc_mode = &mode->crtc_modes[i];
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
if (monitor_crtc_mode->crtc_mode &&
|
if (monitor_crtc_mode->crtc_mode &&
|
||||||
(!output->crtc ||
|
(!crtc || crtc->current_mode != monitor_crtc_mode->crtc_mode))
|
||||||
output->crtc->current_mode != monitor_crtc_mode->crtc_mode))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
else if (!monitor_crtc_mode->crtc_mode && output->crtc)
|
else if (!monitor_crtc_mode->crtc_mode && crtc)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1217,14 +1237,16 @@ meta_monitor_tiled_derive_layout (MetaMonitor *monitor,
|
|||||||
for (l = monitor_priv->outputs; l; l = l->next)
|
for (l = monitor_priv->outputs; l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaOutput *output = l->data;
|
MetaOutput *output = l->data;
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
if (!output->crtc)
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
if (!crtc)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
min_x = MIN (output->crtc->rect.x, min_x);
|
min_x = MIN (crtc->rect.x, min_x);
|
||||||
min_y = MIN (output->crtc->rect.y, min_y);
|
min_y = MIN (crtc->rect.y, min_y);
|
||||||
max_x = MAX (output->crtc->rect.x + output->crtc->rect.width, max_x);
|
max_x = MAX (crtc->rect.x + crtc->rect.width, max_x);
|
||||||
max_y = MAX (output->crtc->rect.y + output->crtc->rect.height, max_y);
|
max_y = MAX (crtc->rect.y + crtc->rect.height, max_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
*layout = (MetaRectangle) {
|
*layout = (MetaRectangle) {
|
||||||
@ -1318,10 +1340,14 @@ meta_monitor_get_spec (MetaMonitor *monitor)
|
|||||||
MetaLogicalMonitor *
|
MetaLogicalMonitor *
|
||||||
meta_monitor_get_logical_monitor (MetaMonitor *monitor)
|
meta_monitor_get_logical_monitor (MetaMonitor *monitor)
|
||||||
{
|
{
|
||||||
MetaOutput *output = meta_monitor_get_main_output (monitor);
|
MetaOutput *output;
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
if (output->crtc)
|
output = meta_monitor_get_main_output (monitor);
|
||||||
return output->crtc->logical_monitor;
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
|
||||||
|
if (crtc)
|
||||||
|
return crtc->logical_monitor;
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1381,6 +1407,18 @@ meta_monitor_get_current_mode (MetaMonitor *monitor)
|
|||||||
return priv->current_mode;
|
return priv->current_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_current_mode_known (MetaMonitor *monitor)
|
||||||
|
{
|
||||||
|
MetaOutput *output;
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
|
output = meta_monitor_get_main_output (monitor);
|
||||||
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
|
||||||
|
return meta_monitor_is_active (monitor) == (crtc && crtc->current_mode);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
||||||
{
|
{
|
||||||
@ -1400,6 +1438,8 @@ meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->current_mode = current_mode;
|
priv->current_mode = current_mode;
|
||||||
|
|
||||||
|
g_warn_if_fail (is_current_mode_known (monitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -21,7 +21,13 @@
|
|||||||
|
|
||||||
#include "backends/meta-output.h"
|
#include "backends/meta-output.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaOutput, meta_output, G_TYPE_OBJECT)
|
typedef struct _MetaOutputPrivate
|
||||||
|
{
|
||||||
|
/* The CRTC driving this output, NULL if the output is not enabled */
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
} MetaOutputPrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT)
|
||||||
|
|
||||||
MetaGpu *
|
MetaGpu *
|
||||||
meta_output_get_gpu (MetaOutput *output)
|
meta_output_get_gpu (MetaOutput *output)
|
||||||
@ -29,6 +35,44 @@ meta_output_get_gpu (MetaOutput *output)
|
|||||||
return output->gpu;
|
return output->gpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_output_assign_crtc (MetaOutput *output,
|
||||||
|
MetaCrtc *crtc)
|
||||||
|
{
|
||||||
|
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
|
||||||
|
|
||||||
|
g_assert (crtc);
|
||||||
|
|
||||||
|
g_set_object (&priv->crtc, crtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_output_unassign_crtc (MetaOutput *output)
|
||||||
|
{
|
||||||
|
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
|
||||||
|
|
||||||
|
g_clear_object (&priv->crtc);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaCrtc *
|
||||||
|
meta_output_get_assigned_crtc (MetaOutput *output)
|
||||||
|
{
|
||||||
|
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
|
||||||
|
|
||||||
|
return priv->crtc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_output_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
MetaOutput *output = META_OUTPUT (object);
|
||||||
|
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
|
||||||
|
|
||||||
|
g_clear_object (&priv->crtc);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_output_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_output_finalize (GObject *object)
|
meta_output_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@ -58,5 +102,6 @@ meta_output_class_init (MetaOutputClass *klass)
|
|||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->dispose = meta_output_dispose;
|
||||||
object_class->finalize = meta_output_finalize;
|
object_class->finalize = meta_output_finalize;
|
||||||
}
|
}
|
||||||
|
@ -64,9 +64,6 @@ struct _MetaOutput
|
|||||||
|
|
||||||
MetaGpu *gpu;
|
MetaGpu *gpu;
|
||||||
|
|
||||||
/* The CRTC driving this output, NULL if the output is not enabled */
|
|
||||||
MetaCrtc *crtc;
|
|
||||||
|
|
||||||
/* The low-level ID of this output, used to apply back configuration */
|
/* The low-level ID of this output, used to apply back configuration */
|
||||||
glong winsys_id;
|
glong winsys_id;
|
||||||
char *name;
|
char *name;
|
||||||
@ -122,4 +119,11 @@ G_DECLARE_FINAL_TYPE (MetaOutput, meta_output, META, OUTPUT, GObject)
|
|||||||
|
|
||||||
MetaGpu * meta_output_get_gpu (MetaOutput *output);
|
MetaGpu * meta_output_get_gpu (MetaOutput *output);
|
||||||
|
|
||||||
|
void meta_output_assign_crtc (MetaOutput *output,
|
||||||
|
MetaCrtc *crtc);
|
||||||
|
|
||||||
|
void meta_output_unassign_crtc (MetaOutput *output);
|
||||||
|
|
||||||
|
MetaCrtc * meta_output_get_assigned_crtc (MetaOutput *output);
|
||||||
|
|
||||||
#endif /* META_OUTPUT_H */
|
#endif /* META_OUTPUT_H */
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Wayland Support
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
*
|
|
||||||
* Copyright (C) 2016 Red Hat, Inc.
|
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@ -17,26 +15,17 @@
|
|||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#ifndef META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
|
||||||
#include "meta-wayland-surface-role-tablet-cursor.h"
|
#define META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
|
||||||
|
|
||||||
struct _MetaWaylandSurfaceRoleTabletCursor
|
#include "meta/meta-remote-access-controller.h"
|
||||||
{
|
|
||||||
MetaWaylandSurfaceRoleCursor parent;
|
|
||||||
};
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaWaylandSurfaceRoleTabletCursor,
|
void meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller,
|
||||||
meta_wayland_surface_role_tablet_cursor,
|
MetaRemoteAccessHandle *handle);
|
||||||
META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR)
|
|
||||||
|
|
||||||
static void
|
void meta_remote_access_handle_notify_stopped (MetaRemoteAccessHandle *handle);
|
||||||
meta_wayland_surface_role_tablet_cursor_init (MetaWaylandSurfaceRoleTabletCursor *role)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
#endif /* META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H */
|
||||||
meta_wayland_surface_role_tablet_cursor_class_init (MetaWaylandSurfaceRoleTabletCursorClass *klass)
|
|
||||||
{
|
|
||||||
}
|
|
130
src/backends/meta-remote-access-controller.c
Normal file
130
src/backends/meta-remote-access-controller.c
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "backends/meta-remote-access-controller-private.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
HANDLE_STOPPED,
|
||||||
|
|
||||||
|
N_HANDLE_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static int handle_signals[N_HANDLE_SIGNALS];
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
CONTROLLER_NEW_HANDLE,
|
||||||
|
|
||||||
|
N_CONTROLLER_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static int controller_signals[N_CONTROLLER_SIGNALS];
|
||||||
|
|
||||||
|
typedef struct _MetaRemoteAccessHandlePrivate
|
||||||
|
{
|
||||||
|
gboolean has_stopped;
|
||||||
|
} MetaRemoteAccessHandlePrivate;
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaRemoteAccessHandle,
|
||||||
|
meta_remote_access_handle,
|
||||||
|
G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
struct _MetaRemoteAccessController
|
||||||
|
{
|
||||||
|
GObject parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaRemoteAccessController,
|
||||||
|
meta_remote_access_controller,
|
||||||
|
G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_remote_access_handle_stop:
|
||||||
|
* @handle: A #MetaRemoteAccessHandle
|
||||||
|
*
|
||||||
|
* Stop the associated remote access session.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_remote_access_handle_stop (MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandlePrivate *priv =
|
||||||
|
meta_remote_access_handle_get_instance_private (handle);
|
||||||
|
|
||||||
|
if (priv->has_stopped)
|
||||||
|
return;
|
||||||
|
|
||||||
|
META_REMOTE_ACCESS_HANDLE_GET_CLASS (handle)->stop (handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_remote_access_handle_notify_stopped (MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandlePrivate *priv =
|
||||||
|
meta_remote_access_handle_get_instance_private (handle);
|
||||||
|
|
||||||
|
priv->has_stopped = TRUE;
|
||||||
|
g_signal_emit (handle, handle_signals[HANDLE_STOPPED], 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller,
|
||||||
|
MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
g_signal_emit (controller, controller_signals[CONTROLLER_NEW_HANDLE], 0,
|
||||||
|
handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_access_handle_init (MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_access_handle_class_init (MetaRemoteAccessHandleClass *klass)
|
||||||
|
{
|
||||||
|
handle_signals[HANDLE_STOPPED] =
|
||||||
|
g_signal_new ("stopped",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_access_controller_init (MetaRemoteAccessController *controller)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_access_controller_class_init (MetaRemoteAccessControllerClass *klass)
|
||||||
|
{
|
||||||
|
controller_signals[CONTROLLER_NEW_HANDLE] =
|
||||||
|
g_signal_new ("new-handle",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
META_TYPE_REMOTE_ACCESS_HANDLE);
|
||||||
|
}
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "backends/meta-dbus-session-watcher.h"
|
#include "backends/meta-dbus-session-watcher.h"
|
||||||
#include "backends/meta-screen-cast-session.h"
|
#include "backends/meta-screen-cast-session.h"
|
||||||
|
#include "backends/meta-remote-access-controller-private.h"
|
||||||
#include "backends/native/meta-backend-native.h"
|
#include "backends/native/meta-backend-native.h"
|
||||||
#include "backends/x11/meta-backend-x11.h"
|
#include "backends/x11/meta-backend-x11.h"
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
@ -59,6 +60,8 @@ struct _MetaRemoteDesktopSession
|
|||||||
ClutterVirtualInputDevice *virtual_pointer;
|
ClutterVirtualInputDevice *virtual_pointer;
|
||||||
ClutterVirtualInputDevice *virtual_keyboard;
|
ClutterVirtualInputDevice *virtual_keyboard;
|
||||||
ClutterVirtualInputDevice *virtual_touchscreen;
|
ClutterVirtualInputDevice *virtual_touchscreen;
|
||||||
|
|
||||||
|
MetaRemoteDesktopSessionHandle *handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -75,12 +78,41 @@ G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktopSession,
|
|||||||
G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION,
|
G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION,
|
||||||
meta_dbus_session_init_iface))
|
meta_dbus_session_init_iface))
|
||||||
|
|
||||||
|
struct _MetaRemoteDesktopSessionHandle
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandle parent;
|
||||||
|
|
||||||
|
MetaRemoteDesktopSession *session;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaRemoteDesktopSessionHandle,
|
||||||
|
meta_remote_desktop_session_handle,
|
||||||
|
META_TYPE_REMOTE_ACCESS_HANDLE)
|
||||||
|
|
||||||
|
static MetaRemoteDesktopSessionHandle *
|
||||||
|
meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session);
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_remote_desktop_session_is_running (MetaRemoteDesktopSession *session)
|
meta_remote_desktop_session_is_running (MetaRemoteDesktopSession *session)
|
||||||
{
|
{
|
||||||
return !!session->virtual_pointer;
|
return !!session->virtual_pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_remote_access_handle (MetaRemoteDesktopSession *session)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRemoteAccessController *remote_access_controller;
|
||||||
|
MetaRemoteAccessHandle *remote_access_handle;
|
||||||
|
|
||||||
|
session->handle = meta_remote_desktop_session_handle_new (session);
|
||||||
|
|
||||||
|
remote_access_controller = meta_backend_get_remote_access_controller (backend);
|
||||||
|
remote_access_handle = META_REMOTE_ACCESS_HANDLE (session->handle);
|
||||||
|
meta_remote_access_controller_notify_new_handle (remote_access_controller,
|
||||||
|
remote_access_handle);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -107,6 +139,8 @@ meta_remote_desktop_session_start (MetaRemoteDesktopSession *session,
|
|||||||
clutter_device_manager_create_virtual_device (device_manager,
|
clutter_device_manager_create_virtual_device (device_manager,
|
||||||
CLUTTER_TOUCHSCREEN_DEVICE);
|
CLUTTER_TOUCHSCREEN_DEVICE);
|
||||||
|
|
||||||
|
init_remote_access_handle (session);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +160,20 @@ meta_remote_desktop_session_close (MetaRemoteDesktopSession *session)
|
|||||||
|
|
||||||
g_clear_object (&session->virtual_pointer);
|
g_clear_object (&session->virtual_pointer);
|
||||||
g_clear_object (&session->virtual_keyboard);
|
g_clear_object (&session->virtual_keyboard);
|
||||||
|
g_clear_object (&session->virtual_touchscreen);
|
||||||
|
|
||||||
meta_dbus_session_notify_closed (META_DBUS_SESSION (session));
|
meta_dbus_session_notify_closed (META_DBUS_SESSION (session));
|
||||||
meta_dbus_remote_desktop_session_emit_closed (skeleton);
|
meta_dbus_remote_desktop_session_emit_closed (skeleton);
|
||||||
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
|
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
|
||||||
|
|
||||||
|
if (session->handle)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandle *remote_access_handle =
|
||||||
|
META_REMOTE_ACCESS_HANDLE (session->handle);
|
||||||
|
|
||||||
|
meta_remote_access_handle_notify_stopped (remote_access_handle);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_unref (session);
|
g_object_unref (session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -729,6 +772,7 @@ meta_remote_desktop_session_finalize (GObject *object)
|
|||||||
|
|
||||||
g_assert (!meta_remote_desktop_session_is_running (session));
|
g_assert (!meta_remote_desktop_session_is_running (session));
|
||||||
|
|
||||||
|
g_clear_object (&session->handle);
|
||||||
g_free (session->peer_name);
|
g_free (session->peer_name);
|
||||||
g_free (session->session_id);
|
g_free (session->session_id);
|
||||||
g_free (session->object_path);
|
g_free (session->object_path);
|
||||||
@ -763,3 +807,40 @@ meta_remote_desktop_session_class_init (MetaRemoteDesktopSessionClass *klass)
|
|||||||
|
|
||||||
object_class->finalize = meta_remote_desktop_session_finalize;
|
object_class->finalize = meta_remote_desktop_session_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaRemoteDesktopSessionHandle *
|
||||||
|
meta_remote_desktop_session_handle_new (MetaRemoteDesktopSession *session)
|
||||||
|
{
|
||||||
|
MetaRemoteDesktopSessionHandle *handle;
|
||||||
|
|
||||||
|
handle = g_object_new (META_TYPE_REMOTE_DESKTOP_SESSION_HANDLE, NULL);
|
||||||
|
handle->session = session;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_desktop_session_handle_stop (MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
MetaRemoteDesktopSession *session;
|
||||||
|
|
||||||
|
session = META_REMOTE_DESKTOP_SESSION_HANDLE (handle)->session;
|
||||||
|
if (!session)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_remote_desktop_session_close (session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_desktop_session_handle_init (MetaRemoteDesktopSessionHandle *handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_remote_desktop_session_handle_class_init (MetaRemoteDesktopSessionHandleClass *klass)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandleClass *remote_access_handle_class =
|
||||||
|
META_REMOTE_ACCESS_HANDLE_CLASS (klass);
|
||||||
|
|
||||||
|
remote_access_handle_class->stop = meta_remote_desktop_session_handle_stop;
|
||||||
|
}
|
||||||
|
@ -33,6 +33,12 @@ G_DECLARE_FINAL_TYPE (MetaRemoteDesktopSession, meta_remote_desktop_session,
|
|||||||
META, REMOTE_DESKTOP_SESSION,
|
META, REMOTE_DESKTOP_SESSION,
|
||||||
MetaDBusRemoteDesktopSessionSkeleton)
|
MetaDBusRemoteDesktopSessionSkeleton)
|
||||||
|
|
||||||
|
#define META_TYPE_REMOTE_DESKTOP_SESSION_HANDLE (meta_remote_desktop_session_handle_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaRemoteDesktopSessionHandle,
|
||||||
|
meta_remote_desktop_session_handle,
|
||||||
|
META, REMOTE_DESKTOP_SESSION_HANDLE,
|
||||||
|
MetaRemoteAccessHandle)
|
||||||
|
|
||||||
char * meta_remote_desktop_session_get_object_path (MetaRemoteDesktopSession *session);
|
char * meta_remote_desktop_session_get_object_path (MetaRemoteDesktopSession *session);
|
||||||
|
|
||||||
char * meta_remote_desktop_session_get_session_id (MetaRemoteDesktopSession *session);
|
char * meta_remote_desktop_session_get_session_id (MetaRemoteDesktopSession *session);
|
||||||
|
@ -94,6 +94,24 @@ meta_renderer_get_views (MetaRenderer *renderer)
|
|||||||
return priv->views;
|
return priv->views;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaRendererView *
|
||||||
|
meta_renderer_get_view_from_logical_monitor (MetaRenderer *renderer,
|
||||||
|
MetaLogicalMonitor *logical_monitor)
|
||||||
|
{
|
||||||
|
GList *l;
|
||||||
|
|
||||||
|
for (l = meta_renderer_get_views (renderer); l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaRendererView *view = l->data;
|
||||||
|
|
||||||
|
if (meta_renderer_view_get_logical_monitor (view) ==
|
||||||
|
logical_monitor)
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_renderer_finalize (GObject *object)
|
meta_renderer_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
|
@ -53,4 +53,7 @@ void meta_renderer_set_legacy_view (MetaRenderer *renderer,
|
|||||||
|
|
||||||
GList * meta_renderer_get_views (MetaRenderer *renderer);
|
GList * meta_renderer_get_views (MetaRenderer *renderer);
|
||||||
|
|
||||||
|
MetaRendererView * meta_renderer_get_view_from_logical_monitor (MetaRenderer *renderer,
|
||||||
|
MetaLogicalMonitor *logical_monitor);
|
||||||
|
|
||||||
#endif /* META_RENDERER_H */
|
#endif /* META_RENDERER_H */
|
||||||
|
@ -24,23 +24,38 @@
|
|||||||
|
|
||||||
#include "backends/meta-screen-cast-monitor-stream-src.h"
|
#include "backends/meta-screen-cast-monitor-stream-src.h"
|
||||||
|
|
||||||
|
#include <spa/buffer/meta.h>
|
||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/meta-cursor-tracker-private.h"
|
||||||
#include "backends/meta-screen-cast-monitor-stream.h"
|
#include "backends/meta-screen-cast-monitor-stream.h"
|
||||||
|
#include "backends/meta-screen-cast-session.h"
|
||||||
#include "backends/meta-logical-monitor.h"
|
#include "backends/meta-logical-monitor.h"
|
||||||
#include "backends/meta-monitor.h"
|
#include "backends/meta-monitor.h"
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
|
#include "core/boxes-private.h"
|
||||||
|
|
||||||
struct _MetaScreenCastMonitorStreamSrc
|
struct _MetaScreenCastMonitorStreamSrc
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc parent;
|
MetaScreenCastStreamSrc parent;
|
||||||
|
|
||||||
gulong stage_painted_handler_id;
|
gboolean cursor_bitmap_invalid;
|
||||||
|
|
||||||
|
gulong actors_painted_handler_id;
|
||||||
|
gulong paint_handler_id;
|
||||||
|
gulong cursor_moved_handler_id;
|
||||||
|
gulong cursor_changed_handler_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaScreenCastMonitorStreamSrc,
|
static void
|
||||||
|
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MetaScreenCastMonitorStreamSrc,
|
||||||
meta_screen_cast_monitor_stream_src,
|
meta_screen_cast_monitor_stream_src,
|
||||||
META_TYPE_SCREEN_CAST_STREAM_SRC)
|
META_TYPE_SCREEN_CAST_STREAM_SRC,
|
||||||
|
G_IMPLEMENT_INTERFACE (META_TYPE_HW_CURSOR_INHIBITOR,
|
||||||
|
hw_cursor_inhibitor_iface_init))
|
||||||
|
|
||||||
static ClutterStage *
|
static ClutterStage *
|
||||||
get_stage (MetaScreenCastMonitorStreamSrc *monitor_src)
|
get_stage (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
@ -102,18 +117,164 @@ stage_painted (ClutterActor *actor,
|
|||||||
meta_screen_cast_stream_src_maybe_record_frame (src);
|
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaBackend *
|
||||||
|
get_backend (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
|
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||||
|
MetaScreenCast *screen_cast =
|
||||||
|
meta_screen_cast_session_get_screen_cast (session);
|
||||||
|
|
||||||
|
return meta_screen_cast_get_backend (screen_cast);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_cursor_in_stream (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = get_backend (monitor_src);
|
||||||
|
MetaCursorRenderer *cursor_renderer =
|
||||||
|
meta_backend_get_cursor_renderer (backend);
|
||||||
|
MetaMonitor *monitor;
|
||||||
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
MetaRectangle logical_monitor_layout;
|
||||||
|
ClutterRect logical_monitor_rect;
|
||||||
|
MetaCursorSprite *cursor_sprite;
|
||||||
|
|
||||||
|
monitor = get_monitor (monitor_src);
|
||||||
|
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||||
|
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
logical_monitor_rect =
|
||||||
|
meta_rectangle_to_clutter_rect (&logical_monitor_layout);
|
||||||
|
|
||||||
|
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
||||||
|
if (cursor_sprite)
|
||||||
|
{
|
||||||
|
ClutterRect cursor_rect;
|
||||||
|
|
||||||
|
cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
|
||||||
|
cursor_sprite);
|
||||||
|
return clutter_rect_intersection (&cursor_rect,
|
||||||
|
&logical_monitor_rect,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ClutterPoint cursor_position;
|
||||||
|
|
||||||
|
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||||
|
return clutter_rect_contains_point (&logical_monitor_rect,
|
||||||
|
&cursor_position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
ClutterStage *stage = get_stage (monitor_src);
|
||||||
|
|
||||||
|
if (!is_cursor_in_stream (monitor_src))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (clutter_stage_is_redraw_queued (stage))
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cursor_moved (MetaCursorTracker *cursor_tracker,
|
||||||
|
float x,
|
||||||
|
float y,
|
||||||
|
MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
sync_cursor_state (monitor_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cursor_changed (MetaCursorTracker *cursor_tracker,
|
||||||
|
MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
monitor_src->cursor_bitmap_invalid = TRUE;
|
||||||
|
sync_cursor_state (monitor_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaCursorRenderer *
|
||||||
|
get_cursor_renderer (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
|
||||||
|
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
|
MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream);
|
||||||
|
MetaScreenCast *screen_cast =
|
||||||
|
meta_screen_cast_session_get_screen_cast (session);
|
||||||
|
MetaBackend *backend = meta_screen_cast_get_backend (screen_cast);
|
||||||
|
|
||||||
|
return meta_backend_get_cursor_renderer (backend);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaCursorRenderer *cursor_renderer;
|
||||||
|
MetaHwCursorInhibitor *inhibitor;
|
||||||
|
|
||||||
|
cursor_renderer = get_cursor_renderer (monitor_src);
|
||||||
|
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
|
||||||
|
meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
uninhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
|
{
|
||||||
|
MetaCursorRenderer *cursor_renderer;
|
||||||
|
MetaHwCursorInhibitor *inhibitor;
|
||||||
|
|
||||||
|
cursor_renderer = get_cursor_renderer (monitor_src);
|
||||||
|
inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
|
||||||
|
meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
|
meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
|
||||||
{
|
{
|
||||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||||
|
MetaBackend *backend = get_backend (monitor_src);
|
||||||
|
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
|
MetaScreenCastStream *stream;
|
||||||
|
|
||||||
|
stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
stage = get_stage (monitor_src);
|
stage = get_stage (monitor_src);
|
||||||
monitor_src->stage_painted_handler_id =
|
|
||||||
|
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
||||||
|
{
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
||||||
|
monitor_src->cursor_moved_handler_id =
|
||||||
|
g_signal_connect_after (cursor_tracker, "cursor-moved",
|
||||||
|
G_CALLBACK (cursor_moved),
|
||||||
|
monitor_src);
|
||||||
|
monitor_src->cursor_changed_handler_id =
|
||||||
|
g_signal_connect_after (cursor_tracker, "cursor-changed",
|
||||||
|
G_CALLBACK (cursor_changed),
|
||||||
|
monitor_src);
|
||||||
|
/* Intentional fall-through */
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
||||||
|
monitor_src->actors_painted_handler_id =
|
||||||
|
g_signal_connect (stage, "actors-painted",
|
||||||
|
G_CALLBACK (stage_painted),
|
||||||
|
monitor_src);
|
||||||
|
break;
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
||||||
|
inhibit_hw_cursor (monitor_src);
|
||||||
|
monitor_src->paint_handler_id =
|
||||||
g_signal_connect_after (stage, "paint",
|
g_signal_connect_after (stage, "paint",
|
||||||
G_CALLBACK (stage_painted),
|
G_CALLBACK (stage_painted),
|
||||||
monitor_src);
|
monitor_src);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,14 +283,43 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
|
|||||||
{
|
{
|
||||||
MetaScreenCastMonitorStreamSrc *monitor_src =
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||||
|
MetaBackend *backend = get_backend (monitor_src);
|
||||||
|
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
|
|
||||||
stage = get_stage (monitor_src);
|
stage = get_stage (monitor_src);
|
||||||
g_signal_handler_disconnect (stage, monitor_src->stage_painted_handler_id);
|
|
||||||
monitor_src->stage_painted_handler_id = 0;
|
if (monitor_src->actors_painted_handler_id)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (stage,
|
||||||
|
monitor_src->actors_painted_handler_id);
|
||||||
|
monitor_src->actors_painted_handler_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor_src->paint_handler_id)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (stage,
|
||||||
|
monitor_src->paint_handler_id);
|
||||||
|
monitor_src->paint_handler_id = 0;
|
||||||
|
uninhibit_hw_cursor (monitor_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor_src->cursor_moved_handler_id)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (cursor_tracker,
|
||||||
|
monitor_src->cursor_moved_handler_id);
|
||||||
|
monitor_src->cursor_moved_handler_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monitor_src->cursor_changed_handler_id)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (cursor_tracker,
|
||||||
|
monitor_src->cursor_changed_handler_id);
|
||||||
|
monitor_src->cursor_changed_handler_id = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data)
|
uint8_t *data)
|
||||||
{
|
{
|
||||||
@ -140,9 +330,226 @@ 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);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
draw_cursor_sprite_via_offscreen (MetaScreenCastMonitorStreamSrc *monitor_src,
|
||||||
|
CoglTexture *cursor_texture,
|
||||||
|
int bitmap_width,
|
||||||
|
int bitmap_height,
|
||||||
|
uint32_t *bitmap_data,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = get_backend (monitor_src);
|
||||||
|
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
CoglTexture2D *bitmap_texture;
|
||||||
|
CoglOffscreen *offscreen;
|
||||||
|
CoglFramebuffer *fb;
|
||||||
|
CoglPipeline *pipeline;
|
||||||
|
CoglColor clear_color;
|
||||||
|
|
||||||
|
bitmap_texture = cogl_texture_2d_new_with_size (cogl_context,
|
||||||
|
bitmap_width, bitmap_height);
|
||||||
|
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (bitmap_texture),
|
||||||
|
FALSE);
|
||||||
|
if (!cogl_texture_allocate (COGL_TEXTURE (bitmap_texture), error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (bitmap_texture);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (bitmap_texture));
|
||||||
|
fb = COGL_FRAMEBUFFER (offscreen);
|
||||||
|
cogl_object_unref (bitmap_texture);
|
||||||
|
if (!cogl_framebuffer_allocate (fb, error))
|
||||||
|
{
|
||||||
|
cogl_object_unref (fb);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipeline = cogl_pipeline_new (cogl_context);
|
||||||
|
cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture);
|
||||||
|
cogl_pipeline_set_layer_filters (pipeline, 0,
|
||||||
|
COGL_PIPELINE_FILTER_LINEAR,
|
||||||
|
COGL_PIPELINE_FILTER_LINEAR);
|
||||||
|
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
||||||
|
cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
|
||||||
|
cogl_framebuffer_draw_rectangle (fb, pipeline,
|
||||||
|
-1, 1, 1, -1);
|
||||||
|
cogl_object_unref (pipeline);
|
||||||
|
|
||||||
|
cogl_framebuffer_read_pixels (fb,
|
||||||
|
0, 0,
|
||||||
|
bitmap_width, bitmap_height,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
(uint8_t *) bitmap_data);
|
||||||
|
cogl_object_unref (fb);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
|
struct spa_meta_cursor *spa_meta_cursor)
|
||||||
|
{
|
||||||
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
|
||||||
|
MetaBackend *backend = get_backend (monitor_src);
|
||||||
|
MetaCursorRenderer *cursor_renderer =
|
||||||
|
meta_backend_get_cursor_renderer (backend);
|
||||||
|
MetaRenderer *renderer = meta_backend_get_renderer (backend);
|
||||||
|
MetaSpaType *spa_type = meta_screen_cast_stream_src_get_spa_type (src);
|
||||||
|
GError *error = NULL;
|
||||||
|
MetaCursorSprite *cursor_sprite;
|
||||||
|
CoglTexture *cursor_texture;
|
||||||
|
MetaMonitor *monitor;
|
||||||
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
MetaRectangle logical_monitor_layout;
|
||||||
|
ClutterRect logical_monitor_rect;
|
||||||
|
MetaRendererView *view;
|
||||||
|
float view_scale;
|
||||||
|
ClutterPoint cursor_position;
|
||||||
|
struct spa_meta_bitmap *spa_meta_bitmap;
|
||||||
|
|
||||||
|
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
|
||||||
|
if (cursor_sprite)
|
||||||
|
cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
||||||
|
else
|
||||||
|
cursor_texture = NULL;
|
||||||
|
|
||||||
|
if (!is_cursor_in_stream (monitor_src))
|
||||||
|
{
|
||||||
|
spa_meta_cursor->id = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor = get_monitor (monitor_src);
|
||||||
|
logical_monitor = meta_monitor_get_logical_monitor (monitor);
|
||||||
|
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
logical_monitor_rect =
|
||||||
|
meta_rectangle_to_clutter_rect (&logical_monitor_layout);
|
||||||
|
|
||||||
|
view = meta_renderer_get_view_from_logical_monitor (renderer,
|
||||||
|
logical_monitor);
|
||||||
|
if (view)
|
||||||
|
view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
|
||||||
|
else
|
||||||
|
view_scale = 1.0;
|
||||||
|
|
||||||
|
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
|
||||||
|
cursor_position.x -= logical_monitor_rect.origin.x;
|
||||||
|
cursor_position.y -= logical_monitor_rect.origin.y;
|
||||||
|
cursor_position.x *= view_scale;
|
||||||
|
cursor_position.y *= view_scale;
|
||||||
|
|
||||||
|
spa_meta_cursor->id = 1;
|
||||||
|
spa_meta_cursor->position.x = (int32_t) roundf (cursor_position.x);
|
||||||
|
spa_meta_cursor->position.y = (int32_t) roundf (cursor_position.y);
|
||||||
|
|
||||||
|
if (!monitor_src->cursor_bitmap_invalid)
|
||||||
|
{
|
||||||
|
spa_meta_cursor->hotspot.x = 0;
|
||||||
|
spa_meta_cursor->hotspot.y = 0;
|
||||||
|
spa_meta_cursor->bitmap_offset = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
monitor_src->cursor_bitmap_invalid = FALSE;
|
||||||
|
|
||||||
|
spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor);
|
||||||
|
|
||||||
|
spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor,
|
||||||
|
spa_meta_cursor->bitmap_offset,
|
||||||
|
struct spa_meta_bitmap);
|
||||||
|
spa_meta_bitmap->format = spa_type->video_format.RGBA;
|
||||||
|
spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap);
|
||||||
|
|
||||||
|
if (cursor_texture)
|
||||||
|
{
|
||||||
|
float cursor_scale;
|
||||||
|
float bitmap_scale;
|
||||||
|
int hotspot_x, hotspot_y;
|
||||||
|
int texture_width, texture_height;
|
||||||
|
int bitmap_width, bitmap_height;
|
||||||
|
uint32_t *bitmap_data;
|
||||||
|
|
||||||
|
cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
|
||||||
|
bitmap_scale = view_scale * cursor_scale;
|
||||||
|
|
||||||
|
meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y);
|
||||||
|
spa_meta_cursor->hotspot.x = (int32_t) roundf (hotspot_x * bitmap_scale);
|
||||||
|
spa_meta_cursor->hotspot.y = (int32_t) roundf (hotspot_y * bitmap_scale);
|
||||||
|
|
||||||
|
texture_width = cogl_texture_get_width (cursor_texture);
|
||||||
|
texture_height = cogl_texture_get_height (cursor_texture);
|
||||||
|
bitmap_width = texture_width * bitmap_scale;
|
||||||
|
bitmap_height = texture_height * bitmap_scale;
|
||||||
|
|
||||||
|
spa_meta_bitmap->size.width = bitmap_width;
|
||||||
|
spa_meta_bitmap->size.height = bitmap_height;
|
||||||
|
spa_meta_bitmap->stride = bitmap_width * 4;
|
||||||
|
|
||||||
|
bitmap_data = SPA_MEMBER (spa_meta_bitmap,
|
||||||
|
spa_meta_bitmap->offset,
|
||||||
|
uint32_t);
|
||||||
|
|
||||||
|
if (texture_width == bitmap_width &&
|
||||||
|
texture_height == bitmap_height)
|
||||||
|
{
|
||||||
|
cogl_texture_get_data (cursor_texture,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
texture_width * 4,
|
||||||
|
(uint8_t *) bitmap_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!draw_cursor_sprite_via_offscreen (monitor_src,
|
||||||
|
cursor_texture,
|
||||||
|
bitmap_width,
|
||||||
|
bitmap_height,
|
||||||
|
bitmap_data,
|
||||||
|
&error))
|
||||||
|
{
|
||||||
|
g_warning ("Failed to draw cursor via offscreen: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
spa_meta_cursor->id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spa_meta_cursor->hotspot.x = 0;
|
||||||
|
spa_meta_cursor->hotspot.y = 0;
|
||||||
|
|
||||||
|
*spa_meta_bitmap = (struct spa_meta_bitmap) { 0 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_screen_cast_monitor_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
|
||||||
|
MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
MetaScreenCastMonitorStreamSrc *monitor_src =
|
||||||
|
META_SCREEN_CAST_MONITOR_STREAM_SRC (inhibitor);
|
||||||
|
|
||||||
|
return is_cursor_in_stream (monitor_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface)
|
||||||
|
{
|
||||||
|
iface->is_cursor_sprite_inhibited =
|
||||||
|
meta_screen_cast_monitor_stream_src_is_cursor_sprite_inhibited;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaScreenCastMonitorStreamSrc *
|
MetaScreenCastMonitorStreamSrc *
|
||||||
@ -157,6 +564,7 @@ meta_screen_cast_monitor_stream_src_new (MetaScreenCastMonitorStream *monitor_s
|
|||||||
static void
|
static void
|
||||||
meta_screen_cast_monitor_stream_src_init (MetaScreenCastMonitorStreamSrc *monitor_src)
|
meta_screen_cast_monitor_stream_src_init (MetaScreenCastMonitorStreamSrc *monitor_src)
|
||||||
{
|
{
|
||||||
|
monitor_src->cursor_bitmap_invalid = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -169,4 +577,6 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
|
|||||||
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_frame = meta_screen_cast_monitor_stream_src_record_frame;
|
||||||
|
src_class->set_cursor_metadata =
|
||||||
|
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
|
||||||
}
|
}
|
||||||
|
@ -105,12 +105,15 @@ meta_screen_cast_monitor_stream_get_monitor (MetaScreenCastMonitorStream *monito
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaScreenCastMonitorStream *
|
MetaScreenCastMonitorStream *
|
||||||
meta_screen_cast_monitor_stream_new (GDBusConnection *connection,
|
meta_screen_cast_monitor_stream_new (MetaScreenCastSession *session,
|
||||||
MetaMonitorManager *monitor_manager,
|
GDBusConnection *connection,
|
||||||
MetaMonitor *monitor,
|
MetaMonitor *monitor,
|
||||||
ClutterStage *stage,
|
ClutterStage *stage,
|
||||||
|
MetaScreenCastCursorMode cursor_mode,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
|
MetaGpu *gpu = meta_monitor_get_gpu (monitor);
|
||||||
|
MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu);
|
||||||
MetaScreenCastMonitorStream *monitor_stream;
|
MetaScreenCastMonitorStream *monitor_stream;
|
||||||
|
|
||||||
if (!meta_monitor_is_active (monitor))
|
if (!meta_monitor_is_active (monitor))
|
||||||
@ -122,7 +125,9 @@ meta_screen_cast_monitor_stream_new (GDBusConnection *connection,
|
|||||||
monitor_stream = g_initable_new (META_TYPE_SCREEN_CAST_MONITOR_STREAM,
|
monitor_stream = g_initable_new (META_TYPE_SCREEN_CAST_MONITOR_STREAM,
|
||||||
NULL,
|
NULL,
|
||||||
error,
|
error,
|
||||||
|
"session", session,
|
||||||
"connection", connection,
|
"connection", connection,
|
||||||
|
"cursor-mode", cursor_mode,
|
||||||
"monitor", monitor,
|
"monitor", monitor,
|
||||||
NULL);
|
NULL);
|
||||||
if (!monitor_stream)
|
if (!monitor_stream)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "backends/meta-monitor-manager-private.h"
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
#include "backends/meta-screen-cast-stream.h"
|
#include "backends/meta-screen-cast-stream.h"
|
||||||
|
#include "backends/meta-screen-cast.h"
|
||||||
|
|
||||||
#define META_TYPE_SCREEN_CAST_MONITOR_STREAM (meta_screen_cast_monitor_stream_get_type ())
|
#define META_TYPE_SCREEN_CAST_MONITOR_STREAM (meta_screen_cast_monitor_stream_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (MetaScreenCastMonitorStream,
|
G_DECLARE_FINAL_TYPE (MetaScreenCastMonitorStream,
|
||||||
@ -34,10 +35,11 @@ G_DECLARE_FINAL_TYPE (MetaScreenCastMonitorStream,
|
|||||||
META, SCREEN_CAST_MONITOR_STREAM,
|
META, SCREEN_CAST_MONITOR_STREAM,
|
||||||
MetaScreenCastStream)
|
MetaScreenCastStream)
|
||||||
|
|
||||||
MetaScreenCastMonitorStream * meta_screen_cast_monitor_stream_new (GDBusConnection *connection,
|
MetaScreenCastMonitorStream * meta_screen_cast_monitor_stream_new (MetaScreenCastSession *session,
|
||||||
MetaMonitorManager *monitor_manager,
|
GDBusConnection *connection,
|
||||||
MetaMonitor *monitor,
|
MetaMonitor *monitor,
|
||||||
ClutterStage *stage,
|
ClutterStage *stage,
|
||||||
|
MetaScreenCastCursorMode cursor_mode,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
ClutterStage * meta_screen_cast_monitor_stream_get_stage (MetaScreenCastMonitorStream *monitor_stream);
|
ClutterStage * meta_screen_cast_monitor_stream_get_stage (MetaScreenCastMonitorStream *monitor_stream);
|
||||||
|
@ -26,8 +26,11 @@
|
|||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
#include "backends/meta-dbus-session-watcher.h"
|
#include "backends/meta-dbus-session-watcher.h"
|
||||||
|
#include "backends/meta-remote-access-controller-private.h"
|
||||||
#include "backends/meta-screen-cast-monitor-stream.h"
|
#include "backends/meta-screen-cast-monitor-stream.h"
|
||||||
#include "backends/meta-screen-cast-stream.h"
|
#include "backends/meta-screen-cast-stream.h"
|
||||||
|
#include "backends/meta-screen-cast-window-stream.h"
|
||||||
|
#include "core/display-private.h"
|
||||||
|
|
||||||
#define META_SCREEN_CAST_SESSION_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Session"
|
#define META_SCREEN_CAST_SESSION_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Session"
|
||||||
|
|
||||||
@ -35,12 +38,16 @@ struct _MetaScreenCastSession
|
|||||||
{
|
{
|
||||||
MetaDBusScreenCastSessionSkeleton parent;
|
MetaDBusScreenCastSessionSkeleton parent;
|
||||||
|
|
||||||
|
MetaScreenCast *screen_cast;
|
||||||
|
|
||||||
char *peer_name;
|
char *peer_name;
|
||||||
|
|
||||||
MetaScreenCastSessionType session_type;
|
MetaScreenCastSessionType session_type;
|
||||||
char *object_path;
|
char *object_path;
|
||||||
|
|
||||||
GList *streams;
|
GList *streams;
|
||||||
|
|
||||||
|
MetaScreenCastSessionHandle *handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -57,6 +64,35 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastSession,
|
|||||||
G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION,
|
G_IMPLEMENT_INTERFACE (META_TYPE_DBUS_SESSION,
|
||||||
meta_dbus_session_init_iface))
|
meta_dbus_session_init_iface))
|
||||||
|
|
||||||
|
struct _MetaScreenCastSessionHandle
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandle parent;
|
||||||
|
|
||||||
|
MetaScreenCastSession *session;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaScreenCastSessionHandle,
|
||||||
|
meta_screen_cast_session_handle,
|
||||||
|
META_TYPE_REMOTE_ACCESS_HANDLE)
|
||||||
|
|
||||||
|
static MetaScreenCastSessionHandle *
|
||||||
|
meta_screen_cast_session_handle_new (MetaScreenCastSession *session);
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_remote_access_handle (MetaScreenCastSession *session)
|
||||||
|
{
|
||||||
|
MetaBackend *backend = meta_get_backend ();
|
||||||
|
MetaRemoteAccessController *remote_access_controller;
|
||||||
|
MetaRemoteAccessHandle *remote_access_handle;
|
||||||
|
|
||||||
|
session->handle = meta_screen_cast_session_handle_new (session);
|
||||||
|
|
||||||
|
remote_access_controller = meta_backend_get_remote_access_controller (backend);
|
||||||
|
remote_access_handle = META_REMOTE_ACCESS_HANDLE (session->handle);
|
||||||
|
meta_remote_access_controller_notify_new_handle (remote_access_controller,
|
||||||
|
remote_access_handle);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_screen_cast_session_start (MetaScreenCastSession *session,
|
meta_screen_cast_session_start (MetaScreenCastSession *session,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -71,6 +107,8 @@ meta_screen_cast_session_start (MetaScreenCastSession *session,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
init_remote_access_handle (session);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +132,14 @@ meta_screen_cast_session_close (MetaScreenCastSession *session)
|
|||||||
|
|
||||||
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
|
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (session));
|
||||||
|
|
||||||
|
if (session->handle)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandle *remote_access_handle =
|
||||||
|
META_REMOTE_ACCESS_HANDLE (session->handle);
|
||||||
|
|
||||||
|
meta_remote_access_handle_notify_stopped (remote_access_handle);
|
||||||
|
}
|
||||||
|
|
||||||
g_object_unref (session);
|
g_object_unref (session);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,6 +161,12 @@ meta_screen_cast_session_get_stream (MetaScreenCastSession *session,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaScreenCast *
|
||||||
|
meta_screen_cast_session_get_screen_cast (MetaScreenCastSession *session)
|
||||||
|
{
|
||||||
|
return session->screen_cast;
|
||||||
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
meta_screen_cast_session_get_object_path (MetaScreenCastSession *session)
|
meta_screen_cast_session_get_object_path (MetaScreenCastSession *session)
|
||||||
{
|
{
|
||||||
@ -210,6 +262,20 @@ on_stream_closed (MetaScreenCastStream *stream,
|
|||||||
meta_screen_cast_session_close (session);
|
meta_screen_cast_session_close (session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_valid_cursor_mode (MetaScreenCastCursorMode cursor_mode)
|
||||||
|
{
|
||||||
|
switch (cursor_mode)
|
||||||
|
{
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
handle_record_monitor (MetaDBusScreenCastSession *skeleton,
|
handle_record_monitor (MetaDBusScreenCastSession *skeleton,
|
||||||
GDBusMethodInvocation *invocation,
|
GDBusMethodInvocation *invocation,
|
||||||
@ -223,6 +289,7 @@ handle_record_monitor (MetaDBusScreenCastSession *skeleton,
|
|||||||
MetaMonitorManager *monitor_manager =
|
MetaMonitorManager *monitor_manager =
|
||||||
meta_backend_get_monitor_manager (backend);
|
meta_backend_get_monitor_manager (backend);
|
||||||
MetaMonitor *monitor;
|
MetaMonitor *monitor;
|
||||||
|
MetaScreenCastCursorMode cursor_mode;
|
||||||
ClutterStage *stage;
|
ClutterStage *stage;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
MetaScreenCastMonitorStream *monitor_stream;
|
MetaScreenCastMonitorStream *monitor_stream;
|
||||||
@ -254,12 +321,28 @@ handle_record_monitor (MetaDBusScreenCastSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode))
|
||||||
|
{
|
||||||
|
cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!is_valid_cursor_mode (cursor_mode))
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Unknown cursor mode");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
|
||||||
|
|
||||||
monitor_stream = meta_screen_cast_monitor_stream_new (connection,
|
monitor_stream = meta_screen_cast_monitor_stream_new (session,
|
||||||
monitor_manager,
|
connection,
|
||||||
monitor,
|
monitor,
|
||||||
stage,
|
stage,
|
||||||
|
cursor_mode,
|
||||||
&error);
|
&error);
|
||||||
if (!monitor_stream)
|
if (!monitor_stream)
|
||||||
{
|
{
|
||||||
@ -291,6 +374,15 @@ handle_record_window (MetaDBusScreenCastSession *skeleton,
|
|||||||
GVariant *properties_variant)
|
GVariant *properties_variant)
|
||||||
{
|
{
|
||||||
MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton);
|
MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton);
|
||||||
|
GDBusInterfaceSkeleton *interface_skeleton;
|
||||||
|
GDBusConnection *connection;
|
||||||
|
MetaWindow *window;
|
||||||
|
GError *error = NULL;
|
||||||
|
MetaDisplay *display;
|
||||||
|
GVariant *window_id_variant = NULL;
|
||||||
|
MetaScreenCastWindowStream *window_stream;
|
||||||
|
MetaScreenCastStream *stream;
|
||||||
|
char *stream_path;
|
||||||
|
|
||||||
if (!check_permission (session, invocation))
|
if (!check_permission (session, invocation))
|
||||||
{
|
{
|
||||||
@ -300,9 +392,60 @@ handle_record_window (MetaDBusScreenCastSession *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties_variant)
|
||||||
|
window_id_variant = g_variant_lookup_value (properties_variant,
|
||||||
|
"window-id",
|
||||||
|
G_VARIANT_TYPE ("t"));
|
||||||
|
|
||||||
|
display = meta_get_display ();
|
||||||
|
if (window_id_variant)
|
||||||
|
{
|
||||||
|
uint64_t window_id;
|
||||||
|
|
||||||
|
g_variant_get (window_id_variant, "t", &window_id);
|
||||||
|
window = meta_display_get_window_from_id (display, window_id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
window = meta_display_get_focus_window (display);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window)
|
||||||
|
{
|
||||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
G_DBUS_ERROR_FAILED,
|
G_DBUS_ERROR_FAILED,
|
||||||
"Recording a window not yet supported");
|
"Window not found");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton);
|
||||||
|
connection = g_dbus_interface_skeleton_get_connection (interface_skeleton);
|
||||||
|
|
||||||
|
window_stream = meta_screen_cast_window_stream_new (session,
|
||||||
|
connection,
|
||||||
|
window,
|
||||||
|
&error);
|
||||||
|
if (!window_stream)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_FAILED,
|
||||||
|
"Failed to record window: %s",
|
||||||
|
error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = META_SCREEN_CAST_STREAM (window_stream);
|
||||||
|
stream_path = meta_screen_cast_stream_get_object_path (stream);
|
||||||
|
|
||||||
|
session->streams = g_list_append (session->streams, stream);
|
||||||
|
|
||||||
|
g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session);
|
||||||
|
|
||||||
|
meta_dbus_screen_cast_session_complete_record_window (skeleton,
|
||||||
|
invocation,
|
||||||
|
stream_path);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,6 +482,7 @@ meta_screen_cast_session_new (MetaScreenCast *screen_cast,
|
|||||||
static unsigned int global_session_number = 0;
|
static unsigned int global_session_number = 0;
|
||||||
|
|
||||||
session = g_object_new (META_TYPE_SCREEN_CAST_SESSION, NULL);
|
session = g_object_new (META_TYPE_SCREEN_CAST_SESSION, NULL);
|
||||||
|
session->screen_cast = screen_cast;
|
||||||
session->session_type = session_type;
|
session->session_type = session_type;
|
||||||
session->peer_name = g_strdup (peer_name);
|
session->peer_name = g_strdup (peer_name);
|
||||||
session->object_path =
|
session->object_path =
|
||||||
@ -361,6 +505,7 @@ meta_screen_cast_session_finalize (GObject *object)
|
|||||||
{
|
{
|
||||||
MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (object);
|
MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (object);
|
||||||
|
|
||||||
|
g_clear_object (&session->handle);
|
||||||
g_free (session->peer_name);
|
g_free (session->peer_name);
|
||||||
g_free (session->object_path);
|
g_free (session->object_path);
|
||||||
|
|
||||||
@ -379,3 +524,40 @@ meta_screen_cast_session_class_init (MetaScreenCastSessionClass *klass)
|
|||||||
|
|
||||||
object_class->finalize = meta_screen_cast_session_finalize;
|
object_class->finalize = meta_screen_cast_session_finalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MetaScreenCastSessionHandle *
|
||||||
|
meta_screen_cast_session_handle_new (MetaScreenCastSession *session)
|
||||||
|
{
|
||||||
|
MetaScreenCastSessionHandle *handle;
|
||||||
|
|
||||||
|
handle = g_object_new (META_TYPE_SCREEN_CAST_SESSION_HANDLE, NULL);
|
||||||
|
handle->session = session;
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_session_handle_stop (MetaRemoteAccessHandle *handle)
|
||||||
|
{
|
||||||
|
MetaScreenCastSession *session;
|
||||||
|
|
||||||
|
session = META_SCREEN_CAST_SESSION_HANDLE (handle)->session;
|
||||||
|
if (!session)
|
||||||
|
return;
|
||||||
|
|
||||||
|
meta_screen_cast_session_close (session);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_session_handle_init (MetaScreenCastSessionHandle *handle)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_session_handle_class_init (MetaScreenCastSessionHandleClass *klass)
|
||||||
|
{
|
||||||
|
MetaRemoteAccessHandleClass *remote_access_handle_class =
|
||||||
|
META_REMOTE_ACCESS_HANDLE_CLASS (klass);
|
||||||
|
|
||||||
|
remote_access_handle_class->stop = meta_screen_cast_session_handle_stop;
|
||||||
|
}
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "backends/meta-screen-cast.h"
|
#include "backends/meta-screen-cast.h"
|
||||||
|
|
||||||
#include "backends/meta-screen-cast-stream.h"
|
#include "backends/meta-screen-cast-stream.h"
|
||||||
|
#include "meta/meta-remote-access-controller.h"
|
||||||
|
|
||||||
typedef enum _MetaScreenCastSessionType
|
typedef enum _MetaScreenCastSessionType
|
||||||
{
|
{
|
||||||
@ -38,6 +39,12 @@ G_DECLARE_FINAL_TYPE (MetaScreenCastSession, meta_screen_cast_session,
|
|||||||
META, SCREEN_CAST_SESSION,
|
META, SCREEN_CAST_SESSION,
|
||||||
MetaDBusScreenCastSessionSkeleton)
|
MetaDBusScreenCastSessionSkeleton)
|
||||||
|
|
||||||
|
#define META_TYPE_SCREEN_CAST_SESSION_HANDLE (meta_screen_cast_session_handle_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaScreenCastSessionHandle,
|
||||||
|
meta_screen_cast_session_handle,
|
||||||
|
META, SCREEN_CAST_SESSION_HANDLE,
|
||||||
|
MetaRemoteAccessHandle)
|
||||||
|
|
||||||
char * meta_screen_cast_session_get_object_path (MetaScreenCastSession *session);
|
char * meta_screen_cast_session_get_object_path (MetaScreenCastSession *session);
|
||||||
|
|
||||||
MetaScreenCastSession * meta_screen_cast_session_new (MetaScreenCast *screen_cast,
|
MetaScreenCastSession * meta_screen_cast_session_new (MetaScreenCast *screen_cast,
|
||||||
@ -53,4 +60,6 @@ void meta_screen_cast_session_close (MetaScreenCastSession *session);
|
|||||||
MetaScreenCastStream * meta_screen_cast_session_get_stream (MetaScreenCastSession *session,
|
MetaScreenCastStream * meta_screen_cast_session_get_stream (MetaScreenCastSession *session,
|
||||||
const char *path);
|
const char *path);
|
||||||
|
|
||||||
|
MetaScreenCast * meta_screen_cast_session_get_screen_cast (MetaScreenCastSession *session);
|
||||||
|
|
||||||
#endif /* META_SCREEN_CAST_SESSION_H */
|
#endif /* META_SCREEN_CAST_SESSION_H */
|
||||||
|
@ -40,6 +40,10 @@
|
|||||||
#define PRIVATE_OWNER_FROM_FIELD(TypeName, field_ptr, field_name) \
|
#define PRIVATE_OWNER_FROM_FIELD(TypeName, field_ptr, field_name) \
|
||||||
(TypeName *)((guint8 *)(field_ptr) - G_PRIVATE_OFFSET (TypeName, field_name))
|
(TypeName *)((guint8 *)(field_ptr) - G_PRIVATE_OFFSET (TypeName, field_name))
|
||||||
|
|
||||||
|
#define CURSOR_META_SIZE(width, height) \
|
||||||
|
(sizeof (struct spa_meta_cursor) + \
|
||||||
|
sizeof (struct spa_meta_bitmap) + width * height * 4)
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
@ -57,14 +61,6 @@ enum
|
|||||||
|
|
||||||
static guint signals[N_SIGNALS];
|
static guint signals[N_SIGNALS];
|
||||||
|
|
||||||
typedef struct _MetaSpaType
|
|
||||||
{
|
|
||||||
struct spa_type_media_type media_type;
|
|
||||||
struct spa_type_media_subtype media_subtype;
|
|
||||||
struct spa_type_format_video format_video;
|
|
||||||
struct spa_type_video_format video_format;
|
|
||||||
} MetaSpaType;
|
|
||||||
|
|
||||||
typedef struct _MetaPipeWireSource
|
typedef struct _MetaPipeWireSource
|
||||||
{
|
{
|
||||||
GSource base;
|
GSource base;
|
||||||
@ -91,6 +87,9 @@ typedef struct _MetaScreenCastStreamSrcPrivate
|
|||||||
struct spa_video_info_raw video_format;
|
struct spa_video_info_raw video_format;
|
||||||
|
|
||||||
uint64_t last_frame_timestamp_us;
|
uint64_t last_frame_timestamp_us;
|
||||||
|
|
||||||
|
int stream_width;
|
||||||
|
int stream_height;
|
||||||
} MetaScreenCastStreamSrcPrivate;
|
} MetaScreenCastStreamSrcPrivate;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -117,14 +116,81 @@ meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
|||||||
klass->get_specs (src, width, height, frame_rate);
|
klass->get_specs (src, width, height, frame_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
|
meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
|
||||||
|
MetaRectangle *crop_rect)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrcClass *klass =
|
||||||
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
|
if (klass->get_videocrop)
|
||||||
|
return klass->get_videocrop (src, crop_rect);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data)
|
uint8_t *data)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcClass *klass =
|
MetaScreenCastStreamSrcClass *klass =
|
||||||
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
klass->record_frame (src, data);
|
return klass->record_frame (src, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
|
struct spa_meta_cursor *spa_meta_cursor)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrcClass *klass =
|
||||||
|
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
|
||||||
|
|
||||||
|
if (klass->set_cursor_metadata)
|
||||||
|
klass->set_cursor_metadata (src, spa_meta_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaSpaType *
|
||||||
|
meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
|
|
||||||
|
return &priv->spa_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_cursor_metadata (MetaScreenCastStreamSrc *src,
|
||||||
|
struct spa_buffer *spa_buffer)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
|
MetaSpaType *spa_type = &priv->spa_type;
|
||||||
|
struct spa_meta_cursor *spa_meta_cursor;
|
||||||
|
|
||||||
|
spa_meta_cursor = spa_buffer_find_meta (spa_buffer, spa_type->meta_cursor);
|
||||||
|
if (spa_meta_cursor)
|
||||||
|
meta_screen_cast_stream_src_set_cursor_metadata (src, spa_meta_cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
maybe_record_cursor (MetaScreenCastStreamSrc *src,
|
||||||
|
struct spa_buffer *spa_buffer,
|
||||||
|
uint8_t *data)
|
||||||
|
{
|
||||||
|
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
|
|
||||||
|
switch (meta_screen_cast_stream_get_cursor_mode (stream))
|
||||||
|
{
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
|
||||||
|
return;
|
||||||
|
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
|
||||||
|
add_cursor_metadata (src, spa_buffer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -132,8 +198,9 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
{
|
{
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
meta_screen_cast_stream_src_get_instance_private (src);
|
meta_screen_cast_stream_src_get_instance_private (src);
|
||||||
uint32_t buffer_id;
|
MetaRectangle crop_rect;
|
||||||
struct spa_buffer *buffer;
|
struct pw_buffer *buffer;
|
||||||
|
struct spa_buffer *spa_buffer;
|
||||||
uint8_t *map = NULL;
|
uint8_t *map = NULL;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint64_t now_us;
|
uint64_t now_us;
|
||||||
@ -148,17 +215,24 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
if (!priv->pipewire_stream)
|
if (!priv->pipewire_stream)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
buffer_id = pw_stream_get_empty_buffer (priv->pipewire_stream);
|
buffer = pw_stream_dequeue_buffer (priv->pipewire_stream);
|
||||||
if (buffer_id == SPA_ID_INVALID)
|
if (!buffer)
|
||||||
return;
|
|
||||||
|
|
||||||
buffer = pw_stream_peek_buffer (priv->pipewire_stream, buffer_id);
|
|
||||||
|
|
||||||
if (buffer->datas[0].type == priv->pipewire_type->data.MemFd)
|
|
||||||
{
|
{
|
||||||
map = mmap (NULL, buffer->datas[0].maxsize + buffer->datas[0].mapoffset,
|
g_warning ("Failed to dequeue at PipeWire buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spa_buffer = buffer->buffer;
|
||||||
|
|
||||||
|
if (spa_buffer->datas[0].data)
|
||||||
|
{
|
||||||
|
data = spa_buffer->datas[0].data;
|
||||||
|
}
|
||||||
|
else if (spa_buffer->datas[0].type == priv->pipewire_type->data.MemFd)
|
||||||
|
{
|
||||||
|
map = mmap (NULL, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset,
|
||||||
PROT_READ | PROT_WRITE, MAP_SHARED,
|
PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
buffer->datas[0].fd, 0);
|
spa_buffer->datas[0].fd, 0);
|
||||||
if (map == MAP_FAILED)
|
if (map == MAP_FAILED)
|
||||||
{
|
{
|
||||||
g_warning ("Failed to mmap pipewire stream buffer: %s\n",
|
g_warning ("Failed to mmap pipewire stream buffer: %s\n",
|
||||||
@ -166,26 +240,54 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = SPA_MEMBER (map, buffer->datas[0].mapoffset, uint8_t);
|
data = SPA_MEMBER (map, spa_buffer->datas[0].mapoffset, uint8_t);
|
||||||
}
|
|
||||||
else if (buffer->datas[0].type == priv->pipewire_type->data.MemPtr)
|
|
||||||
{
|
|
||||||
data = buffer->datas[0].data;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
g_warning ("Unhandled spa buffer type: %d", spa_buffer->datas[0].type);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_screen_cast_stream_src_record_frame (src, data);
|
if (meta_screen_cast_stream_src_record_frame (src, data))
|
||||||
|
{
|
||||||
|
struct spa_meta_video_crop *spa_meta_video_crop;
|
||||||
|
|
||||||
|
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
|
||||||
|
|
||||||
|
/* Update VideoCrop if needed */
|
||||||
|
spa_meta_video_crop =
|
||||||
|
spa_buffer_find_meta (spa_buffer, priv->pipewire_type->meta.VideoCrop);
|
||||||
|
if (spa_meta_video_crop)
|
||||||
|
{
|
||||||
|
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||||
|
{
|
||||||
|
spa_meta_video_crop->x = crop_rect.x;
|
||||||
|
spa_meta_video_crop->y = crop_rect.y;
|
||||||
|
spa_meta_video_crop->width = crop_rect.width;
|
||||||
|
spa_meta_video_crop->height = crop_rect.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spa_meta_video_crop->x = 0;
|
||||||
|
spa_meta_video_crop->y = 0;
|
||||||
|
spa_meta_video_crop->width = priv->stream_width;
|
||||||
|
spa_meta_video_crop->height = priv->stream_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spa_buffer->datas[0].chunk->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_record_cursor (src, spa_buffer, data);
|
||||||
|
|
||||||
priv->last_frame_timestamp_us = now_us;
|
priv->last_frame_timestamp_us = now_us;
|
||||||
|
|
||||||
if (map)
|
if (map)
|
||||||
munmap (map, buffer->datas[0].maxsize + buffer->datas[0].mapoffset);
|
munmap (map, spa_buffer->datas[0].maxsize + spa_buffer->datas[0].mapoffset);
|
||||||
|
|
||||||
buffer->datas[0].chunk->size = buffer->datas[0].maxsize;
|
pw_stream_queue_buffer (priv->pipewire_stream, buffer);
|
||||||
|
|
||||||
pw_stream_send_buffer (priv->pipewire_stream, buffer_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -262,7 +364,7 @@ on_stream_state_changed (void *data,
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
on_stream_format_changed (void *data,
|
on_stream_format_changed (void *data,
|
||||||
struct spa_pod *format)
|
const struct spa_pod *format)
|
||||||
{
|
{
|
||||||
MetaScreenCastStreamSrc *src = data;
|
MetaScreenCastStreamSrc *src = data;
|
||||||
MetaScreenCastStreamSrcPrivate *priv =
|
MetaScreenCastStreamSrcPrivate *priv =
|
||||||
@ -271,7 +373,7 @@ on_stream_format_changed (void *data,
|
|||||||
uint8_t params_buffer[1024];
|
uint8_t params_buffer[1024];
|
||||||
int32_t width, height, stride, size;
|
int32_t width, height, stride, size;
|
||||||
struct spa_pod_builder pod_builder;
|
struct spa_pod_builder pod_builder;
|
||||||
struct spa_pod *params[1];
|
const struct spa_pod *params[3];
|
||||||
const int bpp = 4;
|
const int bpp = 4;
|
||||||
|
|
||||||
if (!format)
|
if (!format)
|
||||||
@ -299,6 +401,18 @@ on_stream_format_changed (void *data,
|
|||||||
":", pipewire_type->param_buffers.buffers, "iru", 16, PROP_RANGE (2, 16),
|
":", pipewire_type->param_buffers.buffers, "iru", 16, PROP_RANGE (2, 16),
|
||||||
":", pipewire_type->param_buffers.align, "i", 16);
|
":", pipewire_type->param_buffers.align, "i", 16);
|
||||||
|
|
||||||
|
params[1] = spa_pod_builder_object (
|
||||||
|
&pod_builder,
|
||||||
|
pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
||||||
|
":", pipewire_type->param_meta.type, "I", pipewire_type->meta.VideoCrop,
|
||||||
|
":", pipewire_type->param_meta.size, "i", sizeof (struct spa_meta_video_crop));
|
||||||
|
|
||||||
|
params[2] = spa_pod_builder_object (
|
||||||
|
&pod_builder,
|
||||||
|
pipewire_type->param.idMeta, pipewire_type->param_meta.Meta,
|
||||||
|
":", pipewire_type->param_meta.type, "I", priv->spa_type.meta_cursor,
|
||||||
|
":", pipewire_type->param_meta.size, "i", CURSOR_META_SIZE (64, 64));
|
||||||
|
|
||||||
pw_stream_finish_format (priv->pipewire_stream, 0,
|
pw_stream_finish_format (priv->pipewire_stream, 0,
|
||||||
params, G_N_ELEMENTS (params));
|
params, G_N_ELEMENTS (params));
|
||||||
}
|
}
|
||||||
@ -321,18 +435,28 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||||
MetaSpaType *spa_type = &priv->spa_type;
|
MetaSpaType *spa_type = &priv->spa_type;
|
||||||
struct pw_type *pipewire_type = priv->pipewire_type;
|
struct pw_type *pipewire_type = priv->pipewire_type;
|
||||||
int width, height;
|
|
||||||
float frame_rate;
|
float frame_rate;
|
||||||
MetaFraction frame_rate_fraction;
|
MetaFraction frame_rate_fraction;
|
||||||
struct spa_fraction max_framerate;
|
struct spa_fraction max_framerate;
|
||||||
struct spa_fraction min_framerate;
|
struct spa_fraction min_framerate;
|
||||||
const struct spa_pod *params[1];
|
const struct spa_pod *params[1];
|
||||||
|
int result;
|
||||||
|
|
||||||
pipewire_stream = pw_stream_new (priv->pipewire_remote,
|
pipewire_stream = pw_stream_new (priv->pipewire_remote,
|
||||||
"meta-screen-cast-src",
|
"meta-screen-cast-src",
|
||||||
NULL);
|
NULL);
|
||||||
|
if (!pipewire_stream)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Failed to create PipeWire stream: %s",
|
||||||
|
strerror (errno));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
meta_screen_cast_stream_src_get_specs (src, &width, &height, &frame_rate);
|
meta_screen_cast_stream_src_get_specs (src,
|
||||||
|
&priv->stream_width,
|
||||||
|
&priv->stream_height,
|
||||||
|
&frame_rate);
|
||||||
frame_rate_fraction = meta_fraction_from_double (frame_rate);
|
frame_rate_fraction = meta_fraction_from_double (frame_rate);
|
||||||
|
|
||||||
min_framerate = SPA_FRACTION (1, 1);
|
min_framerate = SPA_FRACTION (1, 1);
|
||||||
@ -345,9 +469,10 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
"I", spa_type->media_type.video,
|
"I", spa_type->media_type.video,
|
||||||
"I", spa_type->media_subtype.raw,
|
"I", spa_type->media_subtype.raw,
|
||||||
":", spa_type->format_video.format, "I", spa_type->video_format.BGRx,
|
":", spa_type->format_video.format, "I", spa_type->video_format.BGRx,
|
||||||
":", spa_type->format_video.size, "R", &SPA_RECTANGLE (width, height),
|
":", spa_type->format_video.size, "R", &SPA_RECTANGLE (priv->stream_width,
|
||||||
|
priv->stream_height),
|
||||||
":", spa_type->format_video.framerate, "F", &SPA_FRACTION (0, 1),
|
":", spa_type->format_video.framerate, "F", &SPA_FRACTION (0, 1),
|
||||||
":", spa_type->format_video.max_framerate, "Fr", &max_framerate,
|
":", spa_type->format_video.max_framerate, "Fru", &max_framerate,
|
||||||
PROP_RANGE (&min_framerate,
|
PROP_RANGE (&min_framerate,
|
||||||
&max_framerate));
|
&max_framerate));
|
||||||
|
|
||||||
@ -356,14 +481,16 @@ create_pipewire_stream (MetaScreenCastStreamSrc *src,
|
|||||||
&stream_events,
|
&stream_events,
|
||||||
src);
|
src);
|
||||||
|
|
||||||
if (pw_stream_connect (pipewire_stream,
|
result = pw_stream_connect (pipewire_stream,
|
||||||
PW_DIRECTION_OUTPUT,
|
PW_DIRECTION_OUTPUT,
|
||||||
NULL,
|
NULL,
|
||||||
PW_STREAM_FLAG_NONE,
|
(PW_STREAM_FLAG_DRIVER |
|
||||||
params, G_N_ELEMENTS (¶ms)) != 0)
|
PW_STREAM_FLAG_MAP_BUFFERS),
|
||||||
|
params, G_N_ELEMENTS (params));
|
||||||
|
if (result != 0)
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
"Could not connect");
|
"Could not connect: %s", spa_strerror (result));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,6 +582,7 @@ init_spa_type (MetaSpaType *type,
|
|||||||
spa_type_media_subtype_map (map, &type->media_subtype);
|
spa_type_media_subtype_map (map, &type->media_subtype);
|
||||||
spa_type_format_video_map (map, &type->format_video);
|
spa_type_format_video_map (map, &type->format_video);
|
||||||
spa_type_video_format_map (map, &type->video_format);
|
spa_type_video_format_map (map, &type->video_format);
|
||||||
|
type->meta_cursor = spa_type_map_get_id(map, SPA_TYPE_META__Cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaPipeWireSource *
|
static MetaPipeWireSource *
|
||||||
@ -466,6 +594,12 @@ create_pipewire_source (void)
|
|||||||
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
|
(MetaPipeWireSource *) g_source_new (&pipewire_source_funcs,
|
||||||
sizeof (MetaPipeWireSource));
|
sizeof (MetaPipeWireSource));
|
||||||
pipewire_source->pipewire_loop = pw_loop_new (NULL);
|
pipewire_source->pipewire_loop = pw_loop_new (NULL);
|
||||||
|
if (!pipewire_source->pipewire_loop)
|
||||||
|
{
|
||||||
|
g_source_destroy ((GSource *) pipewire_source);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_source_add_unix_fd (&pipewire_source->base,
|
g_source_add_unix_fd (&pipewire_source->base,
|
||||||
pw_loop_get_fd (pipewire_source->pipewire_loop),
|
pw_loop_get_fd (pipewire_source->pipewire_loop),
|
||||||
G_IO_IN | G_IO_ERR);
|
G_IO_IN | G_IO_ERR);
|
||||||
@ -491,6 +625,13 @@ meta_screen_cast_stream_src_initable_init (GInitable *initable,
|
|||||||
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 ();
|
||||||
|
if (!priv->pipewire_source)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Failed to create PipeWire source");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
|
priv->pipewire_core = pw_core_new (priv->pipewire_source->pipewire_loop,
|
||||||
NULL);
|
NULL);
|
||||||
if (!priv->pipewire_core)
|
if (!priv->pipewire_core)
|
||||||
|
@ -24,8 +24,25 @@
|
|||||||
#define META_SCREEN_CAST_STREAM_SRC_H
|
#define META_SCREEN_CAST_STREAM_SRC_H
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <spa/param/video/format-utils.h>
|
||||||
|
#include <spa/buffer/meta.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/meta-cursor-renderer.h"
|
||||||
|
#include "backends/meta-cursor.h"
|
||||||
|
#include "backends/meta-renderer.h"
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
|
#include "cogl/cogl.h"
|
||||||
|
#include "meta/boxes.h"
|
||||||
|
|
||||||
|
typedef struct _MetaSpaType
|
||||||
|
{
|
||||||
|
struct spa_type_media_type media_type;
|
||||||
|
struct spa_type_media_subtype media_subtype;
|
||||||
|
struct spa_type_format_video format_video;
|
||||||
|
struct spa_type_video_format video_format;
|
||||||
|
uint32_t meta_cursor;
|
||||||
|
} MetaSpaType;
|
||||||
|
|
||||||
typedef struct _MetaScreenCastStream MetaScreenCastStream;
|
typedef struct _MetaScreenCastStream MetaScreenCastStream;
|
||||||
|
|
||||||
@ -45,12 +62,18 @@ struct _MetaScreenCastStreamSrcClass
|
|||||||
float *frame_rate);
|
float *frame_rate);
|
||||||
void (* enable) (MetaScreenCastStreamSrc *src);
|
void (* enable) (MetaScreenCastStreamSrc *src);
|
||||||
void (* disable) (MetaScreenCastStreamSrc *src);
|
void (* disable) (MetaScreenCastStreamSrc *src);
|
||||||
void (* record_frame) (MetaScreenCastStreamSrc *src,
|
gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
|
||||||
uint8_t *data);
|
uint8_t *data);
|
||||||
|
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
|
||||||
|
MetaRectangle *crop_rect);
|
||||||
|
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
|
||||||
|
struct spa_meta_cursor *spa_meta_cursor);
|
||||||
};
|
};
|
||||||
|
|
||||||
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
|
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
|
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
|
MetaSpaType * meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src);
|
||||||
|
|
||||||
#endif /* META_SCREEN_CAST_STREAM_SRC_H */
|
#endif /* META_SCREEN_CAST_STREAM_SRC_H */
|
||||||
|
@ -24,13 +24,17 @@
|
|||||||
|
|
||||||
#include "backends/meta-screen-cast-stream.h"
|
#include "backends/meta-screen-cast-stream.h"
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-session.h"
|
||||||
|
|
||||||
#define META_SCREEN_CAST_STREAM_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Stream"
|
#define META_SCREEN_CAST_STREAM_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Stream"
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_0,
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_SESSION,
|
||||||
PROP_CONNECTION,
|
PROP_CONNECTION,
|
||||||
|
PROP_CURSOR_MODE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
@ -44,9 +48,13 @@ static guint signals[N_SIGNALS];
|
|||||||
|
|
||||||
typedef struct _MetaScreenCastStreamPrivate
|
typedef struct _MetaScreenCastStreamPrivate
|
||||||
{
|
{
|
||||||
|
MetaScreenCastSession *session;
|
||||||
|
|
||||||
GDBusConnection *connection;
|
GDBusConnection *connection;
|
||||||
char *object_path;
|
char *object_path;
|
||||||
|
|
||||||
|
MetaScreenCastCursorMode cursor_mode;
|
||||||
|
|
||||||
MetaScreenCastStreamSrc *src;
|
MetaScreenCastStreamSrc *src;
|
||||||
} MetaScreenCastStreamPrivate;
|
} MetaScreenCastStreamPrivate;
|
||||||
|
|
||||||
@ -97,6 +105,15 @@ on_stream_src_ready (MetaScreenCastStreamSrc *src,
|
|||||||
meta_dbus_screen_cast_stream_emit_pipewire_stream_added (skeleton, node_id);
|
meta_dbus_screen_cast_stream_emit_pipewire_stream_added (skeleton, node_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaScreenCastSession *
|
||||||
|
meta_screen_cast_stream_get_session (MetaScreenCastStream *stream)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamPrivate *priv =
|
||||||
|
meta_screen_cast_stream_get_instance_private (stream);
|
||||||
|
|
||||||
|
return priv->session;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_screen_cast_stream_start (MetaScreenCastStream *stream,
|
meta_screen_cast_stream_start (MetaScreenCastStream *stream,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -150,6 +167,15 @@ meta_screen_cast_stream_transform_position (MetaScreenCastStream *stream,
|
|||||||
y);
|
y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaScreenCastCursorMode
|
||||||
|
meta_screen_cast_stream_get_cursor_mode (MetaScreenCastStream *stream)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamPrivate *priv =
|
||||||
|
meta_screen_cast_stream_get_instance_private (stream);
|
||||||
|
|
||||||
|
return priv->cursor_mode;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_screen_cast_stream_set_property (GObject *object,
|
meta_screen_cast_stream_set_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -162,9 +188,15 @@ meta_screen_cast_stream_set_property (GObject *object,
|
|||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_SESSION:
|
||||||
|
priv->session = g_value_get_object (value);
|
||||||
|
break;
|
||||||
case PROP_CONNECTION:
|
case PROP_CONNECTION:
|
||||||
priv->connection = g_value_get_object (value);
|
priv->connection = g_value_get_object (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CURSOR_MODE:
|
||||||
|
priv->cursor_mode = g_value_get_uint (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -182,9 +214,15 @@ meta_screen_cast_stream_get_property (GObject *object,
|
|||||||
|
|
||||||
switch (prop_id)
|
switch (prop_id)
|
||||||
{
|
{
|
||||||
|
case PROP_SESSION:
|
||||||
|
g_value_set_object (value, priv->session);
|
||||||
|
break;
|
||||||
case PROP_CONNECTION:
|
case PROP_CONNECTION:
|
||||||
g_value_set_object (value, priv->connection);
|
g_value_set_object (value, priv->connection);
|
||||||
break;
|
break;
|
||||||
|
case PROP_CURSOR_MODE:
|
||||||
|
g_value_set_uint (value, priv->cursor_mode);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
}
|
}
|
||||||
@ -256,6 +294,16 @@ meta_screen_cast_stream_class_init (MetaScreenCastStreamClass *klass)
|
|||||||
object_class->set_property = meta_screen_cast_stream_set_property;
|
object_class->set_property = meta_screen_cast_stream_set_property;
|
||||||
object_class->get_property = meta_screen_cast_stream_get_property;
|
object_class->get_property = meta_screen_cast_stream_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_SESSION,
|
||||||
|
g_param_spec_object ("session",
|
||||||
|
"session",
|
||||||
|
"MetaScreenSession",
|
||||||
|
META_TYPE_SCREEN_CAST_SESSION,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
g_object_class_install_property (object_class,
|
g_object_class_install_property (object_class,
|
||||||
PROP_CONNECTION,
|
PROP_CONNECTION,
|
||||||
g_param_spec_object ("connection",
|
g_param_spec_object ("connection",
|
||||||
@ -266,6 +314,18 @@ meta_screen_cast_stream_class_init (MetaScreenCastStreamClass *klass)
|
|||||||
G_PARAM_CONSTRUCT_ONLY |
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
G_PARAM_STATIC_STRINGS));
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_CURSOR_MODE,
|
||||||
|
g_param_spec_uint ("cursor-mode",
|
||||||
|
"cursor-mode",
|
||||||
|
"Cursor mode",
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_HIDDEN,
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_METADATA,
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_HIDDEN,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
signals[CLOSED] = g_signal_new ("closed",
|
signals[CLOSED] = g_signal_new ("closed",
|
||||||
G_TYPE_FROM_CLASS (klass),
|
G_TYPE_FROM_CLASS (klass),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
|
@ -26,8 +26,12 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
#include "backends/meta-screen-cast-stream-src.h"
|
#include "backends/meta-screen-cast-stream-src.h"
|
||||||
|
#include "backends/meta-screen-cast.h"
|
||||||
|
|
||||||
#include "meta-dbus-screen-cast.h"
|
#include "meta-dbus-screen-cast.h"
|
||||||
|
|
||||||
|
typedef struct _MetaScreenCastSession MetaScreenCastSession;
|
||||||
|
|
||||||
#define META_TYPE_SCREEN_CAST_STREAM (meta_screen_cast_stream_get_type ())
|
#define META_TYPE_SCREEN_CAST_STREAM (meta_screen_cast_stream_get_type ())
|
||||||
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStream, meta_screen_cast_stream,
|
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStream, meta_screen_cast_stream,
|
||||||
META, SCREEN_CAST_STREAM,
|
META, SCREEN_CAST_STREAM,
|
||||||
@ -48,6 +52,8 @@ struct _MetaScreenCastStreamClass
|
|||||||
double *y);
|
double *y);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MetaScreenCastSession * meta_screen_cast_stream_get_session (MetaScreenCastStream *stream);
|
||||||
|
|
||||||
gboolean meta_screen_cast_stream_start (MetaScreenCastStream *stream,
|
gboolean meta_screen_cast_stream_start (MetaScreenCastStream *stream,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
@ -61,4 +67,6 @@ void meta_screen_cast_stream_transform_position (MetaScreenCastStream *stream,
|
|||||||
double *x,
|
double *x,
|
||||||
double *y);
|
double *y);
|
||||||
|
|
||||||
|
MetaScreenCastCursorMode meta_screen_cast_stream_get_cursor_mode (MetaScreenCastStream *stream);
|
||||||
|
|
||||||
#endif /* META_SCREEN_CAST_STREAM_H */
|
#endif /* META_SCREEN_CAST_STREAM_H */
|
||||||
|
247
src/backends/meta-screen-cast-window-stream-src.c
Normal file
247
src/backends/meta-screen-cast-window-stream-src.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-window-stream-src.h"
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/meta-screen-cast-window.h"
|
||||||
|
#include "backends/meta-screen-cast-window-stream.h"
|
||||||
|
#include "compositor/meta-window-actor-private.h"
|
||||||
|
|
||||||
|
struct _MetaScreenCastWindowStreamSrc
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc parent;
|
||||||
|
|
||||||
|
MetaWindowActor *window_actor;
|
||||||
|
|
||||||
|
unsigned long actor_painted_handler_id;
|
||||||
|
unsigned long actor_destroyed_handler_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaScreenCastWindowStreamSrc,
|
||||||
|
meta_screen_cast_window_stream_src,
|
||||||
|
META_TYPE_SCREEN_CAST_STREAM_SRC)
|
||||||
|
|
||||||
|
static MetaScreenCastWindowStream *
|
||||||
|
get_window_stream (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc *src;
|
||||||
|
MetaScreenCastStream *stream;
|
||||||
|
|
||||||
|
src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
||||||
|
stream = meta_screen_cast_stream_src_get_stream (src);
|
||||||
|
|
||||||
|
return META_SCREEN_CAST_WINDOW_STREAM (stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaWindow *
|
||||||
|
get_window (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream;
|
||||||
|
|
||||||
|
window_stream = get_window_stream (window_src);
|
||||||
|
|
||||||
|
return meta_screen_cast_window_stream_get_window (window_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_stream_width (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream;
|
||||||
|
|
||||||
|
window_stream = get_window_stream (window_src);
|
||||||
|
|
||||||
|
return meta_screen_cast_window_stream_get_width (window_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_stream_height (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream;
|
||||||
|
|
||||||
|
window_stream = get_window_stream (window_src);
|
||||||
|
|
||||||
|
return meta_screen_cast_window_stream_get_height (window_stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
capture_into (MetaScreenCastWindowStreamSrc *window_src,
|
||||||
|
uint8_t *data)
|
||||||
|
{
|
||||||
|
MetaRectangle stream_rect;
|
||||||
|
MetaScreenCastWindow *screen_cast_window;
|
||||||
|
|
||||||
|
stream_rect.x = 0;
|
||||||
|
stream_rect.y = 0;
|
||||||
|
stream_rect.width = get_stream_width (window_src);
|
||||||
|
stream_rect.height = get_stream_height (window_src);
|
||||||
|
|
||||||
|
screen_cast_window = META_SCREEN_CAST_WINDOW (window_src->window_actor);
|
||||||
|
meta_screen_cast_window_capture_into (screen_cast_window, &stream_rect, data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_get_specs (MetaScreenCastStreamSrc *src,
|
||||||
|
int *width,
|
||||||
|
int *height,
|
||||||
|
float *frame_rate)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
|
|
||||||
|
*width = get_stream_width (window_src);
|
||||||
|
*height = get_stream_height (window_src);
|
||||||
|
*frame_rate = 60.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_screen_cast_window_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
|
||||||
|
MetaRectangle *crop_rect)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
|
MetaScreenCastWindow *screen_cast_window;
|
||||||
|
MetaRectangle stream_rect;
|
||||||
|
|
||||||
|
screen_cast_window = META_SCREEN_CAST_WINDOW (window_src->window_actor);
|
||||||
|
meta_screen_cast_window_get_frame_bounds (screen_cast_window, crop_rect);
|
||||||
|
|
||||||
|
stream_rect.x = 0;
|
||||||
|
stream_rect.y = 0;
|
||||||
|
stream_rect.width = get_stream_width (window_src);
|
||||||
|
stream_rect.height = get_stream_height (window_src);
|
||||||
|
|
||||||
|
meta_rectangle_intersect (crop_rect, &stream_rect, crop_rect);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (!window_src->window_actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (window_src->actor_painted_handler_id)
|
||||||
|
g_signal_handler_disconnect (window_src->window_actor,
|
||||||
|
window_src->actor_painted_handler_id);
|
||||||
|
window_src->actor_painted_handler_id = 0;
|
||||||
|
|
||||||
|
if (window_src->actor_destroyed_handler_id)
|
||||||
|
g_signal_handler_disconnect (window_src->window_actor,
|
||||||
|
window_src->actor_destroyed_handler_id);
|
||||||
|
window_src->actor_destroyed_handler_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_actor_painted (MetaWindowActor *actor,
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
|
||||||
|
|
||||||
|
meta_screen_cast_stream_src_maybe_record_frame (src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
window_actor_destroyed (MetaWindowActor *actor,
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
meta_screen_cast_window_stream_src_stop (window_src);
|
||||||
|
window_src->window_actor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
|
MetaWindowActor *window_actor;
|
||||||
|
|
||||||
|
window_actor = meta_window_actor_from_window (get_window (window_src));
|
||||||
|
if (!window_actor)
|
||||||
|
return;
|
||||||
|
|
||||||
|
window_src->window_actor = window_actor;
|
||||||
|
|
||||||
|
window_src->actor_painted_handler_id =
|
||||||
|
g_signal_connect_after (window_src->window_actor,
|
||||||
|
"paint",
|
||||||
|
G_CALLBACK (window_actor_painted),
|
||||||
|
window_src);
|
||||||
|
|
||||||
|
window_src->actor_destroyed_handler_id =
|
||||||
|
g_signal_connect (window_src->window_actor,
|
||||||
|
"destroy",
|
||||||
|
G_CALLBACK (window_actor_destroyed),
|
||||||
|
window_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
|
|
||||||
|
meta_screen_cast_window_stream_src_stop (window_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
|
||||||
|
uint8_t *data)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStreamSrc *window_src =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
|
||||||
|
|
||||||
|
capture_into (window_src, data);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaScreenCastWindowStreamSrc *
|
||||||
|
meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stream,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM_SRC, NULL, error,
|
||||||
|
"stream", window_stream,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_init (MetaScreenCastWindowStreamSrc *window_src)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClass *klass)
|
||||||
|
{
|
||||||
|
MetaScreenCastStreamSrcClass *src_class =
|
||||||
|
META_SCREEN_CAST_STREAM_SRC_CLASS (klass);
|
||||||
|
|
||||||
|
src_class->get_specs = meta_screen_cast_window_stream_src_get_specs;
|
||||||
|
src_class->enable = meta_screen_cast_window_stream_src_enable;
|
||||||
|
src_class->disable = meta_screen_cast_window_stream_src_disable;
|
||||||
|
src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
|
||||||
|
src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop;
|
||||||
|
}
|
37
src/backends/meta-screen-cast-window-stream-src.h
Normal file
37
src/backends/meta-screen-cast-window-stream-src.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_SCREEN_CAST_WINDOW_STREAM_SRC_H
|
||||||
|
#define META_SCREEN_CAST_WINDOW_STREAM_SRC_H
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-stream-src.h"
|
||||||
|
|
||||||
|
typedef struct _MetaScreenCastWindowStream MetaScreenCastWindowStream;
|
||||||
|
|
||||||
|
#define META_TYPE_SCREEN_CAST_WINDOW_STREAM_SRC (meta_screen_cast_window_stream_src_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaScreenCastWindowStreamSrc,
|
||||||
|
meta_screen_cast_window_stream_src,
|
||||||
|
META, SCREEN_CAST_WINDOW_STREAM_SRC,
|
||||||
|
MetaScreenCastStreamSrc)
|
||||||
|
|
||||||
|
MetaScreenCastWindowStreamSrc * meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stream,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
#endif /* META_SCREEN_CAST_WINDOW_STREAM_SRC_H */
|
272
src/backends/meta-screen-cast-window-stream.c
Normal file
272
src/backends/meta-screen-cast-window-stream.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-window-stream.h"
|
||||||
|
|
||||||
|
#include "backends/meta-logical-monitor.h"
|
||||||
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
|
#include "backends/meta-screen-cast-window.h"
|
||||||
|
#include "backends/meta-screen-cast-window-stream-src.h"
|
||||||
|
#include "compositor/meta-window-actor-private.h"
|
||||||
|
#include "core/window-private.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_WINDOW,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MetaScreenCastWindowStream
|
||||||
|
{
|
||||||
|
MetaScreenCastStream parent;
|
||||||
|
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
|
int stream_width;
|
||||||
|
int stream_height;
|
||||||
|
|
||||||
|
unsigned long window_unmanaged_handler_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MetaScreenCastWindowStream,
|
||||||
|
meta_screen_cast_window_stream,
|
||||||
|
META_TYPE_SCREEN_CAST_STREAM)
|
||||||
|
|
||||||
|
MetaWindow *
|
||||||
|
meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream)
|
||||||
|
{
|
||||||
|
return window_stream->window;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
meta_screen_cast_window_stream_get_width (MetaScreenCastWindowStream *window_stream)
|
||||||
|
{
|
||||||
|
return window_stream->stream_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
meta_screen_cast_window_stream_get_height (MetaScreenCastWindowStream *window_stream)
|
||||||
|
{
|
||||||
|
return window_stream->stream_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetaScreenCastWindowStream *
|
||||||
|
meta_screen_cast_window_stream_new (MetaScreenCastSession *session,
|
||||||
|
GDBusConnection *connection,
|
||||||
|
MetaWindow *window,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream;
|
||||||
|
MetaLogicalMonitor *logical_monitor;
|
||||||
|
int scale;
|
||||||
|
|
||||||
|
logical_monitor = meta_window_get_main_logical_monitor (window);
|
||||||
|
if (!logical_monitor)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"Main logical monitor not found");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
window_stream = g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM,
|
||||||
|
NULL,
|
||||||
|
error,
|
||||||
|
"session", session,
|
||||||
|
"connection", connection,
|
||||||
|
"window", window,
|
||||||
|
NULL);
|
||||||
|
if (!window_stream)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
window_stream->window = window;
|
||||||
|
/* We cannot set the stream size to the exact size of the window, because
|
||||||
|
* windows can be resized, whereas streams cannot.
|
||||||
|
* So we set a size equals to the size of the logical monitor for the window.
|
||||||
|
*/
|
||||||
|
scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor));
|
||||||
|
window_stream->stream_width = logical_monitor->rect.width * scale;
|
||||||
|
window_stream->stream_height = logical_monitor->rect.height * scale;
|
||||||
|
|
||||||
|
return window_stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MetaScreenCastStreamSrc *
|
||||||
|
meta_screen_cast_window_stream_create_src (MetaScreenCastStream *stream,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (stream);
|
||||||
|
MetaScreenCastWindowStreamSrc *window_stream_src;
|
||||||
|
|
||||||
|
window_stream_src = meta_screen_cast_window_stream_src_new (window_stream,
|
||||||
|
error);
|
||||||
|
if (!window_stream_src)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return META_SCREEN_CAST_STREAM_SRC (window_stream_src);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_set_parameters (MetaScreenCastStream *stream,
|
||||||
|
GVariantBuilder *parameters_builder)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (stream);
|
||||||
|
MetaScreenCastWindow *screen_cast_window =
|
||||||
|
META_SCREEN_CAST_WINDOW (meta_window_actor_from_window (window_stream->window));
|
||||||
|
MetaRectangle bounds;
|
||||||
|
|
||||||
|
meta_screen_cast_window_get_buffer_bounds (screen_cast_window, &bounds);
|
||||||
|
|
||||||
|
g_variant_builder_add (parameters_builder, "{sv}",
|
||||||
|
"position",
|
||||||
|
g_variant_new ("(ii)",
|
||||||
|
bounds.x, bounds.y));
|
||||||
|
|
||||||
|
g_variant_builder_add (parameters_builder, "{sv}",
|
||||||
|
"size",
|
||||||
|
g_variant_new ("(ii)",
|
||||||
|
bounds.width,
|
||||||
|
bounds.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_transform_position (MetaScreenCastStream *stream,
|
||||||
|
double stream_x,
|
||||||
|
double stream_y,
|
||||||
|
double *x,
|
||||||
|
double *y)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (stream);
|
||||||
|
MetaScreenCastWindow *screen_cast_window =
|
||||||
|
META_SCREEN_CAST_WINDOW (meta_window_actor_from_window (window_stream->window));
|
||||||
|
|
||||||
|
meta_screen_cast_window_transform_relative_position (screen_cast_window,
|
||||||
|
stream_x,
|
||||||
|
stream_y,
|
||||||
|
x,
|
||||||
|
y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_window_unmanaged (MetaScreenCastWindowStream *window_stream)
|
||||||
|
{
|
||||||
|
meta_screen_cast_stream_close (META_SCREEN_CAST_STREAM (window_stream));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (object);
|
||||||
|
|
||||||
|
window_stream->window_unmanaged_handler_id =
|
||||||
|
g_signal_connect_swapped (window_stream->window, "unmanaged",
|
||||||
|
G_CALLBACK (on_window_unmanaged),
|
||||||
|
window_stream);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_screen_cast_window_stream_parent_class)->constructed (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_WINDOW:
|
||||||
|
window_stream->window = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_WINDOW:
|
||||||
|
g_value_set_object (value, window_stream->window);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_finalize (GObject *object)
|
||||||
|
{
|
||||||
|
MetaScreenCastWindowStream *window_stream =
|
||||||
|
META_SCREEN_CAST_WINDOW_STREAM (object);
|
||||||
|
|
||||||
|
g_signal_handler_disconnect (window_stream->window,
|
||||||
|
window_stream->window_unmanaged_handler_id);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (meta_screen_cast_window_stream_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_init (MetaScreenCastWindowStream *window_stream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_stream_class_init (MetaScreenCastWindowStreamClass *klass)
|
||||||
|
{
|
||||||
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
MetaScreenCastStreamClass *stream_class =
|
||||||
|
META_SCREEN_CAST_STREAM_CLASS (klass);
|
||||||
|
|
||||||
|
object_class->constructed = meta_screen_cast_window_stream_constructed;
|
||||||
|
object_class->set_property = meta_screen_cast_window_stream_set_property;
|
||||||
|
object_class->get_property = meta_screen_cast_window_stream_get_property;
|
||||||
|
object_class->finalize = meta_screen_cast_window_stream_finalize;
|
||||||
|
|
||||||
|
stream_class->create_src = meta_screen_cast_window_stream_create_src;
|
||||||
|
stream_class->set_parameters = meta_screen_cast_window_stream_set_parameters;
|
||||||
|
stream_class->transform_position = meta_screen_cast_window_stream_transform_position;
|
||||||
|
|
||||||
|
g_object_class_install_property (object_class,
|
||||||
|
PROP_WINDOW,
|
||||||
|
g_param_spec_object ("window",
|
||||||
|
"window",
|
||||||
|
"MetaWindow",
|
||||||
|
META_TYPE_WINDOW,
|
||||||
|
G_PARAM_READWRITE |
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
44
src/backends/meta-screen-cast-window-stream.h
Normal file
44
src/backends/meta-screen-cast-window-stream.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_SCREEN_CAST_WINDOW_STREAM_H
|
||||||
|
#define META_SCREEN_CAST_WINDOW_STREAM_H
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-stream.h"
|
||||||
|
#include "meta/window.h"
|
||||||
|
|
||||||
|
#define META_TYPE_SCREEN_CAST_WINDOW_STREAM (meta_screen_cast_window_stream_get_type ())
|
||||||
|
G_DECLARE_FINAL_TYPE (MetaScreenCastWindowStream,
|
||||||
|
meta_screen_cast_window_stream,
|
||||||
|
META, SCREEN_CAST_WINDOW_STREAM,
|
||||||
|
MetaScreenCastStream)
|
||||||
|
|
||||||
|
MetaScreenCastWindowStream * meta_screen_cast_window_stream_new (MetaScreenCastSession *session,
|
||||||
|
GDBusConnection *connection,
|
||||||
|
MetaWindow *window,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
MetaWindow * meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream);
|
||||||
|
int meta_screen_cast_window_stream_get_width (MetaScreenCastWindowStream *window_stream);
|
||||||
|
int meta_screen_cast_window_stream_get_height (MetaScreenCastWindowStream *window_stream);
|
||||||
|
|
||||||
|
#endif /* META_SCREEN_CAST_WINDOW_STREAM_H */
|
71
src/backends/meta-screen-cast-window.c
Normal file
71
src/backends/meta-screen-cast-window.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "backends/meta-screen-cast-window.h"
|
||||||
|
|
||||||
|
G_DEFINE_INTERFACE (MetaScreenCastWindow, meta_screen_cast_window, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_screen_cast_window_default_init (MetaScreenCastWindowInterface *iface)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds)
|
||||||
|
{
|
||||||
|
META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_buffer_bounds (screen_cast_window,
|
||||||
|
bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds)
|
||||||
|
{
|
||||||
|
META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_frame_bounds (screen_cast_window,
|
||||||
|
bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double *x_out,
|
||||||
|
double *y_out)
|
||||||
|
{
|
||||||
|
META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->transform_relative_position (screen_cast_window,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
x_out,
|
||||||
|
y_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds,
|
||||||
|
uint8_t *data)
|
||||||
|
{
|
||||||
|
META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->capture_into (screen_cast_window,
|
||||||
|
bounds,
|
||||||
|
data);
|
||||||
|
}
|
74
src/backends/meta-screen-cast-window.h
Normal file
74
src/backends/meta-screen-cast-window.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef META_SCREEN_CAST_WINDOW_H
|
||||||
|
#define META_SCREEN_CAST_WINDOW_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "meta/boxes.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define META_TYPE_SCREEN_CAST_WINDOW (meta_screen_cast_window_get_type ())
|
||||||
|
G_DECLARE_INTERFACE (MetaScreenCastWindow, meta_screen_cast_window,
|
||||||
|
META, SCREEN_CAST_WINDOW, GObject)
|
||||||
|
|
||||||
|
struct _MetaScreenCastWindowInterface
|
||||||
|
{
|
||||||
|
GTypeInterface parent_iface;
|
||||||
|
|
||||||
|
void (*get_buffer_bounds) (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds);
|
||||||
|
|
||||||
|
void (*get_frame_bounds) (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds);
|
||||||
|
|
||||||
|
void (*transform_relative_position) (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double *x_out,
|
||||||
|
double *y_out);
|
||||||
|
|
||||||
|
void (*capture_into) (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds,
|
||||||
|
uint8_t *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
void meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds);
|
||||||
|
|
||||||
|
void meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds);
|
||||||
|
|
||||||
|
void meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double *x_out,
|
||||||
|
double *y_out);
|
||||||
|
|
||||||
|
void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window,
|
||||||
|
MetaRectangle *bounds,
|
||||||
|
uint8_t *data);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* META_SCREEN_CAST_WINDOW_H */
|
@ -43,6 +43,7 @@ struct _MetaScreenCast
|
|||||||
GList *sessions;
|
GList *sessions;
|
||||||
|
|
||||||
MetaDbusSessionWatcher *session_watcher;
|
MetaDbusSessionWatcher *session_watcher;
|
||||||
|
MetaBackend *backend;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -62,12 +63,20 @@ meta_screen_cast_get_connection (MetaScreenCast *screen_cast)
|
|||||||
return g_dbus_interface_skeleton_get_connection (interface_skeleton);
|
return g_dbus_interface_skeleton_get_connection (interface_skeleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetaBackend *
|
||||||
|
meta_screen_cast_get_backend (MetaScreenCast *screen_cast)
|
||||||
|
{
|
||||||
|
return screen_cast->backend;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
register_remote_desktop_screen_cast_session (MetaScreenCastSession *session,
|
register_remote_desktop_screen_cast_session (MetaScreenCastSession *session,
|
||||||
const char *remote_desktop_session_id,
|
const char *remote_desktop_session_id,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaBackend *backend = meta_get_backend ();
|
MetaScreenCast *screen_cast =
|
||||||
|
meta_screen_cast_session_get_screen_cast (session);
|
||||||
|
MetaBackend *backend = meta_screen_cast_get_backend (screen_cast);
|
||||||
MetaRemoteDesktop *remote_desktop = meta_backend_get_remote_desktop (backend);
|
MetaRemoteDesktop *remote_desktop = meta_backend_get_remote_desktop (backend);
|
||||||
MetaRemoteDesktopSession *remote_desktop_session;
|
MetaRemoteDesktopSession *remote_desktop_session;
|
||||||
|
|
||||||
@ -244,11 +253,13 @@ meta_screen_cast_finalize (GObject *object)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MetaScreenCast *
|
MetaScreenCast *
|
||||||
meta_screen_cast_new (MetaDbusSessionWatcher *session_watcher)
|
meta_screen_cast_new (MetaBackend *backend,
|
||||||
|
MetaDbusSessionWatcher *session_watcher)
|
||||||
{
|
{
|
||||||
MetaScreenCast *screen_cast;
|
MetaScreenCast *screen_cast;
|
||||||
|
|
||||||
screen_cast = g_object_new (META_TYPE_SCREEN_CAST, NULL);
|
screen_cast = g_object_new (META_TYPE_SCREEN_CAST, NULL);
|
||||||
|
screen_cast->backend = backend;
|
||||||
screen_cast->session_watcher = session_watcher;
|
screen_cast->session_watcher = session_watcher;
|
||||||
|
|
||||||
return screen_cast;
|
return screen_cast;
|
||||||
|
@ -25,9 +25,17 @@
|
|||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "backends/meta-backend-private.h"
|
||||||
#include "backends/meta-dbus-session-watcher.h"
|
#include "backends/meta-dbus-session-watcher.h"
|
||||||
#include "meta-dbus-screen-cast.h"
|
#include "meta-dbus-screen-cast.h"
|
||||||
|
|
||||||
|
typedef enum _MetaScreenCastCursorMode
|
||||||
|
{
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_HIDDEN = 0,
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_EMBEDDED = 1,
|
||||||
|
META_SCREEN_CAST_CURSOR_MODE_METADATA = 2,
|
||||||
|
} MetaScreenCastCursorMode;
|
||||||
|
|
||||||
#define META_TYPE_SCREEN_CAST (meta_screen_cast_get_type ())
|
#define META_TYPE_SCREEN_CAST (meta_screen_cast_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
|
G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
|
||||||
META, SCREEN_CAST,
|
META, SCREEN_CAST,
|
||||||
@ -35,6 +43,9 @@ G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
|
|||||||
|
|
||||||
GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast);
|
GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast);
|
||||||
|
|
||||||
MetaScreenCast * meta_screen_cast_new (MetaDbusSessionWatcher *session_watcher);
|
MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast);
|
||||||
|
|
||||||
|
MetaScreenCast * meta_screen_cast_new (MetaBackend *backend,
|
||||||
|
MetaDbusSessionWatcher *session_watcher);
|
||||||
|
|
||||||
#endif /* META_SCREEN_CAST_H */
|
#endif /* META_SCREEN_CAST_H */
|
||||||
|
@ -31,8 +31,7 @@ typedef enum _MetaExperimentalFeature
|
|||||||
{
|
{
|
||||||
META_EXPERIMENTAL_FEATURE_NONE = 0,
|
META_EXPERIMENTAL_FEATURE_NONE = 0,
|
||||||
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0),
|
META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER = (1 << 0),
|
||||||
META_EXPERIMENTAL_FEATURE_SCREEN_CAST = (1 << 1),
|
META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS = (1 << 1),
|
||||||
META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP = (1 << 2),
|
|
||||||
} MetaExperimentalFeature;
|
} MetaExperimentalFeature;
|
||||||
|
|
||||||
#define META_TYPE_SETTINGS (meta_settings_get_type ())
|
#define META_TYPE_SETTINGS (meta_settings_get_type ())
|
||||||
|
@ -263,10 +263,8 @@ experimental_features_handler (GVariant *features_variant,
|
|||||||
/* So far no experimental features defined. */
|
/* So far no experimental features defined. */
|
||||||
if (g_str_equal (feature, "scale-monitor-framebuffer"))
|
if (g_str_equal (feature, "scale-monitor-framebuffer"))
|
||||||
features |= META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER;
|
features |= META_EXPERIMENTAL_FEATURE_SCALE_MONITOR_FRAMEBUFFER;
|
||||||
else if (g_str_equal (feature, "screen-cast"))
|
else if (g_str_equal (feature, "kms-modifiers"))
|
||||||
features |= META_EXPERIMENTAL_FEATURE_SCREEN_CAST;
|
features |= META_EXPERIMENTAL_FEATURE_KMS_MODIFIERS;
|
||||||
else if (g_str_equal (feature, "remote-desktop"))
|
|
||||||
features |= META_EXPERIMENTAL_FEATURE_REMOTE_DESKTOP;
|
|
||||||
else
|
else
|
||||||
g_info ("Unknown experimental feature '%s'\n", feature);
|
g_info ("Unknown experimental feature '%s'\n", feature);
|
||||||
}
|
}
|
||||||
|
@ -17,39 +17,23 @@
|
|||||||
* 02111-1307, USA.
|
* 02111-1307, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef META_STAGE_H
|
#ifndef META_STAGE_PRIVATE_H
|
||||||
#define META_STAGE_H
|
#define META_STAGE_PRIVATE_H
|
||||||
|
|
||||||
#include <clutter/clutter.h>
|
#include <meta/meta-stage.h>
|
||||||
|
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
#include <meta/boxes.h>
|
#include <meta/boxes.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define META_TYPE_STAGE (meta_stage_get_type ())
|
|
||||||
#define META_STAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_STAGE, MetaStage))
|
|
||||||
#define META_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_STAGE, MetaStageClass))
|
|
||||||
#define META_IS_STAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_STAGE))
|
|
||||||
#define META_IS_STAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_STAGE))
|
|
||||||
#define META_STAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_STAGE, MetaStageClass))
|
|
||||||
|
|
||||||
typedef struct _MetaStage MetaStage;
|
|
||||||
typedef struct _MetaStageClass MetaStageClass;
|
|
||||||
typedef struct _MetaOverlay MetaOverlay;
|
typedef struct _MetaOverlay MetaOverlay;
|
||||||
|
|
||||||
struct _MetaStageClass
|
|
||||||
{
|
|
||||||
ClutterStageClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaStage
|
struct _MetaStage
|
||||||
{
|
{
|
||||||
ClutterStage parent;
|
ClutterStage parent;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType meta_stage_get_type (void) G_GNUC_CONST;
|
|
||||||
|
|
||||||
ClutterActor *meta_stage_new (void);
|
ClutterActor *meta_stage_new (void);
|
||||||
|
|
||||||
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
|
MetaOverlay *meta_stage_create_cursor_overlay (MetaStage *stage);
|
||||||
@ -68,4 +52,4 @@ void meta_stage_update_view_layout (MetaStage *stage);
|
|||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* META_STAGE_H */
|
#endif /* META_STAGE_PRIVATE_H */
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include "meta-stage.h"
|
#include "meta-stage-private.h"
|
||||||
|
|
||||||
#include <meta/meta-backend.h>
|
#include <meta/meta-backend.h>
|
||||||
#include <meta/meta-monitor-manager.h>
|
#include <meta/meta-monitor-manager.h>
|
||||||
@ -30,7 +30,17 @@
|
|||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
#include "clutter/clutter-mutter.h"
|
#include "clutter/clutter-mutter.h"
|
||||||
|
|
||||||
struct _MetaOverlay {
|
enum
|
||||||
|
{
|
||||||
|
ACTORS_PAINTED,
|
||||||
|
|
||||||
|
N_SIGNALS
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[N_SIGNALS];
|
||||||
|
|
||||||
|
struct _MetaOverlay
|
||||||
|
{
|
||||||
gboolean enabled;
|
gboolean enabled;
|
||||||
|
|
||||||
CoglPipeline *pipeline;
|
CoglPipeline *pipeline;
|
||||||
@ -140,6 +150,8 @@ meta_stage_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
|
||||||
|
|
||||||
|
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
|
||||||
|
|
||||||
for (l = priv->overlays; l; l = l->next)
|
for (l = priv->overlays; l; l = l->next)
|
||||||
meta_overlay_paint (l->data);
|
meta_overlay_paint (l->data);
|
||||||
}
|
}
|
||||||
@ -179,6 +191,13 @@ meta_stage_class_init (MetaStageClass *klass)
|
|||||||
|
|
||||||
stage_class->activate = meta_stage_activate;
|
stage_class->activate = meta_stage_activate;
|
||||||
stage_class->deactivate = meta_stage_deactivate;
|
stage_class->deactivate = meta_stage_deactivate;
|
||||||
|
|
||||||
|
signals[ACTORS_PAINTED] = g_signal_new ("actors-painted",
|
||||||
|
G_TYPE_FROM_CLASS (klass),
|
||||||
|
G_SIGNAL_RUN_LAST,
|
||||||
|
0,
|
||||||
|
NULL, NULL, NULL,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -35,15 +35,15 @@
|
|||||||
#include "clutter/evdev/clutter-evdev.h"
|
#include "clutter/evdev/clutter-evdev.h"
|
||||||
#include "meta-barrier-native.h"
|
#include "meta-barrier-native.h"
|
||||||
#include "meta-border.h"
|
#include "meta-border.h"
|
||||||
#include "meta-idle-monitor-native.h"
|
|
||||||
#include "meta-monitor-manager-kms.h"
|
#include "meta-monitor-manager-kms.h"
|
||||||
#include "meta-cursor-renderer-native.h"
|
#include "meta-cursor-renderer-native.h"
|
||||||
#include "meta-launcher.h"
|
#include "meta-launcher.h"
|
||||||
#include "backends/meta-cursor-tracker-private.h"
|
#include "backends/meta-cursor-tracker-private.h"
|
||||||
|
#include "backends/meta-idle-monitor-private.h"
|
||||||
#include "backends/meta-logical-monitor.h"
|
#include "backends/meta-logical-monitor.h"
|
||||||
#include "backends/meta-monitor-manager-private.h"
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
#include "backends/meta-pointer-constraint.h"
|
#include "backends/meta-pointer-constraint.h"
|
||||||
#include "backends/meta-stage.h"
|
#include "backends/meta-stage-private.h"
|
||||||
#include "backends/native/meta-clutter-backend-native.h"
|
#include "backends/native/meta-clutter-backend-native.h"
|
||||||
#include "backends/native/meta-input-settings-native.h"
|
#include "backends/native/meta-input-settings-native.h"
|
||||||
#include "backends/native/meta-renderer-native.h"
|
#include "backends/native/meta-renderer-native.h"
|
||||||
@ -60,10 +60,6 @@ struct _MetaBackendNativePrivate
|
|||||||
{
|
{
|
||||||
MetaLauncher *launcher;
|
MetaLauncher *launcher;
|
||||||
MetaBarrierManagerNative *barrier_manager;
|
MetaBarrierManagerNative *barrier_manager;
|
||||||
UpClient *up_client;
|
|
||||||
guint sleep_signal_id;
|
|
||||||
GCancellable *cancellable;
|
|
||||||
GDBusConnection *system_bus;
|
|
||||||
};
|
};
|
||||||
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
typedef struct _MetaBackendNativePrivate MetaBackendNativePrivate;
|
||||||
|
|
||||||
@ -85,69 +81,9 @@ meta_backend_native_finalize (GObject *object)
|
|||||||
|
|
||||||
meta_launcher_free (priv->launcher);
|
meta_launcher_free (priv->launcher);
|
||||||
|
|
||||||
g_object_unref (priv->up_client);
|
|
||||||
if (priv->sleep_signal_id)
|
|
||||||
g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id);
|
|
||||||
g_cancellable_cancel (priv->cancellable);
|
|
||||||
g_clear_object (&priv->cancellable);
|
|
||||||
g_clear_object (&priv->system_bus);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
|
G_OBJECT_CLASS (meta_backend_native_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
prepare_for_sleep_cb (GDBusConnection *connection,
|
|
||||||
const gchar *sender_name,
|
|
||||||
const gchar *object_path,
|
|
||||||
const gchar *interface_name,
|
|
||||||
const gchar *signal_name,
|
|
||||||
GVariant *parameters,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
gboolean suspending;
|
|
||||||
g_variant_get (parameters, "(b)", &suspending);
|
|
||||||
if (suspending)
|
|
||||||
return;
|
|
||||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
system_bus_gotten_cb (GObject *object,
|
|
||||||
GAsyncResult *res,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaBackendNativePrivate *priv;
|
|
||||||
GDBusConnection *bus;
|
|
||||||
|
|
||||||
bus = g_bus_get_finish (res, NULL);
|
|
||||||
if (!bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
priv = meta_backend_native_get_instance_private (META_BACKEND_NATIVE (user_data));
|
|
||||||
priv->system_bus = bus;
|
|
||||||
priv->sleep_signal_id = g_dbus_connection_signal_subscribe (priv->system_bus,
|
|
||||||
"org.freedesktop.login1",
|
|
||||||
"org.freedesktop.login1.Manager",
|
|
||||||
"PrepareForSleep",
|
|
||||||
"/org/freedesktop/login1",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
|
||||||
prepare_for_sleep_cb,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
lid_is_closed_changed_cb (UpClient *client,
|
|
||||||
GParamSpec *pspec,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
if (up_client_get_lid_is_closed (client))
|
|
||||||
return;
|
|
||||||
|
|
||||||
meta_idle_monitor_native_reset_idletime (meta_idle_monitor_get_core ());
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
constrain_to_barriers (ClutterInputDevice *device,
|
constrain_to_barriers (ClutterInputDevice *device,
|
||||||
guint32 time,
|
guint32 time,
|
||||||
@ -398,15 +334,6 @@ meta_backend_native_post_init (MetaBackend *backend)
|
|||||||
meta_backend_get_monitor_manager (backend));
|
meta_backend_get_monitor_manager (backend));
|
||||||
}
|
}
|
||||||
|
|
||||||
static MetaIdleMonitor *
|
|
||||||
meta_backend_native_create_idle_monitor (MetaBackend *backend,
|
|
||||||
int device_id)
|
|
||||||
{
|
|
||||||
return g_object_new (META_TYPE_IDLE_MONITOR_NATIVE,
|
|
||||||
"device-id", device_id,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaMonitorManager *
|
static MetaMonitorManager *
|
||||||
meta_backend_native_create_monitor_manager (MetaBackend *backend,
|
meta_backend_native_create_monitor_manager (MetaBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -604,7 +531,6 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
|
|||||||
|
|
||||||
backend_class->post_init = meta_backend_native_post_init;
|
backend_class->post_init = meta_backend_native_post_init;
|
||||||
|
|
||||||
backend_class->create_idle_monitor = meta_backend_native_create_idle_monitor;
|
|
||||||
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
backend_class->create_monitor_manager = meta_backend_native_create_monitor_manager;
|
||||||
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
backend_class->create_cursor_renderer = meta_backend_native_create_cursor_renderer;
|
||||||
backend_class->create_renderer = meta_backend_native_create_renderer;
|
backend_class->create_renderer = meta_backend_native_create_renderer;
|
||||||
@ -637,16 +563,6 @@ meta_backend_native_init (MetaBackendNative *native)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv->barrier_manager = meta_barrier_manager_native_new ();
|
priv->barrier_manager = meta_barrier_manager_native_new ();
|
||||||
|
|
||||||
priv->up_client = up_client_new ();
|
|
||||||
g_signal_connect (priv->up_client, "notify::lid-is-closed",
|
|
||||||
G_CALLBACK (lid_is_closed_changed_cb), NULL);
|
|
||||||
|
|
||||||
priv->cancellable = g_cancellable_new ();
|
|
||||||
g_bus_get (G_BUS_TYPE_SYSTEM,
|
|
||||||
priv->cancellable,
|
|
||||||
system_bus_gotten_cb,
|
|
||||||
native);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaLauncher *
|
MetaLauncher *
|
||||||
@ -729,11 +645,20 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
|||||||
meta_backend_get_monitor_manager (backend);
|
meta_backend_get_monitor_manager (backend);
|
||||||
MetaMonitorManagerKms *monitor_manager_kms =
|
MetaMonitorManagerKms *monitor_manager_kms =
|
||||||
META_MONITOR_MANAGER_KMS (monitor_manager);
|
META_MONITOR_MANAGER_KMS (monitor_manager);
|
||||||
MetaCursorRenderer *cursor_renderer;
|
MetaDisplay *display = meta_get_display ();
|
||||||
MetaCursorRendererNative *cursor_renderer_native;
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
ClutterActor *stage;
|
ClutterActor *stage;
|
||||||
MetaIdleMonitor *idle_monitor;
|
MetaIdleMonitor *idle_monitor;
|
||||||
|
|
||||||
|
if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
|
||||||
|
{
|
||||||
|
clutter_clear_glyph_cache ();
|
||||||
|
meta_screen_update_cursor (display->screen);
|
||||||
|
g_signal_emit_by_name (display, "gl-video-memory-purged");
|
||||||
|
}
|
||||||
|
|
||||||
meta_monitor_manager_kms_resume (monitor_manager_kms);
|
meta_monitor_manager_kms_resume (monitor_manager_kms);
|
||||||
|
|
||||||
clutter_evdev_reclaim_devices ();
|
clutter_evdev_reclaim_devices ();
|
||||||
@ -742,10 +667,6 @@ void meta_backend_native_resume (MetaBackendNative *native)
|
|||||||
stage = meta_backend_get_stage (backend);
|
stage = meta_backend_get_stage (backend);
|
||||||
clutter_actor_queue_redraw (stage);
|
clutter_actor_queue_redraw (stage);
|
||||||
|
|
||||||
cursor_renderer = meta_backend_get_cursor_renderer (backend);
|
|
||||||
cursor_renderer_native = META_CURSOR_RENDERER_NATIVE (cursor_renderer);
|
|
||||||
meta_cursor_renderer_native_force_update (cursor_renderer_native);
|
|
||||||
|
|
||||||
idle_monitor = meta_backend_get_idle_monitor (backend, 0);
|
idle_monitor = meta_backend_get_idle_monitor (backend, 0);
|
||||||
meta_idle_monitor_native_reset_idletime (idle_monitor);
|
meta_idle_monitor_reset_idletime (idle_monitor);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include <meta/meta-backend.h>
|
#include <meta/meta-backend.h>
|
||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
|
#include "backends/meta-cursor-sprite-xcursor.h"
|
||||||
#include "backends/meta-logical-monitor.h"
|
#include "backends/meta-logical-monitor.h"
|
||||||
#include "backends/meta-monitor.h"
|
#include "backends/meta-monitor.h"
|
||||||
#include "backends/meta-monitor-manager-private.h"
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
@ -43,6 +44,11 @@
|
|||||||
#include "core/boxes-private.h"
|
#include "core/boxes-private.h"
|
||||||
#include "meta/boxes.h"
|
#include "meta/boxes.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
|
#include "wayland/meta-cursor-sprite-wayland.h"
|
||||||
|
#include "wayland/meta-wayland-buffer.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||||
#define DRM_CAP_CURSOR_WIDTH 0x8
|
#define DRM_CAP_CURSOR_WIDTH 0x8
|
||||||
#endif
|
#endif
|
||||||
@ -113,6 +119,11 @@ static GQuark quark_cursor_renderer_native_gpu_data = 0;
|
|||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER);
|
||||||
|
|
||||||
|
static void
|
||||||
|
realize_cursor_sprite (MetaCursorRenderer *renderer,
|
||||||
|
MetaCursorSprite *cursor_sprite,
|
||||||
|
GList *gpus);
|
||||||
|
|
||||||
static MetaCursorNativeGpuState *
|
static MetaCursorNativeGpuState *
|
||||||
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
||||||
MetaGpuKms *gpu_kms);
|
MetaGpuKms *gpu_kms);
|
||||||
@ -152,7 +163,8 @@ static void
|
|||||||
meta_cursor_renderer_native_finalize (GObject *object)
|
meta_cursor_renderer_native_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
|
MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object);
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (renderer);
|
||||||
|
|
||||||
if (priv->animation_timeout_id)
|
if (priv->animation_timeout_id)
|
||||||
g_source_remove (priv->animation_timeout_id);
|
g_source_remove (priv->animation_timeout_id);
|
||||||
@ -203,7 +215,8 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
|||||||
MetaCrtc *crtc,
|
MetaCrtc *crtc,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||||
MetaGpuKms *gpu_kms;
|
MetaGpuKms *gpu_kms;
|
||||||
int kms_fd;
|
int kms_fd;
|
||||||
@ -291,9 +304,12 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
data->in_cursor_renderer_native;
|
data->in_cursor_renderer_native;
|
||||||
MetaCursorRendererNativePrivate *priv =
|
MetaCursorRendererNativePrivate *priv =
|
||||||
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
||||||
|
MetaCrtc *crtc;
|
||||||
|
MetaMonitorTransform transform;
|
||||||
ClutterRect scaled_crtc_rect;
|
ClutterRect scaled_crtc_rect;
|
||||||
float scale;
|
float scale;
|
||||||
int crtc_x, crtc_y;
|
int crtc_x, crtc_y;
|
||||||
|
int crtc_width, crtc_height;
|
||||||
|
|
||||||
if (meta_is_stage_views_scaled ())
|
if (meta_is_stage_views_scaled ())
|
||||||
scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
|
scale = meta_logical_monitor_get_scale (data->in_logical_monitor);
|
||||||
@ -305,17 +321,31 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
META_MONITOR_TRANSFORM_NORMAL,
|
META_MONITOR_TRANSFORM_NORMAL,
|
||||||
&crtc_x, &crtc_y);
|
&crtc_x, &crtc_y);
|
||||||
|
|
||||||
|
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
|
||||||
|
if (meta_monitor_transform_is_rotated (transform))
|
||||||
|
{
|
||||||
|
crtc_width = monitor_crtc_mode->crtc_mode->height;
|
||||||
|
crtc_height = monitor_crtc_mode->crtc_mode->width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
crtc_width = monitor_crtc_mode->crtc_mode->width;
|
||||||
|
crtc_height = monitor_crtc_mode->crtc_mode->height;
|
||||||
|
}
|
||||||
|
|
||||||
scaled_crtc_rect = (ClutterRect) {
|
scaled_crtc_rect = (ClutterRect) {
|
||||||
.origin = {
|
.origin = {
|
||||||
.x = crtc_x / scale,
|
.x = crtc_x / scale,
|
||||||
.y = crtc_y / scale
|
.y = crtc_y / scale
|
||||||
},
|
},
|
||||||
.size = {
|
.size = {
|
||||||
.width = monitor_crtc_mode->crtc_mode->width / scale,
|
.width = crtc_width / scale,
|
||||||
.height = monitor_crtc_mode->crtc_mode->height / scale
|
.height = crtc_height / scale
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
|
||||||
|
|
||||||
if (priv->has_hw_cursor &&
|
if (priv->has_hw_cursor &&
|
||||||
clutter_rect_intersection (&scaled_crtc_rect,
|
clutter_rect_intersection (&scaled_crtc_rect,
|
||||||
&data->in_local_cursor_rect,
|
&data->in_local_cursor_rect,
|
||||||
@ -326,7 +356,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
float crtc_cursor_x, crtc_cursor_y;
|
float crtc_cursor_x, crtc_cursor_y;
|
||||||
|
|
||||||
set_crtc_cursor (data->in_cursor_renderer_native,
|
set_crtc_cursor (data->in_cursor_renderer_native,
|
||||||
monitor_crtc_mode->output->crtc,
|
crtc,
|
||||||
data->in_cursor_sprite);
|
data->in_cursor_sprite);
|
||||||
|
|
||||||
gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
|
gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
|
||||||
@ -336,7 +366,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
|
crtc_cursor_y = (data->in_local_cursor_rect.origin.y -
|
||||||
scaled_crtc_rect.origin.y) * scale;
|
scaled_crtc_rect.origin.y) * scale;
|
||||||
drmModeMoveCursor (kms_fd,
|
drmModeMoveCursor (kms_fd,
|
||||||
monitor_crtc_mode->output->crtc->crtc_id,
|
crtc->crtc_id,
|
||||||
roundf (crtc_cursor_x),
|
roundf (crtc_cursor_x),
|
||||||
roundf (crtc_cursor_y));
|
roundf (crtc_cursor_y));
|
||||||
|
|
||||||
@ -344,8 +374,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
set_crtc_cursor (data->in_cursor_renderer_native,
|
set_crtc_cursor (data->in_cursor_renderer_native, crtc, NULL);
|
||||||
monitor_crtc_mode->output->crtc, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -355,7 +384,8 @@ static void
|
|||||||
update_hw_cursor (MetaCursorRendererNative *native,
|
update_hw_cursor (MetaCursorRendererNative *native,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
||||||
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
||||||
GList *logical_monitors;
|
GList *logical_monitors;
|
||||||
@ -548,18 +578,19 @@ can_draw_cursor_unscaled (MetaCursorRenderer *renderer,
|
|||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
should_have_hw_cursor (MetaCursorRenderer *renderer,
|
should_have_hw_cursor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite,
|
||||||
|
GList *gpus)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
|
||||||
GList *gpus;
|
|
||||||
GList *l;
|
GList *l;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
|
|
||||||
if (!cursor_sprite)
|
if (!cursor_sprite)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
|
if (meta_cursor_renderer_is_hw_cursors_inhibited (renderer,
|
||||||
|
cursor_sprite))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
for (l = gpus; l; l = l->next)
|
for (l = gpus; l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaGpuKms *gpu_kms = l->data;
|
MetaGpuKms *gpu_kms = l->data;
|
||||||
@ -593,7 +624,8 @@ should_have_hw_cursor (MetaCursorRenderer *renderer,
|
|||||||
static gboolean
|
static gboolean
|
||||||
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
|
meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native);
|
||||||
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
|
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
|
||||||
|
|
||||||
@ -605,10 +637,11 @@ meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native,
|
maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
gboolean cursor_change;
|
gboolean cursor_change;
|
||||||
guint delay;
|
guint delay;
|
||||||
|
|
||||||
@ -640,21 +673,78 @@ meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GList *
|
||||||
|
calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer,
|
||||||
|
MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
|
MetaMonitorManager *monitor_manager = priv->monitor_manager;
|
||||||
|
GList *gpus = NULL;
|
||||||
|
GList *logical_monitors;
|
||||||
|
GList *l;
|
||||||
|
ClutterRect cursor_rect;
|
||||||
|
|
||||||
|
cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
|
||||||
|
|
||||||
|
logical_monitors =
|
||||||
|
meta_monitor_manager_get_logical_monitors (monitor_manager);
|
||||||
|
for (l = logical_monitors; l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaLogicalMonitor *logical_monitor = l->data;
|
||||||
|
MetaRectangle logical_monitor_layout;
|
||||||
|
ClutterRect logical_monitor_rect;
|
||||||
|
GList *monitors, *l_mon;
|
||||||
|
|
||||||
|
logical_monitor_layout =
|
||||||
|
meta_logical_monitor_get_layout (logical_monitor);
|
||||||
|
logical_monitor_rect =
|
||||||
|
meta_rectangle_to_clutter_rect (&logical_monitor_layout);
|
||||||
|
|
||||||
|
if (!clutter_rect_intersection (&cursor_rect, &logical_monitor_rect,
|
||||||
|
NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
monitors = meta_logical_monitor_get_monitors (logical_monitor);
|
||||||
|
for (l_mon = monitors; l_mon; l_mon = l_mon->next)
|
||||||
|
{
|
||||||
|
MetaMonitor *monitor = l_mon->data;
|
||||||
|
MetaGpu *gpu;
|
||||||
|
|
||||||
|
gpu = meta_monitor_get_gpu (monitor);
|
||||||
|
if (!g_list_find (gpus, gpu))
|
||||||
|
gpus = g_list_prepend (gpus, gpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gpus;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite)
|
MetaCursorSprite *cursor_sprite)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
MetaCursorRendererNativePrivate *priv =
|
||||||
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
|
g_autoptr (GList) gpus = NULL;
|
||||||
|
|
||||||
if (cursor_sprite)
|
if (cursor_sprite)
|
||||||
|
{
|
||||||
meta_cursor_sprite_realize_texture (cursor_sprite);
|
meta_cursor_sprite_realize_texture (cursor_sprite);
|
||||||
|
gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite);
|
||||||
|
realize_cursor_sprite (renderer, cursor_sprite, gpus);
|
||||||
|
}
|
||||||
|
|
||||||
meta_cursor_renderer_native_trigger_frame (native, cursor_sprite);
|
maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite);
|
||||||
|
|
||||||
priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite);
|
priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus);
|
||||||
update_hw_cursor (native, cursor_sprite);
|
update_hw_cursor (native, cursor_sprite);
|
||||||
return priv->has_hw_cursor;
|
|
||||||
|
return (priv->has_hw_cursor ||
|
||||||
|
!cursor_sprite ||
|
||||||
|
!meta_cursor_sprite_get_cogl_texture (cursor_sprite));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -690,6 +780,24 @@ ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv,
|
|||||||
return cursor_gpu_state;
|
return cursor_gpu_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite);
|
||||||
|
GHashTableIter iter;
|
||||||
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, cursor_priv->gpu_states);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state))
|
||||||
|
{
|
||||||
|
guint pending_bo;
|
||||||
|
pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state);
|
||||||
|
g_clear_pointer (&cursor_gpu_state->bos[pending_bo],
|
||||||
|
(GDestroyNotify) gbm_bo_destroy);
|
||||||
|
cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
cursor_priv_free (MetaCursorNativePrivate *cursor_priv)
|
||||||
{
|
{
|
||||||
@ -722,6 +830,9 @@ ensure_cursor_priv (MetaCursorSprite *cursor_sprite)
|
|||||||
cursor_priv,
|
cursor_priv,
|
||||||
(GDestroyNotify) cursor_priv_free);
|
(GDestroyNotify) cursor_priv_free);
|
||||||
|
|
||||||
|
g_signal_connect (cursor_sprite, "texture-changed",
|
||||||
|
G_CALLBACK (on_cursor_sprite_texture_changed), NULL);
|
||||||
|
|
||||||
return cursor_priv;
|
return cursor_priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,57 +900,71 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite,
|
is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite,
|
||||||
MetaGpuKms *gpu_kms)
|
MetaGpuKms *gpu_kms)
|
||||||
{
|
{
|
||||||
MetaCursorNativePrivate *cursor_priv;
|
MetaCursorNativePrivate *cursor_priv;
|
||||||
MetaCursorNativeGpuState *cursor_gpu_state;
|
MetaCursorNativeGpuState *cursor_gpu_state;
|
||||||
guint pending_bo;
|
|
||||||
|
|
||||||
cursor_priv = get_cursor_priv (cursor_sprite);
|
cursor_priv = get_cursor_priv (cursor_sprite);
|
||||||
if (!cursor_priv)
|
if (!cursor_priv)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms);
|
||||||
if (!cursor_gpu_state)
|
if (!cursor_gpu_state)
|
||||||
return;
|
return FALSE;
|
||||||
|
|
||||||
pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state);
|
switch (cursor_gpu_state->pending_bo_state)
|
||||||
g_clear_pointer (&cursor_gpu_state->bos[pending_bo],
|
{
|
||||||
(GDestroyNotify) gbm_bo_destroy);
|
case META_CURSOR_GBM_BO_STATE_SET:
|
||||||
cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED;
|
case META_CURSOR_GBM_BO_STATE_NONE:
|
||||||
|
return TRUE;
|
||||||
|
case META_CURSOR_GBM_BO_STATE_INVALIDATED:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
#ifdef HAVE_WAYLAND
|
||||||
static void
|
static void
|
||||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaGpuKms *gpu_kms,
|
MetaGpuKms *gpu_kms,
|
||||||
MetaCursorSprite *cursor_sprite,
|
MetaCursorSpriteWayland *sprite_wayland)
|
||||||
struct wl_resource *buffer)
|
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
|
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland);
|
||||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||||
uint32_t gbm_format;
|
uint32_t gbm_format;
|
||||||
uint64_t cursor_width, cursor_height;
|
uint64_t cursor_width, cursor_height;
|
||||||
CoglTexture *texture;
|
CoglTexture *texture;
|
||||||
uint width, height;
|
uint width, height;
|
||||||
|
MetaWaylandBuffer *buffer;
|
||||||
|
struct wl_resource *buffer_resource;
|
||||||
|
struct wl_shm_buffer *shm_buffer;
|
||||||
|
|
||||||
cursor_renderer_gpu_data =
|
cursor_renderer_gpu_data =
|
||||||
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
||||||
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Destroy any previous pending cursor buffer; we'll always either fail (which
|
if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms))
|
||||||
* should unset, or succeed, which will set new buffer.
|
return;
|
||||||
*/
|
|
||||||
invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms);
|
|
||||||
|
|
||||||
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite);
|
||||||
width = cogl_texture_get_width (texture);
|
width = cogl_texture_get_width (texture);
|
||||||
height = cogl_texture_get_height (texture);
|
height = cogl_texture_get_height (texture);
|
||||||
|
|
||||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland);
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
buffer_resource = meta_wayland_buffer_get_resource (buffer);
|
||||||
|
if (!buffer_resource)
|
||||||
|
return;
|
||||||
|
|
||||||
|
shm_buffer = wl_shm_buffer_get (buffer_resource);
|
||||||
if (shm_buffer)
|
if (shm_buffer)
|
||||||
{
|
{
|
||||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||||
@ -913,47 +1038,27 @@ meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (MetaCursorRen
|
|||||||
set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo);
|
set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
|
||||||
MetaCursorSprite *cursor_sprite,
|
|
||||||
struct wl_resource *buffer)
|
|
||||||
{
|
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
|
||||||
MetaCursorRendererNativePrivate *priv =
|
|
||||||
meta_cursor_renderer_native_get_instance_private (native);
|
|
||||||
GList *gpus;
|
|
||||||
GList *l;
|
|
||||||
|
|
||||||
gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
|
|
||||||
for (l = gpus; l; l = l->next)
|
|
||||||
{
|
|
||||||
MetaGpuKms *gpu_kms = l->data;
|
|
||||||
|
|
||||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (
|
|
||||||
renderer,
|
|
||||||
gpu_kms,
|
|
||||||
cursor_sprite,
|
|
||||||
buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaGpuKms *gpu_kms,
|
MetaGpuKms *gpu_kms,
|
||||||
MetaCursorSprite *cursor_sprite,
|
MetaCursorSpriteXcursor *sprite_xcursor)
|
||||||
XcursorImage *xc_image)
|
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||||
|
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
|
||||||
|
XcursorImage *xc_image;
|
||||||
|
|
||||||
cursor_renderer_gpu_data =
|
cursor_renderer_gpu_data =
|
||||||
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms);
|
||||||
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms);
|
if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms))
|
||||||
|
return;
|
||||||
|
|
||||||
|
xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor);
|
||||||
|
|
||||||
load_cursor_sprite_gbm_buffer_for_gpu (native,
|
load_cursor_sprite_gbm_buffer_for_gpu (native,
|
||||||
gpu_kms,
|
gpu_kms,
|
||||||
@ -966,26 +1071,45 @@ meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (MetaCursorRende
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer,
|
||||||
MetaCursorSprite *cursor_sprite,
|
MetaGpuKms *gpu_kms,
|
||||||
XcursorImage *xc_image)
|
MetaCursorSprite *cursor_sprite)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
|
if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite))
|
||||||
|
{
|
||||||
|
MetaCursorSpriteWayland *sprite_wayland =
|
||||||
|
META_CURSOR_SPRITE_WAYLAND (cursor_sprite);
|
||||||
|
|
||||||
|
realize_cursor_sprite_from_wl_buffer_for_gpu (renderer,
|
||||||
|
gpu_kms,
|
||||||
|
sprite_wayland);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
|
||||||
|
{
|
||||||
|
MetaCursorSpriteXcursor *sprite_xcursor =
|
||||||
|
META_CURSOR_SPRITE_XCURSOR (cursor_sprite);
|
||||||
|
|
||||||
|
realize_cursor_sprite_from_xcursor_for_gpu (renderer,
|
||||||
|
gpu_kms,
|
||||||
|
sprite_xcursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
realize_cursor_sprite (MetaCursorRenderer *renderer,
|
||||||
|
MetaCursorSprite *cursor_sprite,
|
||||||
|
GList *gpus)
|
||||||
{
|
{
|
||||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
|
||||||
MetaCursorRendererNativePrivate *priv =
|
|
||||||
meta_cursor_renderer_native_get_instance_private (native);
|
|
||||||
GList *gpus;
|
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
gpus = meta_monitor_manager_get_gpus (priv->monitor_manager);
|
|
||||||
for (l = gpus; l; l = l->next)
|
for (l = gpus; l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaGpuKms *gpu_kms = l->data;
|
MetaGpuKms *gpu_kms = l->data;
|
||||||
|
|
||||||
meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (
|
realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite);
|
||||||
renderer,
|
|
||||||
gpu_kms,
|
|
||||||
cursor_sprite,
|
|
||||||
xc_image);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,12 +1121,6 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
|||||||
|
|
||||||
object_class->finalize = meta_cursor_renderer_native_finalize;
|
object_class->finalize = meta_cursor_renderer_native_finalize;
|
||||||
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
|
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
|
||||||
#ifdef HAVE_WAYLAND
|
|
||||||
renderer_class->realize_cursor_from_wl_buffer =
|
|
||||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
|
|
||||||
#endif
|
|
||||||
renderer_class->realize_cursor_from_xcursor =
|
|
||||||
meta_cursor_renderer_native_realize_cursor_from_xcursor;
|
|
||||||
|
|
||||||
quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
|
quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
|
||||||
quark_cursor_renderer_native_gpu_data =
|
quark_cursor_renderer_native_gpu_data =
|
||||||
@ -1017,14 +1135,13 @@ force_update_hw_cursor (MetaCursorRendererNative *native)
|
|||||||
meta_cursor_renderer_native_get_instance_private (native);
|
meta_cursor_renderer_native_get_instance_private (native);
|
||||||
|
|
||||||
priv->hw_state_invalidated = TRUE;
|
priv->hw_state_invalidated = TRUE;
|
||||||
update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer));
|
meta_cursor_renderer_force_update (renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_monitors_changed (MetaMonitorManager *monitors,
|
on_monitors_changed (MetaMonitorManager *monitors,
|
||||||
MetaCursorRendererNative *native)
|
MetaCursorRendererNative *native)
|
||||||
{
|
{
|
||||||
/* Our tracking is all messed up, so force an update. */
|
|
||||||
force_update_hw_cursor (native);
|
force_update_hw_cursor (native);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1096,9 +1213,3 @@ static void
|
|||||||
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
meta_cursor_renderer_native_init (MetaCursorRendererNative *native)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
|
||||||
{
|
|
||||||
force_update_hw_cursor (native);
|
|
||||||
}
|
|
||||||
|
@ -32,8 +32,6 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native,
|
|||||||
META, CURSOR_RENDERER_NATIVE,
|
META, CURSOR_RENDERER_NATIVE,
|
||||||
MetaCursorRenderer)
|
MetaCursorRenderer)
|
||||||
|
|
||||||
void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer);
|
|
||||||
|
|
||||||
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend);
|
MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend);
|
||||||
|
|
||||||
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
#endif /* META_CURSOR_RENDERER_NATIVE_H */
|
||||||
|
@ -47,6 +47,12 @@ typedef struct _MetaKmsSource
|
|||||||
MetaGpuKms *gpu_kms;
|
MetaGpuKms *gpu_kms;
|
||||||
} MetaKmsSource;
|
} MetaKmsSource;
|
||||||
|
|
||||||
|
typedef struct _MetaGpuKmsFlipClosureContainer
|
||||||
|
{
|
||||||
|
GClosure *flip_closure;
|
||||||
|
MetaGpuKms *gpu_kms;
|
||||||
|
} MetaGpuKmsFlipClosureContainer;
|
||||||
|
|
||||||
struct _MetaGpuKms
|
struct _MetaGpuKms
|
||||||
{
|
{
|
||||||
MetaGpu parent;
|
MetaGpu parent;
|
||||||
@ -62,8 +68,11 @@ struct _MetaGpuKms
|
|||||||
int max_buffer_height;
|
int max_buffer_height;
|
||||||
|
|
||||||
gboolean page_flips_not_supported;
|
gboolean page_flips_not_supported;
|
||||||
|
|
||||||
|
gboolean resources_init_failed_before;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
G_DEFINE_QUARK (MetaGpuKmsError, meta_gpu_kms_error)
|
||||||
G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
|
G_DEFINE_TYPE (MetaGpuKms, meta_gpu_kms, META_TYPE_GPU)
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -104,8 +113,10 @@ get_crtc_drm_connectors (MetaGpu *gpu,
|
|||||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaOutput *output = l->data;
|
MetaOutput *output = l->data;
|
||||||
|
MetaCrtc *assigned_crtc;
|
||||||
|
|
||||||
if (output->crtc == crtc)
|
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
if (assigned_crtc == crtc)
|
||||||
g_array_append_val (connectors_array, output->winsys_id);
|
g_array_append_val (connectors_array, output->winsys_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +151,10 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
|
|||||||
connectors, n_connectors,
|
connectors, n_connectors,
|
||||||
mode) != 0)
|
mode) != 0)
|
||||||
{
|
{
|
||||||
|
if (mode)
|
||||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||||
|
else
|
||||||
|
g_warning ("Failed to disable CRTC");
|
||||||
g_free (connectors);
|
g_free (connectors);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@ -185,8 +199,10 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
|||||||
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
|
||||||
{
|
{
|
||||||
MetaOutput *output = l->data;
|
MetaOutput *output = l->data;
|
||||||
|
MetaCrtc *assigned_crtc;
|
||||||
|
|
||||||
if (output->crtc == crtc)
|
assigned_crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
if (assigned_crtc == crtc)
|
||||||
{
|
{
|
||||||
connected_crtc_found = TRUE;
|
connected_crtc_found = TRUE;
|
||||||
break;
|
break;
|
||||||
@ -199,11 +215,26 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _GpuClosureContainer
|
MetaGpuKmsFlipClosureContainer *
|
||||||
|
meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
||||||
|
GClosure *flip_closure)
|
||||||
{
|
{
|
||||||
GClosure *flip_closure;
|
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||||
MetaGpuKms *gpu_kms;
|
|
||||||
} GpuClosureContainer;
|
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
|
||||||
|
*closure_container = (MetaGpuKmsFlipClosureContainer) {
|
||||||
|
.flip_closure = flip_closure,
|
||||||
|
.gpu_kms = gpu_kms
|
||||||
|
};
|
||||||
|
|
||||||
|
return closure_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container)
|
||||||
|
{
|
||||||
|
g_free (closure_container);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||||
@ -229,14 +260,11 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
|||||||
|
|
||||||
if (!gpu_kms->page_flips_not_supported)
|
if (!gpu_kms->page_flips_not_supported)
|
||||||
{
|
{
|
||||||
GpuClosureContainer *closure_container;
|
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||||
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||||
|
|
||||||
closure_container = g_new0 (GpuClosureContainer, 1);
|
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
|
||||||
*closure_container = (GpuClosureContainer) {
|
flip_closure);
|
||||||
.flip_closure = flip_closure,
|
|
||||||
.gpu_kms = gpu_kms
|
|
||||||
};
|
|
||||||
|
|
||||||
ret = drmModePageFlip (kms_fd,
|
ret = drmModePageFlip (kms_fd,
|
||||||
crtc->crtc_id,
|
crtc->crtc_id,
|
||||||
@ -245,7 +273,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
|||||||
closure_container);
|
closure_container);
|
||||||
if (ret != 0 && ret != -EACCES)
|
if (ret != 0 && ret != -EACCES)
|
||||||
{
|
{
|
||||||
g_free (closure_container);
|
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||||
g_warning ("Failed to flip: %s", strerror (-ret));
|
g_warning ("Failed to flip: %s", strerror (-ret));
|
||||||
gpu_kms->page_flips_not_supported = TRUE;
|
gpu_kms->page_flips_not_supported = TRUE;
|
||||||
}
|
}
|
||||||
@ -276,12 +304,12 @@ page_flip_handler (int fd,
|
|||||||
unsigned int usec,
|
unsigned int usec,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
{
|
{
|
||||||
GpuClosureContainer *closure_container = user_data;
|
MetaGpuKmsFlipClosureContainer *closure_container = user_data;
|
||||||
GClosure *flip_closure = closure_container->flip_closure;
|
GClosure *flip_closure = closure_container->flip_closure;
|
||||||
MetaGpuKms *gpu_kms = closure_container->gpu_kms;
|
MetaGpuKms *gpu_kms = closure_container->gpu_kms;
|
||||||
|
|
||||||
invoke_flip_closure (flip_closure, gpu_kms);
|
invoke_flip_closure (flip_closure, gpu_kms);
|
||||||
g_free (closure_container);
|
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -701,20 +729,34 @@ init_outputs (MetaGpuKms *gpu_kms,
|
|||||||
setup_output_clones (gpu);
|
setup_output_clones (gpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
meta_kms_resources_init (MetaKmsResources *resources,
|
meta_kms_resources_init (MetaKmsResources *resources,
|
||||||
int fd)
|
int fd,
|
||||||
|
GError **error)
|
||||||
|
|
||||||
{
|
{
|
||||||
drmModeRes *drm_resources;
|
drmModeRes *drm_resources;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
drm_resources = drmModeGetResources (fd);
|
drm_resources = drmModeGetResources (fd);
|
||||||
|
|
||||||
|
if (!drm_resources)
|
||||||
|
{
|
||||||
|
g_set_error (error,
|
||||||
|
G_IO_ERROR,
|
||||||
|
G_IO_ERROR_FAILED,
|
||||||
|
"Calling drmModeGetResources() failed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
resources->resources = drm_resources;
|
resources->resources = drm_resources;
|
||||||
|
|
||||||
resources->n_encoders = (unsigned int) drm_resources->count_encoders;
|
resources->n_encoders = (unsigned int) drm_resources->count_encoders;
|
||||||
resources->encoders = g_new (drmModeEncoder *, resources->n_encoders);
|
resources->encoders = g_new (drmModeEncoder *, resources->n_encoders);
|
||||||
for (i = 0; i < resources->n_encoders; i++)
|
for (i = 0; i < resources->n_encoders; i++)
|
||||||
resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]);
|
resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -726,7 +768,7 @@ meta_kms_resources_release (MetaKmsResources *resources)
|
|||||||
drmModeFreeEncoder (resources->encoders[i]);
|
drmModeFreeEncoder (resources->encoders[i]);
|
||||||
g_free (resources->encoders);
|
g_free (resources->encoders);
|
||||||
|
|
||||||
drmModeFreeResources (resources->resources);
|
g_clear_pointer (&resources->resources, drmModeFreeResources);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -737,8 +779,18 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
|
|||||||
MetaMonitorManager *monitor_manager =
|
MetaMonitorManager *monitor_manager =
|
||||||
meta_gpu_get_monitor_manager (gpu);
|
meta_gpu_get_monitor_manager (gpu);
|
||||||
MetaKmsResources resources;
|
MetaKmsResources resources;
|
||||||
|
g_autoptr (GError) local_error = NULL;
|
||||||
|
|
||||||
meta_kms_resources_init (&resources, gpu_kms->fd);
|
if (!meta_kms_resources_init (&resources, gpu_kms->fd, &local_error))
|
||||||
|
{
|
||||||
|
if (!gpu_kms->resources_init_failed_before)
|
||||||
|
{
|
||||||
|
g_warning ("meta_kms_resources_init failed: %s, assuming we have no outputs",
|
||||||
|
local_error->message);
|
||||||
|
gpu_kms->resources_init_failed_before = TRUE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
gpu_kms->max_buffer_width = resources.resources->max_width;
|
gpu_kms->max_buffer_width = resources.resources->max_width;
|
||||||
gpu_kms->max_buffer_height = resources.resources->max_height;
|
gpu_kms->max_buffer_height = resources.resources->max_height;
|
||||||
@ -751,6 +803,8 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
|
|||||||
are freed by the platform-independent layer. */
|
are freed by the platform-independent layer. */
|
||||||
free_resources (gpu_kms);
|
free_resources (gpu_kms);
|
||||||
|
|
||||||
|
g_assert (resources.resources->count_connectors > 0);
|
||||||
|
|
||||||
init_connectors (gpu_kms, resources.resources);
|
init_connectors (gpu_kms, resources.resources);
|
||||||
init_modes (gpu_kms, resources.resources);
|
init_modes (gpu_kms, resources.resources);
|
||||||
init_crtcs (gpu_kms, &resources);
|
init_crtcs (gpu_kms, &resources);
|
||||||
@ -761,6 +815,12 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms)
|
||||||
|
{
|
||||||
|
return gpu_kms->n_connectors > 0;
|
||||||
|
}
|
||||||
|
|
||||||
MetaGpuKms *
|
MetaGpuKms *
|
||||||
meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
||||||
const char *kms_file_path,
|
const char *kms_file_path,
|
||||||
@ -774,11 +834,46 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
|||||||
GSource *source;
|
GSource *source;
|
||||||
MetaKmsSource *kms_source;
|
MetaKmsSource *kms_source;
|
||||||
MetaGpuKms *gpu_kms;
|
MetaGpuKms *gpu_kms;
|
||||||
|
drmModeRes *drm_resources;
|
||||||
|
guint n_connectors;
|
||||||
int kms_fd;
|
int kms_fd;
|
||||||
|
|
||||||
kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error);
|
kms_fd = meta_launcher_open_restricted (launcher, kms_file_path, error);
|
||||||
if (kms_fd == -1)
|
if (kms_fd == -1)
|
||||||
return FALSE;
|
return NULL;
|
||||||
|
|
||||||
|
/* Some GPUs might have no connectors, for example dedicated GPUs on PRIME (hybrid) laptops.
|
||||||
|
* These GPUs cannot render anything on separate screens, and they are aggressively switched
|
||||||
|
* off by the kernel.
|
||||||
|
*
|
||||||
|
* If we add these PRIME GPUs to the GPU list anyway, Mutter keeps awakening the secondary GPU,
|
||||||
|
* and doing this causes a considerable stuttering. These GPUs are usually put to sleep again
|
||||||
|
* after ~2s without a workload.
|
||||||
|
*
|
||||||
|
* For now, to avoid this situation, only create the MetaGpuKms when the GPU has any connectors.
|
||||||
|
*/
|
||||||
|
drm_resources = drmModeGetResources (kms_fd);
|
||||||
|
|
||||||
|
if (!drm_resources)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No resources");
|
||||||
|
meta_launcher_close_restricted (launcher, kms_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
n_connectors = drm_resources->count_connectors;
|
||||||
|
|
||||||
|
drmModeFreeResources (drm_resources);
|
||||||
|
|
||||||
|
if (n_connectors == 0)
|
||||||
|
{
|
||||||
|
g_set_error (error,
|
||||||
|
META_GPU_KMS_ERROR,
|
||||||
|
META_GPU_KMS_ERROR_NO_CONNECTORS,
|
||||||
|
"No connectors available in this GPU. This is probably a dedicated GPU in a hybrid setup.");
|
||||||
|
meta_launcher_close_restricted (launcher, kms_fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
gpu_kms = g_object_new (META_TYPE_GPU_KMS,
|
gpu_kms = g_object_new (META_TYPE_GPU_KMS,
|
||||||
"monitor-manager", monitor_manager_kms,
|
"monitor-manager", monitor_manager_kms,
|
||||||
@ -789,6 +884,8 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
|||||||
|
|
||||||
drmSetClientCap (gpu_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
drmSetClientCap (gpu_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||||
|
|
||||||
|
meta_gpu_kms_read_current (META_GPU (gpu_kms), NULL);
|
||||||
|
|
||||||
source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource));
|
source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource));
|
||||||
kms_source = (MetaKmsSource *) source;
|
kms_source = (MetaKmsSource *) source;
|
||||||
kms_source->fd_tag = g_source_add_unix_fd (source,
|
kms_source->fd_tag = g_source_add_unix_fd (source,
|
||||||
|
@ -29,9 +29,19 @@
|
|||||||
#include "backends/meta-gpu.h"
|
#include "backends/meta-gpu.h"
|
||||||
#include "backends/native/meta-monitor-manager-kms.h"
|
#include "backends/native/meta-monitor-manager-kms.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
META_GPU_KMS_ERROR_NO_CONNECTORS,
|
||||||
|
} MetaGpuKmsError;
|
||||||
|
|
||||||
|
#define META_GPU_KMS_ERROR (meta_gpu_kms_error_quark ())
|
||||||
|
GQuark meta_gpu_kms_error_quark (void);
|
||||||
|
|
||||||
#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ())
|
#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ())
|
||||||
G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)
|
G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)
|
||||||
|
|
||||||
|
typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer;
|
||||||
|
|
||||||
typedef struct _MetaKmsResources
|
typedef struct _MetaKmsResources
|
||||||
{
|
{
|
||||||
drmModeRes *resources;
|
drmModeRes *resources;
|
||||||
@ -51,6 +61,8 @@ gboolean meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
|
|||||||
int y,
|
int y,
|
||||||
uint32_t fb_id);
|
uint32_t fb_id);
|
||||||
|
|
||||||
|
gboolean meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms);
|
||||||
|
|
||||||
gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
||||||
MetaCrtc *crtc);
|
MetaCrtc *crtc);
|
||||||
|
|
||||||
@ -84,4 +96,9 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
|
|||||||
|
|
||||||
float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
|
float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
|
||||||
|
|
||||||
|
MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
||||||
|
GClosure *flip_closure);
|
||||||
|
|
||||||
|
void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
|
||||||
|
|
||||||
#endif /* META_GPU_KMS_H */
|
#endif /* META_GPU_KMS_H */
|
||||||
|
@ -1,200 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include "meta-idle-monitor-native.h"
|
|
||||||
#include "meta-idle-monitor-private.h"
|
|
||||||
|
|
||||||
#include <meta/util.h>
|
|
||||||
#include "display-private.h"
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorNative
|
|
||||||
{
|
|
||||||
MetaIdleMonitor parent;
|
|
||||||
|
|
||||||
guint64 last_event_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _MetaIdleMonitorNativeClass
|
|
||||||
{
|
|
||||||
MetaIdleMonitorClass parent_class;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
MetaIdleMonitorWatch base;
|
|
||||||
|
|
||||||
GSource *timeout_source;
|
|
||||||
} MetaIdleMonitorWatchNative;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaIdleMonitorNative, meta_idle_monitor_native, META_TYPE_IDLE_MONITOR)
|
|
||||||
|
|
||||||
static gint64
|
|
||||||
meta_idle_monitor_native_get_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
|
|
||||||
return (g_get_monotonic_time () - monitor_native->last_event_time) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint32
|
|
||||||
get_next_watch_serial (void)
|
|
||||||
{
|
|
||||||
static guint32 serial = 0;
|
|
||||||
g_atomic_int_inc (&serial);
|
|
||||||
return serial;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
native_dispatch_timeout (GSource *source,
|
|
||||||
GSourceFunc callback,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native = user_data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
|
|
||||||
_meta_idle_monitor_watch_fire (watch);
|
|
||||||
g_source_set_ready_time (watch_native->timeout_source, -1);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSourceFuncs native_source_funcs = {
|
|
||||||
NULL, /* prepare */
|
|
||||||
NULL, /* check */
|
|
||||||
native_dispatch_timeout,
|
|
||||||
NULL, /* finalize */
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_watch (gpointer data)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native = data;
|
|
||||||
MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
MetaIdleMonitor *monitor = watch->monitor;
|
|
||||||
|
|
||||||
g_object_ref (monitor);
|
|
||||||
|
|
||||||
if (watch->idle_source_id)
|
|
||||||
{
|
|
||||||
g_source_remove (watch->idle_source_id);
|
|
||||||
watch->idle_source_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (watch->notify != NULL)
|
|
||||||
watch->notify (watch->user_data);
|
|
||||||
|
|
||||||
if (watch_native->timeout_source != NULL)
|
|
||||||
g_source_destroy (watch_native->timeout_source);
|
|
||||||
|
|
||||||
g_object_unref (monitor);
|
|
||||||
g_slice_free (MetaIdleMonitorWatchNative, watch_native);
|
|
||||||
}
|
|
||||||
|
|
||||||
static MetaIdleMonitorWatch *
|
|
||||||
meta_idle_monitor_native_make_watch (MetaIdleMonitor *monitor,
|
|
||||||
guint64 timeout_msec,
|
|
||||||
MetaIdleMonitorWatchFunc callback,
|
|
||||||
gpointer user_data,
|
|
||||||
GDestroyNotify notify)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorWatchNative *watch_native;
|
|
||||||
MetaIdleMonitorWatch *watch;
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
|
|
||||||
watch_native = g_slice_new0 (MetaIdleMonitorWatchNative);
|
|
||||||
watch = (MetaIdleMonitorWatch *) watch_native;
|
|
||||||
|
|
||||||
watch->monitor = monitor;
|
|
||||||
watch->id = get_next_watch_serial ();
|
|
||||||
watch->callback = callback;
|
|
||||||
watch->user_data = user_data;
|
|
||||||
watch->notify = notify;
|
|
||||||
watch->timeout_msec = timeout_msec;
|
|
||||||
|
|
||||||
if (timeout_msec != 0)
|
|
||||||
{
|
|
||||||
GSource *source = g_source_new (&native_source_funcs, sizeof (GSource));
|
|
||||||
|
|
||||||
g_source_set_callback (source, NULL, watch, NULL);
|
|
||||||
g_source_set_ready_time (source, monitor_native->last_event_time + timeout_msec * 1000);
|
|
||||||
g_source_attach (source, NULL);
|
|
||||||
g_source_unref (source);
|
|
||||||
|
|
||||||
watch_native->timeout_source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
return watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_native_class_init (MetaIdleMonitorNativeClass *klass)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorClass *idle_monitor_class = META_IDLE_MONITOR_CLASS (klass);
|
|
||||||
|
|
||||||
idle_monitor_class->get_idletime = meta_idle_monitor_native_get_idletime;
|
|
||||||
idle_monitor_class->make_watch = meta_idle_monitor_native_make_watch;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_idle_monitor_native_init (MetaIdleMonitorNative *monitor_native)
|
|
||||||
{
|
|
||||||
MetaIdleMonitor *monitor = META_IDLE_MONITOR (monitor_native);
|
|
||||||
|
|
||||||
monitor->watches = g_hash_table_new_full (NULL, NULL, NULL, free_watch);
|
|
||||||
monitor_native->last_event_time = g_get_monotonic_time ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor)
|
|
||||||
{
|
|
||||||
MetaIdleMonitorNative *monitor_native = META_IDLE_MONITOR_NATIVE (monitor);
|
|
||||||
GList *node, *watch_ids;
|
|
||||||
|
|
||||||
monitor_native->last_event_time = g_get_monotonic_time ();
|
|
||||||
|
|
||||||
watch_ids = g_hash_table_get_keys (monitor->watches);
|
|
||||||
|
|
||||||
for (node = watch_ids; node != NULL; node = node->next)
|
|
||||||
{
|
|
||||||
guint watch_id = GPOINTER_TO_UINT (node->data);
|
|
||||||
MetaIdleMonitorWatchNative *watch;
|
|
||||||
|
|
||||||
watch = g_hash_table_lookup (monitor->watches, GUINT_TO_POINTER (watch_id));
|
|
||||||
if (!watch)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (watch->base.timeout_msec == 0)
|
|
||||||
{
|
|
||||||
_meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_source_set_ready_time (watch->timeout_source,
|
|
||||||
monitor_native->last_event_time +
|
|
||||||
watch->base.timeout_msec * 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_list_free (watch_ids);
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright 2013 Red Hat, Inc.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
|
|
||||||
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef META_IDLE_MONITOR_NATIVE_H
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_H
|
|
||||||
|
|
||||||
#include <glib-object.h>
|
|
||||||
#include <meta/meta-idle-monitor.h>
|
|
||||||
|
|
||||||
#define META_TYPE_IDLE_MONITOR_NATIVE (meta_idle_monitor_native_get_type ())
|
|
||||||
#define META_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNative))
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
|
|
||||||
#define META_IS_IDLE_MONITOR_NATIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_IDLE_MONITOR_NATIVE))
|
|
||||||
#define META_IS_IDLE_MONITOR_NATIVE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_IDLE_MONITOR_NATIVE))
|
|
||||||
#define META_IDLE_MONITOR_NATIVE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_IDLE_MONITOR_NATIVE, MetaIdleMonitorNativeClass))
|
|
||||||
|
|
||||||
typedef struct _MetaIdleMonitorNative MetaIdleMonitorNative;
|
|
||||||
typedef struct _MetaIdleMonitorNativeClass MetaIdleMonitorNativeClass;
|
|
||||||
|
|
||||||
GType meta_idle_monitor_native_get_type (void);
|
|
||||||
|
|
||||||
void meta_idle_monitor_native_reset_idletime (MetaIdleMonitor *monitor);
|
|
||||||
|
|
||||||
#endif /* META_IDLE_MONITOR_NATIVE_H */
|
|
@ -44,7 +44,6 @@
|
|||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
#include "backends/native/meta-backend-native.h"
|
#include "backends/native/meta-backend-native.h"
|
||||||
#include "meta-cursor-renderer-native.h"
|
#include "meta-cursor-renderer-native.h"
|
||||||
#include "meta-idle-monitor-native.h"
|
|
||||||
#include "meta-renderer-native.h"
|
#include "meta-renderer-native.h"
|
||||||
|
|
||||||
struct _MetaLauncher
|
struct _MetaLauncher
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "meta-crtc-kms.h"
|
#include "meta-crtc-kms.h"
|
||||||
#include "meta-gpu-kms.h"
|
#include "meta-gpu-kms.h"
|
||||||
#include "meta-output-kms.h"
|
#include "meta-output-kms.h"
|
||||||
|
#include "wayland/meta-wayland-outputs.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -188,7 +189,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|||||||
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
|
||||||
|
|
||||||
output->is_dirty = TRUE;
|
output->is_dirty = TRUE;
|
||||||
output->crtc = crtc;
|
meta_output_assign_crtc (output, crtc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,7 +250,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
output->crtc = NULL;
|
meta_output_unassign_crtc (output);
|
||||||
output->is_primary = FALSE;
|
output->is_primary = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,9 +416,15 @@ void
|
|||||||
meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
|
meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms)
|
||||||
{
|
{
|
||||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
|
CoglContext *cogl_context =
|
||||||
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
|
||||||
meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
|
meta_monitor_manager_kms_connect_uevent_handler (manager_kms);
|
||||||
handle_hotplug_event (manager);
|
handle_hotplug_event (manager);
|
||||||
|
|
||||||
|
if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES))
|
||||||
|
meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ());
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -642,10 +649,12 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
|
|||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable);
|
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable);
|
||||||
|
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||||
const char *subsystems[2] = { "drm", NULL };
|
const char *subsystems[2] = { "drm", NULL };
|
||||||
GList *gpu_paths;
|
GList *gpu_paths;
|
||||||
g_autofree char *primary_gpu_path = NULL;
|
g_autofree char *primary_gpu_path = NULL;
|
||||||
GList *l;
|
GList *l;
|
||||||
|
gboolean can_have_outputs;
|
||||||
|
|
||||||
manager_kms->udev = g_udev_client_new (subsystems);
|
manager_kms->udev = g_udev_client_new (subsystems);
|
||||||
|
|
||||||
@ -674,16 +683,19 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
|
|||||||
gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_SECONDARY, primary_gpu_path);
|
gpu_paths = get_gpu_paths (manager_kms, GPU_TYPE_SECONDARY, primary_gpu_path);
|
||||||
for (l = gpu_paths; l; l = l->next)
|
for (l = gpu_paths; l; l = l->next)
|
||||||
{
|
{
|
||||||
GError *secondary_error = NULL;
|
g_autoptr (GError) secondary_error = NULL;
|
||||||
char *gpu_path = l->data;
|
char *gpu_path = l->data;
|
||||||
MetaGpuKms *gpu_kms;
|
MetaGpuKms *gpu_kms;
|
||||||
|
|
||||||
gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error);
|
gpu_kms = meta_gpu_kms_new (manager_kms, gpu_path, &secondary_error);
|
||||||
if (!gpu_kms)
|
if (!gpu_kms)
|
||||||
{
|
{
|
||||||
g_warning ("Failed to open secondary gpu '%s': %s",
|
if (g_error_matches (secondary_error, META_GPU_KMS_ERROR, META_GPU_KMS_ERROR_NO_CONNECTORS))
|
||||||
gpu_path, secondary_error->message);
|
g_message ("Ignoring GPU %s due to the lack of connectors", gpu_path);
|
||||||
g_error_free (secondary_error);
|
else
|
||||||
|
g_warning ("Failed to open secondary gpu '%s': %s", gpu_path, secondary_error->message);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
|
meta_monitor_manager_add_gpu (META_MONITOR_MANAGER (manager_kms),
|
||||||
@ -691,6 +703,24 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
|
|||||||
}
|
}
|
||||||
g_list_free_full (gpu_paths, g_free);
|
g_list_free_full (gpu_paths, g_free);
|
||||||
|
|
||||||
|
can_have_outputs = FALSE;
|
||||||
|
for (l = meta_monitor_manager_get_gpus (manager); l; l = l->next)
|
||||||
|
{
|
||||||
|
MetaGpuKms *gpu_kms = l->data;
|
||||||
|
|
||||||
|
if (meta_gpu_kms_can_have_outputs (gpu_kms))
|
||||||
|
{
|
||||||
|
can_have_outputs = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!can_have_outputs)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
"No GPUs with outputs found");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,11 +64,13 @@ typedef struct _MetaOutputKms
|
|||||||
void
|
void
|
||||||
meta_output_kms_set_underscan (MetaOutput *output)
|
meta_output_kms_set_underscan (MetaOutput *output)
|
||||||
{
|
{
|
||||||
if (!output->crtc)
|
MetaCrtc *crtc;
|
||||||
|
|
||||||
|
crtc = meta_output_get_assigned_crtc (output);
|
||||||
|
if (!crtc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
meta_crtc_kms_set_underscan (output->crtc,
|
meta_crtc_kms_set_underscan (crtc, output->is_underscanning);
|
||||||
output->is_underscanning);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -600,14 +602,14 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
|
|||||||
|
|
||||||
if (crtc->crtc_id == output_kms->current_encoder->crtc_id)
|
if (crtc->crtc_id == output_kms->current_encoder->crtc_id)
|
||||||
{
|
{
|
||||||
output->crtc = crtc;
|
meta_output_assign_crtc (output, crtc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output->crtc = NULL;
|
meta_output_unassign_crtc (output);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_output)
|
if (old_output)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user