Compare commits
135 Commits
citadel
...
gnome-3-34
Author | SHA1 | Date | |
---|---|---|---|
|
a416bed34c | ||
|
80c0a470e7 | ||
|
8802f7f0d8 | ||
|
8b3f1117be | ||
|
48ffbb5824 | ||
|
129d134704 | ||
|
4078ba1828 | ||
|
fd8ccbac82 | ||
|
93417d0ceb | ||
|
3bafd23424 | ||
|
e328fcc379 | ||
|
e845bbd579 | ||
|
025730349d | ||
|
f6d0af0c93 | ||
|
8acff5309d | ||
|
0ab8b17433 | ||
|
50f383d2e9 | ||
|
7fbba4ad14 | ||
|
eb6189d6b6 | ||
|
668d13ffb5 | ||
|
02947e7872 | ||
|
ebfe5e44c2 | ||
|
8f64b3dcad | ||
|
8de5b95123 | ||
|
cedab9442f | ||
|
7cc5ed96fc | ||
|
bb831f04c5 | ||
|
c92267feb2 | ||
|
8240aba80f | ||
|
5f34a0f245 | ||
|
83eeb3dbd2 | ||
|
c25011ffba | ||
|
abd67819fe | ||
|
6f3b7b733a | ||
|
e2c61f2739 | ||
|
1a3dfd8110 | ||
|
aeb781acd6 | ||
|
092591b872 | ||
|
57992f37cc | ||
|
7655a63af6 | ||
|
a5b5e95ad9 | ||
|
11da42b2f8 | ||
|
2709a4ffb1 | ||
|
c65db40178 | ||
|
011ff15603 | ||
|
c3d2f3f399 | ||
|
053bb5901a | ||
|
0bce4323c7 | ||
|
b2bc345463 | ||
|
2235629d25 | ||
|
59da900a45 | ||
|
0e0dae2774 | ||
|
4959ae8bc4 | ||
|
aea5541ffa | ||
|
47fe7ac25b | ||
|
d35d7fb618 | ||
|
666bd25005 | ||
|
208fd1b083 | ||
|
12152c7edb | ||
|
de7782221a | ||
|
651d2a57f8 | ||
|
e18aa564b0 | ||
|
4cc5b85c5d | ||
|
ca5ed7369d | ||
|
5ae317e004 | ||
|
21dca32934 | ||
|
41c6e1375b | ||
|
d38c30c128 | ||
|
59e9b073a5 | ||
|
6b6e724425 | ||
|
156dd576f4 | ||
|
4d0a331cfe | ||
|
01d93f2819 | ||
|
be777dbd79 | ||
|
a9a0110818 | ||
|
fd7d0fb339 | ||
|
1671692590 | ||
|
06fc756f0f | ||
|
81b7196ad9 | ||
|
e91b12fdf9 | ||
|
f52c0a3bf7 | ||
|
78a45e1813 | ||
|
4947e8ae5b | ||
|
5724310899 | ||
|
9772f084bf | ||
|
8b087cfe56 | ||
|
c05328f76a | ||
|
868a617907 | ||
|
6f02d2ead0 | ||
|
fc77efbcd7 | ||
|
c0e76186da | ||
|
1b75d78c72 | ||
|
cbbffd1db7 | ||
|
06202c342b | ||
|
9c372388da | ||
|
7e741fe2d2 | ||
|
edb618b2a4 | ||
|
e2d6b33b61 | ||
|
eac37b17b0 | ||
|
d78585d68a | ||
|
c462544f78 | ||
|
eb78b7d0d1 | ||
|
cc00e55513 | ||
|
a14e7b441c | ||
|
403d8fcc66 | ||
|
7e5366f233 | ||
|
cf78598974 | ||
|
7c1f3498fe | ||
|
598be2b1d8 | ||
|
a8776a9634 | ||
|
4b238c10f4 | ||
|
6fa860481c | ||
|
4ba3c4537e | ||
|
1f56514e40 | ||
|
5e1bbb770e | ||
|
3df4348f23 | ||
|
9ed33dc72e | ||
|
8cb0646b62 | ||
|
c9a05d4581 | ||
|
98a1630fa2 | ||
|
4c48c859ea | ||
|
d7bdaeeb82 | ||
|
3564b0df4a | ||
|
34b5a07d58 | ||
|
a112d7a10e | ||
|
51f7e8c4dd | ||
|
f4574ea36f | ||
|
2301cde8f7 | ||
|
ef2f5f07f0 | ||
|
85f5db7e73 | ||
|
c0037305eb | ||
|
ff885fea31 | ||
|
bf17e04010 | ||
|
a22731e2b2 | ||
|
b6ed7d6781 |
@ -1,6 +1,5 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
mutter_branch=$(git describe --contains --all HEAD)
|
||||
gnome_shell_target=
|
||||
|
||||
git clone https://gitlab.gnome.org/GNOME/gnome-shell.git
|
||||
@ -26,8 +25,7 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
|
||||
fi
|
||||
|
||||
if [ -z "$gnome_shell_target" ]; then
|
||||
gnome_shell_target=$(git branch -r -l origin/$mutter_branch)
|
||||
gnome_shell_target=${gnome_shell_target:-$(git branch -r -l ${mutter_branch#remotes/})}
|
||||
gnome_shell_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
|
||||
gnome_shell_target=${gnome_shell_target:-origin/master}
|
||||
echo Using $gnome_shell_target instead
|
||||
fi
|
||||
|
87
NEWS
87
NEWS
@ -1,3 +1,90 @@
|
||||
3.34.6
|
||||
======
|
||||
* Fix various clipboard issues [Carlos; !1198, !1203, !1204, !1186, !1206]
|
||||
* Fix locate-pointer feature interfering with keybindings [Carlos; !1014]
|
||||
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
|
||||
* Preserve keyboard state on VT switch [Olivier; !1185]
|
||||
* Fixed crashes [Florian; #1083]
|
||||
* Plugged memory leaks [Sebastian; !1001]
|
||||
* Misc. bug fixes and cleanups [Pekka, Laurent; !1209, #1074]
|
||||
|
||||
Contributors:
|
||||
Laurent Bigonville, Olivier Fourdan, Carlos Garnacho, Sebastian Keller,
|
||||
Florian Müllner, Pekka Paalanen
|
||||
|
||||
3.34.5
|
||||
======
|
||||
* Fix visibility of initially hidden windows [Jonas; !1066]
|
||||
* Fix hardware cursor on GPU hotplug [Pekka; !1097]
|
||||
* Fix pasting images from wayland [Robert, Carlos; !1141, #1065]
|
||||
* Fixed crashes [Florian, Olivier, Jonas; #1029, !1073, !1121, !1120]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Carlos Garnacho, Robert Mader, Florian Müllner,
|
||||
Pekka Paalanen, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Yi-Jyun Pan [zh_TW]
|
||||
3.34.4
|
||||
======
|
||||
* Handle mode set race conditions more gracefully [Jonas; !1007]
|
||||
* Fix fallback to GLES2 [Adam; #635]
|
||||
* Fix interoperation with wl_data_device_manager v1 [Carlos; #965]
|
||||
* Fix visual glitches with offscreen effects applied [Georges; !992]
|
||||
* Favor text over images in clipboard manager [Carlos; #919]
|
||||
* Fixes crashes [Jonas, Carlos; !961, !869]
|
||||
* Plugged memory leaks [Sebastian, Adam; !1002, !1011]
|
||||
* Misc. bug fixes [Carlos, Robert, Olivier; !1005, #878, !1031, !1034, !1040]
|
||||
|
||||
Contributors:
|
||||
Olivier Fourdan, Carlos Garnacho, Adam Jackson, Sebastian Keller,
|
||||
Robert Mader, Georges Basile Stavracas Neto, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Umarzuki Bin Mochlis Moktar [ms]
|
||||
|
||||
3.34.3
|
||||
======
|
||||
* Fix window recording on HiDPI [Pascal; !976]
|
||||
* Fix top-left pixel being insensitive to clicks [Sebastian; #893]
|
||||
|
||||
Contributors:
|
||||
Sebastian Keller, Pascal Nowack
|
||||
|
||||
3.34.2
|
||||
======
|
||||
* Fix immediate screen blank after releasing inhibitor [Tim; #573]
|
||||
* Respond to frame callbacks regardless of damage [Jonas Å.; !839]
|
||||
* Translate well-known selection atoms to mimetypes [Carlos; !842]
|
||||
* Fix Night Light on wayland [Jonas Å.; !840]
|
||||
* Fix various copy+paste/DND regressions [Carlos; !848, #789, #842,
|
||||
#793, #845, #854]
|
||||
* Don't emit focus event after desctruction [Marco; gnome-shell#1704, !860]
|
||||
* Fix hang when opening not-responding dialog on Xorg [Carlos; !876]
|
||||
* Fix frozen grabs on Xorg after weeks of inactivity [Jonas Å.; !886]
|
||||
* Fix triggering popups from stylus devices on wayland [Carlos; #886]
|
||||
* Support shadow framebuffers for offscreen rendering [Olivier; !917]
|
||||
* Fix hang after interacting with desktop icons on X11 [Marco; !909]
|
||||
* Don't double scale when getting absolute surface coordinates [Xiang; !915]
|
||||
* Kill window effects on destroy [Robert; !924]
|
||||
* Use partial damage for dma-buf and EGLImage buffers on wayland [Robert; #947]
|
||||
* Do not stack transients underneath their always-on-top parent [Florian; #587]
|
||||
* Fix KMS freeze after pageflip [Pekka; !953]
|
||||
* Fixed crashes [Robert, Jonas Å., Marco, Hans, Carlos, Tim; !856, !912, !895,
|
||||
!928, #591, !823, !960]
|
||||
* Plugged memory leaks [Niels, Robert, Carlos; !847, !868, !873]
|
||||
* Misc. bug fixes and cleanups [Daniel, Marco, Jonas Å., Georges, Cosimo,
|
||||
Florian, Hans, Robert, Jonas D.; !841, !764, !837, !846, !673, !811, !893,
|
||||
!925, !927, !940, !832]
|
||||
|
||||
Contributors:
|
||||
Marco Trevisan (Treviño), Cosimo Cecchi, Tim Crawford, Jonas Dreßler,
|
||||
Xiang Fan, Olivier Fourdan, Carlos Garnacho, Hans de Goede, Niels De Graef,
|
||||
Tim Klocke, Robert Mader, Florian Müllner, Georges Basile Stavracas Neto,
|
||||
Pekka Paalanen, Daniel van Vugt, Jonas Ådahl
|
||||
|
||||
Translators:
|
||||
Bruce Cowan [en_GB]
|
||||
3.34.1
|
||||
======
|
||||
* Fix startup of X11 session services on wayland [Carlos; #771]
|
||||
|
@ -75,8 +75,8 @@ struct _CallyRootPrivate
|
||||
GSList *stage_list;
|
||||
|
||||
/* signals id */
|
||||
guint stage_added_id;
|
||||
guint stage_removed_id;
|
||||
gulong stage_added_id;
|
||||
gulong stage_removed_id;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (CallyRoot, cally_root, ATK_TYPE_GOBJECT_ACCESSIBLE)
|
||||
@ -149,11 +149,9 @@ cally_root_finalize (GObject *object)
|
||||
|
||||
stage_manager = atk_gobject_accessible_get_object (ATK_GOBJECT_ACCESSIBLE (root));
|
||||
|
||||
g_signal_handler_disconnect (stage_manager,
|
||||
root->priv->stage_added_id);
|
||||
g_clear_signal_handler (&root->priv->stage_added_id, stage_manager);
|
||||
|
||||
g_signal_handler_disconnect (stage_manager,
|
||||
root->priv->stage_added_id);
|
||||
g_clear_signal_handler (&root->priv->stage_removed_id, stage_manager);
|
||||
|
||||
G_OBJECT_CLASS (cally_root_parent_class)->finalize (object);
|
||||
}
|
||||
|
@ -274,6 +274,9 @@ void _clutter_actor_set_enable_paint_unmapped
|
||||
void _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||
gboolean has_pointer);
|
||||
|
||||
void _clutter_actor_set_has_key_focus (ClutterActor *self,
|
||||
gboolean has_key_focus);
|
||||
|
||||
void _clutter_actor_queue_redraw_with_clip (ClutterActor *self,
|
||||
ClutterRedrawFlags flags,
|
||||
const ClutterPaintVolume *clip_volume);
|
||||
|
@ -835,6 +835,7 @@ struct _ClutterActorPrivate
|
||||
guint enable_model_view_transform : 1;
|
||||
guint enable_paint_unmapped : 1;
|
||||
guint has_pointer : 1;
|
||||
guint has_key_focus : 1;
|
||||
guint propagated_one_redraw : 1;
|
||||
guint paint_volume_valid : 1;
|
||||
guint last_paint_volume_valid : 1;
|
||||
@ -1691,6 +1692,20 @@ clutter_actor_is_mapped (ClutterActor *self)
|
||||
return CLUTTER_ACTOR_IS_MAPPED (self);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_unset_key_focus (ClutterActor *self)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
if (!self->priv->has_key_focus)
|
||||
return;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (self);
|
||||
|
||||
if (stage)
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_real_unmap (ClutterActor *self)
|
||||
{
|
||||
@ -1724,17 +1739,7 @@ clutter_actor_real_unmap (ClutterActor *self)
|
||||
|
||||
/* relinquish keyboard focus if we were unmapped while owning it */
|
||||
if (!CLUTTER_ACTOR_IS_TOPLEVEL (self))
|
||||
{
|
||||
ClutterStage *stage;
|
||||
|
||||
stage = CLUTTER_STAGE (_clutter_actor_get_stage_internal (self));
|
||||
|
||||
if (stage != NULL &&
|
||||
clutter_stage_get_key_focus (stage) == self)
|
||||
{
|
||||
clutter_stage_set_key_focus (stage, NULL);
|
||||
}
|
||||
}
|
||||
maybe_unset_key_focus (self);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -6064,6 +6069,8 @@ clutter_actor_dispose (GObject *object)
|
||||
object->ref_count,
|
||||
g_type_name (G_OBJECT_TYPE (self)));
|
||||
|
||||
maybe_unset_key_focus (self);
|
||||
|
||||
/* Stop the emission of any property change */
|
||||
g_object_freeze_notify (object);
|
||||
|
||||
@ -15979,6 +15986,9 @@ clutter_actor_grab_key_focus (ClutterActor *self)
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
if (self->priv->has_key_focus)
|
||||
return;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (self);
|
||||
if (stage != NULL)
|
||||
clutter_stage_set_key_focus (CLUTTER_STAGE (stage), self);
|
||||
@ -16768,6 +16778,23 @@ _clutter_actor_set_has_pointer (ClutterActor *self,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_actor_set_has_key_focus (ClutterActor *self,
|
||||
gboolean has_key_focus)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
|
||||
if (priv->has_key_focus != has_key_focus)
|
||||
{
|
||||
priv->has_key_focus = has_key_focus;
|
||||
|
||||
if (has_key_focus)
|
||||
g_signal_emit (self, actor_signals[KEY_FOCUS_IN], 0);
|
||||
else
|
||||
g_signal_emit (self, actor_signals[KEY_FOCUS_OUT], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_get_text_direction:
|
||||
* @self: a #ClutterActor
|
||||
@ -17616,15 +17643,9 @@ clutter_actor_clear_effects (ClutterActor *self)
|
||||
gboolean
|
||||
clutter_actor_has_key_focus (ClutterActor *self)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self), FALSE);
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (self);
|
||||
if (stage == NULL)
|
||||
return FALSE;
|
||||
|
||||
return clutter_stage_get_key_focus (CLUTTER_STAGE (stage)) == self;
|
||||
return self->priv->has_key_focus;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -121,12 +121,12 @@ G_DEFINE_TYPE (ClutterBrightnessContrastEffect,
|
||||
static gboolean
|
||||
will_have_no_effect (ClutterBrightnessContrastEffect *self)
|
||||
{
|
||||
return (self->brightness_red == no_change &&
|
||||
self->brightness_green == no_change &&
|
||||
self->brightness_blue == no_change &&
|
||||
self->contrast_red == no_change &&
|
||||
self->contrast_green == no_change &&
|
||||
self->contrast_blue == no_change);
|
||||
return (G_APPROX_VALUE (self->brightness_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->brightness_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->brightness_blue, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_red, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_green, no_change, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (self->contrast_blue, no_change, FLT_EPSILON));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -494,9 +494,9 @@ clutter_brightness_contrast_effect_set_brightness_full (ClutterBrightnessContras
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
if (red == effect->brightness_red &&
|
||||
green == effect->brightness_green &&
|
||||
blue == effect->brightness_blue)
|
||||
if (G_APPROX_VALUE (red, effect->brightness_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, effect->brightness_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, effect->brightness_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
effect->brightness_red = red;
|
||||
@ -584,9 +584,9 @@ clutter_brightness_contrast_effect_set_contrast_full (ClutterBrightnessContrastE
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BRIGHTNESS_CONTRAST_EFFECT (effect));
|
||||
|
||||
if (red == effect->contrast_red &&
|
||||
green == effect->contrast_green &&
|
||||
blue == effect->contrast_blue)
|
||||
if (G_APPROX_VALUE (red, effect->contrast_red, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (green, effect->contrast_green, FLT_EPSILON) &&
|
||||
G_APPROX_VALUE (blue, effect->contrast_blue, FLT_EPSILON))
|
||||
return;
|
||||
|
||||
effect->contrast_red = red;
|
||||
|
@ -117,11 +117,7 @@ clutter_offscreen_effect_set_actor (ClutterActorMeta *meta,
|
||||
meta_class->set_actor (meta, actor);
|
||||
|
||||
/* clear out the previous state */
|
||||
if (priv->offscreen != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
priv->offscreen = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
/* we keep a back pointer here, to avoid going through the ActorMeta */
|
||||
priv->actor = clutter_actor_meta_get_actor (meta);
|
||||
@ -197,17 +193,8 @@ update_fbo (ClutterEffect *effect,
|
||||
ensure_pipeline_filter_for_scale (self, resource_scale);
|
||||
}
|
||||
|
||||
if (priv->texture != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->texture);
|
||||
priv->texture = NULL;
|
||||
}
|
||||
|
||||
if (priv->offscreen != NULL)
|
||||
{
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
priv->offscreen = NULL;
|
||||
}
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
priv->texture =
|
||||
clutter_offscreen_effect_create_texture (self, target_width, target_height);
|
||||
@ -471,29 +458,44 @@ clutter_offscreen_effect_paint (ClutterEffect *effect,
|
||||
*/
|
||||
if (priv->offscreen == NULL || (flags & CLUTTER_EFFECT_PAINT_ACTOR_DIRTY))
|
||||
{
|
||||
/* Chain up to the parent paint method which will call the pre and
|
||||
post paint functions to update the image */
|
||||
CLUTTER_EFFECT_CLASS (clutter_offscreen_effect_parent_class)->
|
||||
paint (effect, flags);
|
||||
ClutterEffectClass *effect_class = CLUTTER_EFFECT_GET_CLASS (effect);
|
||||
gboolean pre_paint_succeeded;
|
||||
|
||||
pre_paint_succeeded = effect_class->pre_paint (effect);
|
||||
|
||||
clutter_actor_continue_paint (priv->actor);
|
||||
|
||||
if (pre_paint_succeeded)
|
||||
effect_class->post_paint (effect);
|
||||
else
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
}
|
||||
else
|
||||
clutter_offscreen_effect_paint_texture (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_notify (GObject *gobject,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = offscreen_effect->priv;
|
||||
|
||||
if (strcmp (pspec->name, "enabled") == 0)
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->notify (gobject, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_offscreen_effect_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterOffscreenEffect *self = CLUTTER_OFFSCREEN_EFFECT (gobject);
|
||||
ClutterOffscreenEffectPrivate *priv = self->priv;
|
||||
|
||||
if (priv->offscreen)
|
||||
cogl_handle_unref (priv->offscreen);
|
||||
|
||||
if (priv->target)
|
||||
cogl_handle_unref (priv->target);
|
||||
|
||||
if (priv->texture)
|
||||
cogl_handle_unref (priv->texture);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->texture, cogl_object_unref);
|
||||
g_clear_pointer (&priv->target, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_offscreen_effect_parent_class)->finalize (gobject);
|
||||
}
|
||||
@ -515,6 +517,7 @@ clutter_offscreen_effect_class_init (ClutterOffscreenEffectClass *klass)
|
||||
effect_class->paint = clutter_offscreen_effect_paint;
|
||||
|
||||
gobject_class->finalize = clutter_offscreen_effect_finalize;
|
||||
gobject_class->notify = clutter_offscreen_effect_notify;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -30,6 +30,7 @@ enum
|
||||
PROP_LAYOUT,
|
||||
PROP_FRAMEBUFFER,
|
||||
PROP_OFFSCREEN,
|
||||
PROP_SHADOWFB,
|
||||
PROP_SCALE,
|
||||
|
||||
PROP_LAST
|
||||
@ -44,7 +45,10 @@ typedef struct _ClutterStageViewPrivate
|
||||
CoglFramebuffer *framebuffer;
|
||||
|
||||
CoglOffscreen *offscreen;
|
||||
CoglPipeline *pipeline;
|
||||
CoglPipeline *offscreen_pipeline;
|
||||
|
||||
CoglOffscreen *shadowfb;
|
||||
CoglPipeline *shadowfb_pipeline;
|
||||
|
||||
guint dirty_viewport : 1;
|
||||
guint dirty_projection : 1;
|
||||
@ -78,6 +82,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view)
|
||||
|
||||
if (priv->offscreen)
|
||||
return priv->offscreen;
|
||||
else if (priv->shadowfb)
|
||||
return priv->shadowfb;
|
||||
else
|
||||
return priv->framebuffer;
|
||||
}
|
||||
@ -99,6 +105,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view)
|
||||
return priv->framebuffer;
|
||||
}
|
||||
|
||||
static CoglPipeline *
|
||||
clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer)
|
||||
{
|
||||
CoglPipeline *pipeline;
|
||||
|
||||
pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer));
|
||||
|
||||
cogl_pipeline_set_layer_filters (pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0,
|
||||
cogl_offscreen_get_texture (framebuffer));
|
||||
cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
{
|
||||
@ -109,21 +133,27 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
|
||||
g_assert (priv->offscreen != NULL);
|
||||
|
||||
if (priv->pipeline)
|
||||
if (priv->offscreen_pipeline)
|
||||
return;
|
||||
|
||||
priv->pipeline =
|
||||
cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen));
|
||||
cogl_pipeline_set_layer_filters (priv->pipeline, 0,
|
||||
COGL_PIPELINE_FILTER_NEAREST,
|
||||
COGL_PIPELINE_FILTER_NEAREST);
|
||||
cogl_pipeline_set_layer_texture (priv->pipeline, 0,
|
||||
cogl_offscreen_get_texture (priv->offscreen));
|
||||
cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0,
|
||||
COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
|
||||
priv->offscreen_pipeline =
|
||||
clutter_stage_view_create_framebuffer_pipeline (priv->offscreen);
|
||||
|
||||
if (view_class->setup_offscreen_blit_pipeline)
|
||||
view_class->setup_offscreen_blit_pipeline (view, priv->pipeline);
|
||||
view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view)
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
if (priv->shadowfb_pipeline)
|
||||
return;
|
||||
|
||||
priv->shadowfb_pipeline =
|
||||
clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb);
|
||||
}
|
||||
|
||||
void
|
||||
@ -132,7 +162,45 @@ clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view)
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
CoglPipeline *pipeline,
|
||||
CoglFramebuffer *src_framebuffer,
|
||||
CoglFramebuffer *dst_framebuffer,
|
||||
gboolean can_blit)
|
||||
{
|
||||
CoglMatrix matrix;
|
||||
|
||||
/* First, try with blit */
|
||||
if (can_blit)
|
||||
{
|
||||
if (cogl_blit_framebuffer (src_framebuffer,
|
||||
dst_framebuffer,
|
||||
0, 0,
|
||||
0, 0,
|
||||
cogl_framebuffer_get_width (dst_framebuffer),
|
||||
cogl_framebuffer_get_height (dst_framebuffer),
|
||||
NULL))
|
||||
return;
|
||||
}
|
||||
|
||||
/* If blit fails, fallback to the slower painting method */
|
||||
cogl_framebuffer_push_matrix (dst_framebuffer);
|
||||
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
cogl_matrix_translate (&matrix, -1, 1, 0);
|
||||
cogl_matrix_scale (&matrix, 2, -2, 0);
|
||||
cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (dst_framebuffer,
|
||||
pipeline,
|
||||
0, 0, 1, 1);
|
||||
|
||||
cogl_framebuffer_pop_matrix (dst_framebuffer);
|
||||
}
|
||||
|
||||
void
|
||||
@ -141,39 +209,46 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view,
|
||||
{
|
||||
ClutterStageViewPrivate *priv =
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
CoglMatrix matrix;
|
||||
|
||||
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
|
||||
if (cogl_matrix_is_identity (&matrix))
|
||||
if (priv->offscreen)
|
||||
{
|
||||
int fb_width = cogl_framebuffer_get_width (priv->framebuffer);
|
||||
int fb_height = cogl_framebuffer_get_height (priv->framebuffer);
|
||||
gboolean can_blit;
|
||||
CoglMatrix matrix;
|
||||
|
||||
if (cogl_blit_framebuffer (priv->offscreen,
|
||||
priv->framebuffer,
|
||||
0, 0,
|
||||
0, 0,
|
||||
fb_width, fb_height,
|
||||
NULL))
|
||||
return;
|
||||
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
|
||||
clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix);
|
||||
can_blit = cogl_matrix_is_identity (&matrix);
|
||||
|
||||
if (priv->shadowfb)
|
||||
{
|
||||
clutter_stage_view_copy_to_framebuffer (view,
|
||||
rect,
|
||||
priv->offscreen_pipeline,
|
||||
priv->offscreen,
|
||||
priv->shadowfb,
|
||||
can_blit);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_stage_view_copy_to_framebuffer (view,
|
||||
rect,
|
||||
priv->offscreen_pipeline,
|
||||
priv->offscreen,
|
||||
priv->framebuffer,
|
||||
can_blit);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_stage_view_ensure_offscreen_blit_pipeline (view);
|
||||
cogl_framebuffer_push_matrix (priv->framebuffer);
|
||||
|
||||
/* Set transform so 0,0 is on the top left corner and 1,1 on
|
||||
* the bottom right corner.
|
||||
*/
|
||||
cogl_matrix_init_identity (&matrix);
|
||||
cogl_matrix_translate (&matrix, -1, 1, 0);
|
||||
cogl_matrix_scale (&matrix, 2, -2, 0);
|
||||
cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (priv->framebuffer,
|
||||
priv->pipeline,
|
||||
0, 0, 1, 1);
|
||||
|
||||
cogl_framebuffer_pop_matrix (priv->framebuffer);
|
||||
if (priv->shadowfb)
|
||||
{
|
||||
clutter_stage_view_ensure_shadowfb_blit_pipeline (view);
|
||||
clutter_stage_view_copy_to_framebuffer (view,
|
||||
rect,
|
||||
priv->shadowfb_pipeline,
|
||||
priv->shadowfb,
|
||||
priv->framebuffer,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
@ -273,6 +348,9 @@ clutter_stage_view_get_property (GObject *object,
|
||||
case PROP_OFFSCREEN:
|
||||
g_value_set_boxed (value, priv->offscreen);
|
||||
break;
|
||||
case PROP_SHADOWFB:
|
||||
g_value_set_boxed (value, priv->shadowfb);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
g_value_set_float (value, priv->scale);
|
||||
break;
|
||||
@ -318,6 +396,9 @@ clutter_stage_view_set_property (GObject *object,
|
||||
case PROP_OFFSCREEN:
|
||||
priv->offscreen = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_SHADOWFB:
|
||||
priv->shadowfb = g_value_dup_boxed (value);
|
||||
break;
|
||||
case PROP_SCALE:
|
||||
priv->scale = g_value_get_float (value);
|
||||
break;
|
||||
@ -334,8 +415,10 @@ clutter_stage_view_dispose (GObject *object)
|
||||
clutter_stage_view_get_instance_private (view);
|
||||
|
||||
g_clear_pointer (&priv->framebuffer, cogl_object_unref);
|
||||
g_clear_pointer (&priv->shadowfb, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref);
|
||||
g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object);
|
||||
}
|
||||
@ -390,6 +473,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_SHADOWFB] =
|
||||
g_param_spec_boxed ("shadowfb",
|
||||
"Shadow framebuffer",
|
||||
"Framebuffer used as intermediate shadow buffer",
|
||||
COGL_TYPE_HANDLE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
obj_props[PROP_SCALE] =
|
||||
g_param_spec_float ("scale",
|
||||
"View scale",
|
||||
|
@ -486,9 +486,9 @@ is_inside_axis_aligned_rectangle (const ClutterPoint *point,
|
||||
const ClutterPoint *vertices)
|
||||
{
|
||||
float min_x = FLT_MAX;
|
||||
float max_x = FLT_MIN;
|
||||
float max_x = -FLT_MAX;
|
||||
float min_y = FLT_MAX;
|
||||
float max_y = FLT_MIN;
|
||||
float max_y = -FLT_MAX;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
@ -1066,10 +1066,7 @@ clutter_stage_emit_key_focus_event (ClutterStage *stage,
|
||||
if (priv->key_focused_actor == NULL)
|
||||
return;
|
||||
|
||||
if (focus_in)
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
|
||||
else
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), focus_in);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||
}
|
||||
@ -3011,14 +3008,6 @@ clutter_stage_get_title (ClutterStage *stage)
|
||||
return stage->priv->title;
|
||||
}
|
||||
|
||||
static void
|
||||
on_key_focus_destroy (ClutterActor *actor,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
/* unset the key focus */
|
||||
clutter_stage_set_key_focus (stage, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_set_key_focus:
|
||||
* @stage: the #ClutterStage
|
||||
@ -3058,18 +3047,14 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
old_focused_actor = priv->key_focused_actor;
|
||||
|
||||
/* set key_focused_actor to NULL before emitting the signal or someone
|
||||
* might hide the previously focused actor in the signal handler and we'd
|
||||
* get re-entrant call and get glib critical from g_object_weak_unref
|
||||
* might hide the previously focused actor in the signal handler
|
||||
*/
|
||||
g_signal_handlers_disconnect_by_func (priv->key_focused_actor,
|
||||
G_CALLBACK (on_key_focus_destroy),
|
||||
stage);
|
||||
priv->key_focused_actor = NULL;
|
||||
|
||||
g_signal_emit_by_name (old_focused_actor, "key-focus-out");
|
||||
_clutter_actor_set_has_key_focus (old_focused_actor, FALSE);
|
||||
}
|
||||
else
|
||||
g_signal_emit_by_name (stage, "key-focus-out");
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), FALSE);
|
||||
|
||||
/* Note, if someone changes key focus in focus-out signal handler we'd be
|
||||
* overriding the latter call below moving the focus where it was originally
|
||||
@ -3079,14 +3064,10 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
if (actor != NULL)
|
||||
{
|
||||
priv->key_focused_actor = actor;
|
||||
|
||||
g_signal_connect (actor,
|
||||
"destroy", G_CALLBACK (on_key_focus_destroy),
|
||||
stage);
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
|
||||
_clutter_actor_set_has_key_focus (actor, TRUE);
|
||||
}
|
||||
else
|
||||
g_signal_emit_by_name (stage, "key-focus-in");
|
||||
_clutter_actor_set_has_key_focus (CLUTTER_ACTOR (stage), TRUE);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (stage), obj_props[PROP_KEY_FOCUS]);
|
||||
}
|
||||
|
@ -526,11 +526,7 @@ paint_stage (ClutterStageCogl *stage_cogl,
|
||||
_clutter_stage_maybe_setup_viewport (stage, view);
|
||||
_clutter_stage_paint_view (stage, view, clip);
|
||||
|
||||
if (clutter_stage_view_get_onscreen (view) !=
|
||||
clutter_stage_view_get_framebuffer (view))
|
||||
{
|
||||
clutter_stage_view_blit_offscreen (view, clip);
|
||||
}
|
||||
clutter_stage_view_blit_offscreen (view, clip);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -329,6 +329,8 @@ try_create_context (CoglDisplay *display,
|
||||
if (renderer->driver == COGL_DRIVER_GL ||
|
||||
renderer->driver == COGL_DRIVER_GL3)
|
||||
eglBindAPI (EGL_OPENGL_API);
|
||||
else if (renderer->driver == COGL_DRIVER_GLES2)
|
||||
eglBindAPI (EGL_OPENGL_ES_API);
|
||||
|
||||
egl_attributes_from_framebuffer_config (display,
|
||||
&display->onscreen_template->config,
|
||||
|
@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.34.1',
|
||||
version: '3.34.6',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
208
po/en_GB.po
208
po/en_GB.po
@ -6,21 +6,22 @@
|
||||
# Philip Withnall <philip@tecnocode.co.uk>, 2010.
|
||||
# Chris Leonard <cjlhomeaddress@gmail.com>, 2012.
|
||||
# Bruce Cowan <bruce@bcowan.me.uk>, 2011, 2012, 2013, 2018.
|
||||
# Zander Brown <zbrown@gnome.org>, 2019.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mutter\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||
"POT-Creation-Date: 2018-07-07 09:58+0000\n"
|
||||
"PO-Revision-Date: 2018-08-19 17:43+0100\n"
|
||||
"Last-Translator: Bruce Cowan <bruce@bcowan.me.uk>\n"
|
||||
"Language-Team: British English <en@li.org>\n"
|
||||
"POT-Creation-Date: 2019-11-22 01:35+0000\n"
|
||||
"PO-Revision-Date: 2019-08-25 15:11+0100\n"
|
||||
"Last-Translator: Zander Brown <zbrown@gnome.org>\n"
|
||||
"Language-Team: English - United Kingdom <en_GB@li.org>\n"
|
||||
"Language: en_GB\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.0.7\n"
|
||||
"X-Generator: Gtranslator 3.32.1\n"
|
||||
"X-Project-Style: gnome\n"
|
||||
|
||||
#: data/50-mutter-navigation.xml:6
|
||||
@ -256,11 +257,6 @@ msgid "Modifier to use for extended window management operations"
|
||||
msgstr "Modifier to use for extended window management operations"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:8
|
||||
#| msgid ""
|
||||
#| "This key will initiate the \"overlay\", which is a combination window "
|
||||
#| "overview and application launching system. The default is intended to be "
|
||||
#| "the \"Windows key\" on PC hardware. It's expected that this binding "
|
||||
#| "either the default or set to the empty string."
|
||||
msgid ""
|
||||
"This key will initiate the “overlay”, which is a combination window overview "
|
||||
"and application launching system. The default is intended to be the “Windows "
|
||||
@ -305,10 +301,6 @@ msgid "Workspaces are managed dynamically"
|
||||
msgstr "Workspaces are managed dynamically"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:41
|
||||
#| msgid ""
|
||||
#| "Determines whether workspaces are managed dynamically or whether there's "
|
||||
#| "a static number of workspaces (determined by the num-workspaces key in "
|
||||
#| "org.gnome.desktop.wm.preferences)."
|
||||
msgid ""
|
||||
"Determines whether workspaces are managed dynamically or whether there’s a "
|
||||
"static number of workspaces (determined by the num-workspaces key in org."
|
||||
@ -347,10 +339,6 @@ msgid "Delay focus changes until the pointer stops moving"
|
||||
msgstr "Delay focus changes until the pointer stops moving"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:69
|
||||
#| msgid ""
|
||||
#| "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
|
||||
#| "the focus will not be changed immediately when entering a window, but "
|
||||
#| "only after the pointer stops moving."
|
||||
msgid ""
|
||||
"If set to true, and the focus mode is either “sloppy” or “mouse” then the "
|
||||
"focus will not be changed immediately when entering a window, but only after "
|
||||
@ -365,9 +353,6 @@ msgid "Draggable border width"
|
||||
msgstr "Draggable border width"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:80
|
||||
#| msgid ""
|
||||
#| "The amount of total draggable borders. If the theme's visible borders are "
|
||||
#| "not enough, invisible borders will be added to meet this value."
|
||||
msgid ""
|
||||
"The amount of total draggable borders. If the theme’s visible borders are "
|
||||
"not enough, invisible borders will be added to meet this value."
|
||||
@ -412,7 +397,10 @@ msgid ""
|
||||
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
||||
"mutter default to layout logical monitors in a logical pixel coordinate "
|
||||
"space, while scaling monitor framebuffers instead of window content, to "
|
||||
"manage HiDPI monitors. Does not require a restart."
|
||||
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
|
||||
"mutter request a low priority real-time scheduling. The executable or user "
|
||||
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
|
||||
"initializes Xwayland lazily if there are X11 clients. Requires restart."
|
||||
msgstr ""
|
||||
"To enable experimental features, add the feature keyword to the list. "
|
||||
"Whether the feature requires restarting the compositor depends on the given "
|
||||
@ -421,22 +409,32 @@ msgstr ""
|
||||
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
||||
"mutter default to layout logical monitors in a logical pixel coordinate "
|
||||
"space, while scaling monitor framebuffers instead of window content, to "
|
||||
"manage HiDPI monitors. Does not require a restart."
|
||||
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
|
||||
"mutter request a low priority real-time scheduling. The executable or user "
|
||||
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
|
||||
"initialises Xwayland lazily if there are X11 clients. Requires restart."
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:141
|
||||
#: data/org.gnome.mutter.gschema.xml.in:134
|
||||
msgid "Modifier to use to locate the pointer"
|
||||
msgstr "Modifier to use to locate the pointer"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:135
|
||||
msgid "This key will initiate the “locate pointer” action."
|
||||
msgstr "This key will initiate the “locate pointer” action."
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:155
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "Select window from tab popup"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:146
|
||||
#: data/org.gnome.mutter.gschema.xml.in:160
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "Cancel tab popup"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:151
|
||||
#| msgid "Switch monitor"
|
||||
#: data/org.gnome.mutter.gschema.xml.in:165
|
||||
msgid "Switch monitor configurations"
|
||||
msgstr "Switch monitor configurations"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:156
|
||||
#: data/org.gnome.mutter.gschema.xml.in:170
|
||||
msgid "Rotates the built-in monitor configuration"
|
||||
msgstr "Rotates the built-in monitor configuration"
|
||||
|
||||
@ -493,28 +491,36 @@ msgid "Re-enable shortcuts"
|
||||
msgstr "Re-enable shortcuts"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
|
||||
msgid "Allow grabs with Xwayland"
|
||||
msgstr "Allow grabs with Xwayland"
|
||||
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
|
||||
msgstr "Allow X11 grabs to lock keyboard focus with Xwayland"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
||||
msgid ""
|
||||
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
"taken into account. For a X11 grab to be taken into account under Wayland, "
|
||||
"the client must also either send a specific X11 ClientMessage to the root "
|
||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
||||
"access-rules”."
|
||||
"Allow all keyboard events to be routed to X11 “override redirect” windows "
|
||||
"with a grab when running in Xwayland. This option is to support X11 clients "
|
||||
"which map an “override redirect” window (which do not receive keyboard "
|
||||
"focus) and issue a keyboard grab to force all keyboard events to that "
|
||||
"window. This option is seldom used and has no effect on regular X11 windows "
|
||||
"which can receive keyboard focus under normal circumstances. For a X11 grab "
|
||||
"to be taken into account under Wayland, the client must also either send a "
|
||||
"specific X11 ClientMessage to the root window or be among the applications "
|
||||
"white-listed in key “xwayland-grab-access-rules”."
|
||||
msgstr ""
|
||||
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
"taken into account. For a X11 grab to be taken into account under Wayland, "
|
||||
"the client must also either send a specific X11 ClientMessage to the root "
|
||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
||||
"access-rules”."
|
||||
"Allow all keyboard events to be routed to X11 “override redirect” windows "
|
||||
"with a grab when running in Xwayland. This option is to support X11 clients "
|
||||
"which map an “override redirect” window (which do not receive keyboard "
|
||||
"focus) and issue a keyboard grab to force all keyboard events to that "
|
||||
"window. This option is seldom used and has no effect on regular X11 windows "
|
||||
"which can receive keyboard focus under normal circumstances. For a X11 grab "
|
||||
"to be taken into account under Wayland, the client must also either send a "
|
||||
"specific X11 ClientMessage to the root window or be among the applications "
|
||||
"white-listed in key “xwayland-grab-access-rules”."
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
|
||||
msgid "Xwayland applications allowed to issue keyboard grabs"
|
||||
msgstr "Xwayland applications allowed to issue keyboard grabs"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
|
||||
msgid ""
|
||||
"List the resource names or resource class of X11 windows either allowed or "
|
||||
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
|
||||
@ -541,114 +547,122 @@ msgstr ""
|
||||
#. TRANSLATORS: This string refers to a button that switches between
|
||||
#. * different modes.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2325
|
||||
#: src/backends/meta-input-settings.c:2528
|
||||
#, c-format
|
||||
#| msgid "Mode Switch: Mode %d"
|
||||
msgid "Mode Switch (Group %d)"
|
||||
msgstr "Mode Switch (Group %d)"
|
||||
|
||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
#. * mapping through the available outputs.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2348
|
||||
#: src/backends/meta-input-settings.c:2551
|
||||
msgid "Switch monitor"
|
||||
msgstr "Switch monitor"
|
||||
|
||||
#: src/backends/meta-input-settings.c:2350
|
||||
#: src/backends/meta-input-settings.c:2553
|
||||
msgid "Show on-screen help"
|
||||
msgstr "Show on-screen help"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:907
|
||||
#: src/backends/meta-monitor.c:223
|
||||
msgid "Built-in display"
|
||||
msgstr "Built-in display"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:930
|
||||
#: src/backends/meta-monitor.c:252
|
||||
msgid "Unknown"
|
||||
msgstr "Unknown"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:932
|
||||
#: src/backends/meta-monitor.c:254
|
||||
msgid "Unknown Display"
|
||||
msgstr "Unknown Display"
|
||||
|
||||
#. TRANSLATORS: this is a monitor vendor name, followed by a
|
||||
#. * size in inches, like 'Dell 15"'
|
||||
#.
|
||||
#: src/backends/meta-monitor-manager.c:940
|
||||
#: src/backends/meta-monitor.c:262
|
||||
#, c-format
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#: src/backends/meta-monitor.c:270
|
||||
#, c-format
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name followed by product/model name where size in "
|
||||
"inches could not be calculated, e.g. Dell U2414H"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. Translators: this string will appear in Sysprof
|
||||
#: src/backends/meta-profiler.c:79
|
||||
msgid "Compositor"
|
||||
msgstr "Compositor"
|
||||
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: src/compositor/compositor.c:481
|
||||
#: src/compositor/compositor.c:533
|
||||
#, c-format
|
||||
#| msgid ""
|
||||
#| "Another compositing manager is already running on screen %i on display "
|
||||
#| "\"%s\"."
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display “%s”."
|
||||
msgstr ""
|
||||
"Another compositing manager is already running on screen %i on display “%s”."
|
||||
|
||||
#: src/core/bell.c:254
|
||||
#: src/core/bell.c:192
|
||||
msgid "Bell event"
|
||||
msgstr "Bell event"
|
||||
|
||||
#: src/core/main.c:191
|
||||
#: src/core/main.c:190
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "Disable connection to session manager"
|
||||
|
||||
#: src/core/main.c:197
|
||||
#: src/core/main.c:196
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "Replace the running window manager"
|
||||
|
||||
#: src/core/main.c:203
|
||||
#: src/core/main.c:202
|
||||
msgid "Specify session management ID"
|
||||
msgstr "Specify session management ID"
|
||||
|
||||
#: src/core/main.c:208
|
||||
#: src/core/main.c:207
|
||||
msgid "X Display to use"
|
||||
msgstr "X Display to use"
|
||||
|
||||
#: src/core/main.c:214
|
||||
#: src/core/main.c:213
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "Initialise session from savefile"
|
||||
|
||||
#: src/core/main.c:220
|
||||
#: src/core/main.c:219
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "Make X calls synchronous"
|
||||
|
||||
#: src/core/main.c:227
|
||||
#: src/core/main.c:226
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "Run as a wayland compositor"
|
||||
|
||||
#: src/core/main.c:233
|
||||
#: src/core/main.c:232
|
||||
msgid "Run as a nested compositor"
|
||||
msgstr "Run as a nested compositor"
|
||||
|
||||
#: src/core/main.c:239
|
||||
#: src/core/main.c:238
|
||||
msgid "Run wayland compositor without starting Xwayland"
|
||||
msgstr "Run wayland compositor without starting Xwayland"
|
||||
|
||||
#: src/core/main.c:247
|
||||
#: src/core/main.c:246
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "Run as a full display server, rather than nested"
|
||||
|
||||
#: src/core/main.c:253
|
||||
#: src/core/main.c:252
|
||||
msgid "Run with X11 backend"
|
||||
msgstr "Run with X11 backend"
|
||||
|
||||
#. Translators: %s is a window title
|
||||
#: src/core/meta-close-dialog-default.c:148
|
||||
#: src/core/meta-close-dialog-default.c:151
|
||||
#, c-format
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "“%s” is not responding."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:150
|
||||
#: src/core/meta-close-dialog-default.c:153
|
||||
msgid "Application is not responding."
|
||||
msgstr "Application is not responding."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:155
|
||||
#: src/core/meta-close-dialog-default.c:158
|
||||
msgid ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
@ -656,22 +670,16 @@ msgstr ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:162
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Force Quit"
|
||||
msgstr "_Force Quit"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:162
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Wait"
|
||||
msgstr "_Wait"
|
||||
|
||||
#: src/core/mutter.c:39
|
||||
#: src/core/mutter.c:38
|
||||
#, c-format
|
||||
#| msgid ""
|
||||
#| "mutter %s\n"
|
||||
#| "Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
#| "This is free software; see the source for copying conditions.\n"
|
||||
#| "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
|
||||
#| "PARTICULAR PURPOSE.\n"
|
||||
msgid ""
|
||||
"mutter %s\n"
|
||||
"Copyright © 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
|
||||
@ -685,33 +693,30 @@ msgstr ""
|
||||
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
|
||||
"PARTICULAR PURPOSE.\n"
|
||||
|
||||
#: src/core/mutter.c:53
|
||||
#: src/core/mutter.c:52
|
||||
msgid "Print version"
|
||||
msgstr "Print version"
|
||||
|
||||
#: src/core/mutter.c:59
|
||||
#: src/core/mutter.c:58
|
||||
msgid "Mutter plugin to use"
|
||||
msgstr "Mutter plugin to use"
|
||||
|
||||
#: src/core/prefs.c:1915
|
||||
#: src/core/prefs.c:1849
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "Workspace %d"
|
||||
|
||||
#: src/core/util.c:120
|
||||
#: src/core/util.c:122
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "Mutter was compiled without support for verbose mode\n"
|
||||
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:567
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:568
|
||||
#, c-format
|
||||
msgid "Mode Switch: Mode %d"
|
||||
msgstr "Mode Switch: Mode %d"
|
||||
|
||||
#: src/x11/meta-x11-display.c:666
|
||||
#: src/x11/meta-x11-display.c:675
|
||||
#, c-format
|
||||
#| msgid ""
|
||||
#| "Display \"%s\" already has a window manager; try using the --replace "
|
||||
#| "option to replace the current window manager."
|
||||
msgid ""
|
||||
"Display “%s” already has a window manager; try using the --replace option to "
|
||||
"replace the current window manager."
|
||||
@ -719,26 +724,26 @@ msgstr ""
|
||||
"Display “%s” already has a window manager; try using the --replace option to "
|
||||
"replace the current window manager."
|
||||
|
||||
#: src/x11/meta-x11-display.c:1010
|
||||
#: src/x11/meta-x11-display.c:1036
|
||||
msgid "Failed to initialize GDK\n"
|
||||
msgstr "Failed to initialise GDK\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1034
|
||||
#: src/x11/meta-x11-display.c:1060
|
||||
#, c-format
|
||||
#| msgid "Failed to open X Window System display '%s'\n"
|
||||
msgid "Failed to open X Window System display “%s”\n"
|
||||
msgstr "Failed to open X Window System display “%s”\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1117
|
||||
#: src/x11/meta-x11-display.c:1143
|
||||
#, c-format
|
||||
#| msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgid "Screen %d on display “%s” is invalid\n"
|
||||
msgstr "Screen %d on display “%s” is invalid\n"
|
||||
|
||||
#: src/x11/session.c:1819
|
||||
#| msgid ""
|
||||
#| "These windows do not support "save current setup" and will have "
|
||||
#| "to be restarted manually next time you log in."
|
||||
#: src/x11/meta-x11-selection-input-stream.c:460
|
||||
#, c-format
|
||||
msgid "Format %s not supported"
|
||||
msgstr "Format %s not supported"
|
||||
|
||||
#: src/x11/session.c:1821
|
||||
msgid ""
|
||||
"These windows do not support “save current setup” and will have to be "
|
||||
"restarted manually next time you log in."
|
||||
@ -746,7 +751,7 @@ msgstr ""
|
||||
"These windows do not support “save current setup” and will have to be "
|
||||
"restarted manually next time you log in."
|
||||
|
||||
#: src/x11/window-props.c:565
|
||||
#: src/x11/window-props.c:569
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s (on %s)"
|
||||
@ -2033,9 +2038,6 @@ msgstr "%s (on %s)"
|
||||
#~ msgid "Commands to run in response to keybindings"
|
||||
#~ msgstr "Commands to run in response to keybindings"
|
||||
|
||||
#~ msgid "Compositing Manager"
|
||||
#~ msgstr "Compositing Manager"
|
||||
|
||||
#~ msgid "Control how new windows get focus"
|
||||
#~ msgstr "Control how new windows get focus"
|
||||
|
||||
|
158
po/zh_TW.po
158
po/zh_TW.po
@ -10,8 +10,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: metacity 3.3.4\n"
|
||||
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
|
||||
"POT-Creation-Date: 2019-02-04 17:52+0000\n"
|
||||
"PO-Revision-Date: 2019-02-17 23:15+0800\n"
|
||||
"POT-Creation-Date: 2019-11-21 15:22+0000\n"
|
||||
"PO-Revision-Date: 2019-11-23 13:58+0800\n"
|
||||
"Last-Translator: pan93412 <pan93412@gmail.com>\n"
|
||||
"Language-Team: Chinese <zh-l10n@linux.org.tw>\n"
|
||||
"Language: zh_TW\n"
|
||||
@ -19,7 +19,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Lokalize 18.12.2\n"
|
||||
"X-Generator: Lokalize 19.11.80\n"
|
||||
|
||||
#: data/50-mutter-navigation.xml:6
|
||||
msgid "Navigation"
|
||||
@ -371,6 +371,16 @@ msgid "Enable experimental features"
|
||||
msgstr "啟用試驗性功能"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:108
|
||||
#| msgid ""
|
||||
#| "To enable experimental features, add the feature keyword to the list. "
|
||||
#| "Whether the feature requires restarting the compositor depends on the "
|
||||
#| "given feature. Any experimental feature is not required to still be "
|
||||
#| "available, or configurable. Don’t expect adding anything in this setting "
|
||||
#| "to be future proof. Currently possible keywords: • “scale-monitor-"
|
||||
#| "framebuffer” — makes mutter default to layout logical monitors in a "
|
||||
#| "logical pixel coordinate space, while scaling monitor framebuffers "
|
||||
#| "instead of window content, to manage HiDPI monitors. Does not require a "
|
||||
#| "restart."
|
||||
msgid ""
|
||||
"To enable experimental features, add the feature keyword to the list. "
|
||||
"Whether the feature requires restarting the compositor depends on the given "
|
||||
@ -379,27 +389,41 @@ msgid ""
|
||||
"proof. Currently possible keywords: • “scale-monitor-framebuffer” — makes "
|
||||
"mutter default to layout logical monitors in a logical pixel coordinate "
|
||||
"space, while scaling monitor framebuffers instead of window content, to "
|
||||
"manage HiDPI monitors. Does not require a restart."
|
||||
"manage HiDPI monitors. Does not require a restart. • “rt-scheduler” — makes "
|
||||
"mutter request a low priority real-time scheduling. The executable or user "
|
||||
"must have CAP_SYS_NICE. Requires a restart. • “autostart-xwayland” — "
|
||||
"initializes Xwayland lazily if there are X11 clients. Requires restart."
|
||||
msgstr ""
|
||||
"若要啟用實驗性功能,請將功能關鍵字加入列表中。置於該功能是否須要重新啟動混成"
|
||||
"器則視給予的功能而定。任何實驗性功能不一定能用、或是可以調整設定。請不要預期"
|
||||
"在此設定中加入的任何東西未來都能存在。目前可用的關鍵字有: • “scale-monitor-"
|
||||
"framebuffer” — 讓 mutter 預設採用邏輯像素座標空間的配置邏輯螢幕,而縮放螢幕 "
|
||||
"framebuffer 則取代視窗內容以管理 HiDPI 螢幕。不須要重新啟動。"
|
||||
"在此設定中加入的任何東西未來都能存在。目前可用的關鍵字有:"
|
||||
"• 「scale-monitor-framebuffer」— 讓 mutter 預設採用邏輯像素座標空間的"
|
||||
"配置邏輯螢幕,而縮放螢幕 framebuffer 則取代視窗內容以管理 HiDPI 螢幕。不需要重新啟動。"
|
||||
"• 「rt-scheduler」— 讓 mutter 請求低優先級的即時排程。可執行檔或使用者必須要有"
|
||||
"CAP_SYS_NICE。需要重新啟動。"
|
||||
"• 「autostart-xwayland」— 如果有 X11 用戶端就延遲初始化 Xwayland。需要重新啟動。"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:141
|
||||
#: data/org.gnome.mutter.gschema.xml.in:134
|
||||
msgid "Modifier to use to locate the pointer"
|
||||
msgstr "要用來定位指標的輔助鍵"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:135
|
||||
msgid "This key will initiate the “locate pointer” action."
|
||||
msgstr "這個按鍵將會「定位指標」。"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:155
|
||||
msgid "Select window from tab popup"
|
||||
msgstr "從分頁彈出項選擇視窗"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:146
|
||||
#: data/org.gnome.mutter.gschema.xml.in:160
|
||||
msgid "Cancel tab popup"
|
||||
msgstr "取消分頁彈出項"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:151
|
||||
#: data/org.gnome.mutter.gschema.xml.in:165
|
||||
msgid "Switch monitor configurations"
|
||||
msgstr "切換螢幕組態"
|
||||
|
||||
#: data/org.gnome.mutter.gschema.xml.in:156
|
||||
#: data/org.gnome.mutter.gschema.xml.in:170
|
||||
msgid "Rotates the built-in monitor configuration"
|
||||
msgstr "旋轉切換內建螢幕組態"
|
||||
|
||||
@ -456,26 +480,38 @@ msgid "Re-enable shortcuts"
|
||||
msgstr "重新啟用快捷鍵"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:64
|
||||
msgid "Allow grabs with Xwayland"
|
||||
msgstr "在 Xwayland 允許抓取"
|
||||
#| msgid "Allow grabs with Xwayland"
|
||||
msgid "Allow X11 grabs to lock keyboard focus with Xwayland"
|
||||
msgstr "允許 X11 抓取以使用 Xwayland 鎖定鍵盤焦點"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:65
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
#| "taken into account. For a X11 grab to be taken into account under "
|
||||
#| "Wayland, the client must also either send a specific X11 ClientMessage to "
|
||||
#| "the root window or be among the applications white-listed in key "
|
||||
#| "“xwayland-grab-access-rules”."
|
||||
msgid ""
|
||||
"Allow keyboard grabs issued by X11 applications running in Xwayland to be "
|
||||
"taken into account. For a X11 grab to be taken into account under Wayland, "
|
||||
"the client must also either send a specific X11 ClientMessage to the root "
|
||||
"window or be among the applications white-listed in key “xwayland-grab-"
|
||||
"access-rules”."
|
||||
"Allow all keyboard events to be routed to X11 “override redirect” windows "
|
||||
"with a grab when running in Xwayland. This option is to support X11 clients "
|
||||
"which map an “override redirect” window (which do not receive keyboard "
|
||||
"focus) and issue a keyboard grab to force all keyboard events to that "
|
||||
"window. This option is seldom used and has no effect on regular X11 windows "
|
||||
"which can receive keyboard focus under normal circumstances. For a X11 grab "
|
||||
"to be taken into account under Wayland, the client must also either send a "
|
||||
"specific X11 ClientMessage to the root window or be among the applications "
|
||||
"white-listed in key “xwayland-grab-access-rules”."
|
||||
msgstr ""
|
||||
"考慮到在 Xwayland 中執行的 X11 應用程序發出的鍵盤抓取。對於在 Wayland 下考慮"
|
||||
"的 X11 抓取,客戶端也必須送出一個特定的 X11 ClientMessage 到 root 視窗或者在 "
|
||||
"xwayland-grab-access-rules 鍵白名單其中的應用程式。"
|
||||
"xwayland-grab-access-rules 鍵白名單其中的應用程式"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:77
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:84
|
||||
msgid "Xwayland applications allowed to issue keyboard grabs"
|
||||
msgstr "Xwayland 應用程式允許發出鍵盤抓取"
|
||||
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:78
|
||||
#: data/org.gnome.mutter.wayland.gschema.xml.in:85
|
||||
msgid ""
|
||||
"List the resource names or resource class of X11 windows either allowed or "
|
||||
"not allowed to issue X11 keyboard grabs under Xwayland. The resource name or "
|
||||
@ -499,7 +535,7 @@ msgstr ""
|
||||
#. TRANSLATORS: This string refers to a button that switches between
|
||||
#. * different modes.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2423
|
||||
#: src/backends/meta-input-settings.c:2532
|
||||
#, c-format
|
||||
msgid "Mode Switch (Group %d)"
|
||||
msgstr "模式切換( 群組 %d)"
|
||||
@ -507,121 +543,124 @@ msgstr "模式切換( 群組 %d)"
|
||||
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
|
||||
#. * mapping through the available outputs.
|
||||
#.
|
||||
#: src/backends/meta-input-settings.c:2446
|
||||
#: src/backends/meta-input-settings.c:2555
|
||||
msgid "Switch monitor"
|
||||
msgstr "切換螢幕"
|
||||
|
||||
#: src/backends/meta-input-settings.c:2448
|
||||
#: src/backends/meta-input-settings.c:2557
|
||||
msgid "Show on-screen help"
|
||||
msgstr "顯示螢幕求助"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:954
|
||||
#: src/backends/meta-monitor.c:223
|
||||
msgid "Built-in display"
|
||||
msgstr "內建顯示"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:986
|
||||
#: src/backends/meta-monitor.c:252
|
||||
msgid "Unknown"
|
||||
msgstr "不明"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:988
|
||||
#: src/backends/meta-monitor.c:254
|
||||
msgid "Unknown Display"
|
||||
msgstr "不明的顯示器"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:996
|
||||
#: src/backends/meta-monitor.c:262
|
||||
#, c-format
|
||||
#| msgid "%s %s"
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#: src/backends/meta-monitor-manager.c:1004
|
||||
#: src/backends/meta-monitor.c:270
|
||||
#, c-format
|
||||
#| msgid "%s %s"
|
||||
msgctxt ""
|
||||
"This is a monitor vendor name followed by product/model name where size in "
|
||||
"inches could not be calculated, e.g. Dell U2414H"
|
||||
msgid "%s %s"
|
||||
msgstr "%s %s"
|
||||
|
||||
#. Translators: this string will appear in Sysprof
|
||||
#: src/backends/meta-profiler.c:82
|
||||
msgid "Compositor"
|
||||
msgstr "合成器"
|
||||
|
||||
# FIXME: I'm still unclear about the meaning of XGetSelectionOwner -- Abel
|
||||
#. This probably means that a non-WM compositor like xcompmgr is running;
|
||||
#. * we have no way to get it to exit
|
||||
#: src/compositor/compositor.c:482
|
||||
#: src/compositor/compositor.c:509
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Another compositing manager is already running on screen %i on display “%s”."
|
||||
msgstr "在畫面「%2$s」中的第 %1$i 個螢幕中已啟動另一個組合視窗管理員。"
|
||||
|
||||
#: src/core/bell.c:252
|
||||
#: src/core/bell.c:192
|
||||
msgid "Bell event"
|
||||
msgstr "響鈴事件"
|
||||
|
||||
#: src/core/main.c:185
|
||||
#: src/core/main.c:190
|
||||
msgid "Disable connection to session manager"
|
||||
msgstr "停用到作業階段管理員的連線"
|
||||
|
||||
#: src/core/main.c:191
|
||||
#: src/core/main.c:196
|
||||
msgid "Replace the running window manager"
|
||||
msgstr "取代執行中的視窗管理員"
|
||||
|
||||
#: src/core/main.c:197
|
||||
#: src/core/main.c:202
|
||||
msgid "Specify session management ID"
|
||||
msgstr "指定作業階段管理 ID"
|
||||
|
||||
#: src/core/main.c:202
|
||||
#: src/core/main.c:207
|
||||
msgid "X Display to use"
|
||||
msgstr "使用的 X 畫面"
|
||||
|
||||
#: src/core/main.c:208
|
||||
#: src/core/main.c:213
|
||||
msgid "Initialize session from savefile"
|
||||
msgstr "以 savefile 初始化作業階段"
|
||||
|
||||
#: src/core/main.c:214
|
||||
#: src/core/main.c:219
|
||||
msgid "Make X calls synchronous"
|
||||
msgstr "使用同步方式調用 X 函式"
|
||||
|
||||
#: src/core/main.c:221
|
||||
#: src/core/main.c:226
|
||||
msgid "Run as a wayland compositor"
|
||||
msgstr "以 wayland 組合器執行"
|
||||
|
||||
#: src/core/main.c:227
|
||||
#: src/core/main.c:232
|
||||
msgid "Run as a nested compositor"
|
||||
msgstr "以巢狀組合器執行"
|
||||
|
||||
#: src/core/main.c:233
|
||||
#: src/core/main.c:238
|
||||
msgid "Run wayland compositor without starting Xwayland"
|
||||
msgstr "在不啟動 Xwayland 的情況下開啟 Wayland 合成器"
|
||||
|
||||
#: src/core/main.c:241
|
||||
#: src/core/main.c:246
|
||||
msgid "Run as a full display server, rather than nested"
|
||||
msgstr "以完全顯示伺服器執行,而非巢狀"
|
||||
|
||||
#: src/core/main.c:247
|
||||
#: src/core/main.c:252
|
||||
msgid "Run with X11 backend"
|
||||
msgstr "透過 X11 後端執行"
|
||||
|
||||
#. Translators: %s is a window title
|
||||
#: src/core/meta-close-dialog-default.c:150
|
||||
#: src/core/meta-close-dialog-default.c:151
|
||||
#, c-format
|
||||
msgid "“%s” is not responding."
|
||||
msgstr "「%s」沒有回應。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:152
|
||||
#: src/core/meta-close-dialog-default.c:153
|
||||
msgid "Application is not responding."
|
||||
msgstr "應用程式沒有回應。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:157
|
||||
#: src/core/meta-close-dialog-default.c:158
|
||||
msgid ""
|
||||
"You may choose to wait a short while for it to continue or force the "
|
||||
"application to quit entirely."
|
||||
msgstr "您可以選擇稍等一下讓它繼續,或者強制完全退出程式。"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:164
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Force Quit"
|
||||
msgstr "強制退出(_F)"
|
||||
|
||||
#: src/core/meta-close-dialog-default.c:164
|
||||
#: src/core/meta-close-dialog-default.c:165
|
||||
msgid "_Wait"
|
||||
msgstr "等待(_W)"
|
||||
|
||||
@ -648,21 +687,21 @@ msgid "Mutter plugin to use"
|
||||
msgstr "要使用的 Mutter 外掛程式"
|
||||
|
||||
# (Abel) take care of the same string in libwnck
|
||||
#: src/core/prefs.c:1786
|
||||
#: src/core/prefs.c:1849
|
||||
#, c-format
|
||||
msgid "Workspace %d"
|
||||
msgstr "工作區 %d"
|
||||
|
||||
#: src/core/util.c:121
|
||||
#: src/core/util.c:122
|
||||
msgid "Mutter was compiled without support for verbose mode\n"
|
||||
msgstr "編譯 Mutter 時並沒有加入詳細偵錯模式的支援\n"
|
||||
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:567
|
||||
#: src/wayland/meta-wayland-tablet-pad.c:568
|
||||
#, c-format
|
||||
msgid "Mode Switch: Mode %d"
|
||||
msgstr "模式切換:模式 %d"
|
||||
|
||||
#: src/x11/meta-x11-display.c:666
|
||||
#: src/x11/meta-x11-display.c:679
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Display “%s” already has a window manager; try using the --replace option to "
|
||||
@ -671,27 +710,32 @@ msgstr ""
|
||||
"畫面「%s」已經有了視窗管理員;請嘗試使用 --replace 選項來替換目前的視窗管理"
|
||||
"員。"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1008
|
||||
#: src/x11/meta-x11-display.c:1040
|
||||
msgid "Failed to initialize GDK\n"
|
||||
msgstr "無法初始化 GDK\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1032
|
||||
#: src/x11/meta-x11-display.c:1064
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display “%s”\n"
|
||||
msgstr "無法開啟 X Window 系統畫面「%s」\n"
|
||||
|
||||
#: src/x11/meta-x11-display.c:1115
|
||||
#: src/x11/meta-x11-display.c:1147
|
||||
#, c-format
|
||||
msgid "Screen %d on display “%s” is invalid\n"
|
||||
msgstr "畫面「%2$s」中的第 %1$d 個螢幕無效\n"
|
||||
|
||||
#: src/x11/meta-x11-selection-input-stream.c:445
|
||||
#, c-format
|
||||
msgid "Format %s not supported"
|
||||
msgstr "不支援 %s 格式"
|
||||
|
||||
#: src/x11/session.c:1821
|
||||
msgid ""
|
||||
"These windows do not support “save current setup” and will have to be "
|
||||
"restarted manually next time you log in."
|
||||
msgstr "這些視窗不支援「儲存目前的設定」,必須在下次登入後自行啟動。"
|
||||
|
||||
#: src/x11/window-props.c:568
|
||||
#: src/x11/window-props.c:569
|
||||
#, c-format
|
||||
msgid "%s (on %s)"
|
||||
msgstr "%s(在 %s)"
|
||||
|
@ -49,6 +49,14 @@
|
||||
#define DEFAULT_XKB_RULES_FILE "evdev"
|
||||
#define DEFAULT_XKB_MODEL "pc105+inet"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_SEQUENCE_NONE,
|
||||
META_SEQUENCE_ACCEPTED,
|
||||
META_SEQUENCE_REJECTED,
|
||||
META_SEQUENCE_PENDING_END
|
||||
} MetaSequenceState;
|
||||
|
||||
struct _MetaBackendClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
@ -71,6 +79,10 @@ struct _MetaBackendClass
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void (* finish_touch_sequence) (MetaBackend *backend,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
|
||||
void (* warp_pointer) (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
@ -135,6 +147,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend,
|
||||
int device_id,
|
||||
uint32_t timestamp);
|
||||
|
||||
void meta_backend_finish_touch_sequence (MetaBackend *backend,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state);
|
||||
|
||||
void meta_backend_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
int y);
|
||||
|
@ -1059,6 +1059,20 @@ meta_backend_ungrab_device (MetaBackend *backend,
|
||||
return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_finish_touch_sequence: (skip)
|
||||
*/
|
||||
void
|
||||
meta_backend_finish_touch_sequence (MetaBackend *backend,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence)
|
||||
META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend,
|
||||
sequence,
|
||||
state);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_backend_warp_pointer: (skip)
|
||||
*/
|
||||
|
@ -31,6 +31,7 @@ struct _MetaCursorTracker {
|
||||
GObject parent_instance;
|
||||
|
||||
gboolean is_showing;
|
||||
gboolean keep_focus_while_hidden;
|
||||
|
||||
MetaCursorSprite *effective_cursor; /* May be NULL when hidden */
|
||||
MetaCursorSprite *displayed_cursor;
|
||||
|
@ -136,6 +136,7 @@ static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
self->is_showing = TRUE;
|
||||
self->keep_focus_while_hidden = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -457,6 +458,44 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_get_keep_focus_while_hidden:
|
||||
* @tracker: a #MetaCursorTracker object.
|
||||
*
|
||||
* Returns: %FALSE if the Wayland focus surface of the pointer will
|
||||
* be forced to NULL while the pointer is hidden, %TRUE otherwise.
|
||||
* This function is only meant to be used by the magnifier of the shell
|
||||
* and will be removed in a future release.
|
||||
*/
|
||||
gboolean
|
||||
meta_cursor_tracker_get_keep_focus_while_hidden (MetaCursorTracker *tracker)
|
||||
{
|
||||
return tracker->keep_focus_while_hidden;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cursor_tracker_set_keep_focus_while_hidden:
|
||||
* @tracker: a #MetaCursorTracker object.
|
||||
* @keep_focus: whether to keep the cursor focus while hidden
|
||||
*
|
||||
* If this is set to %TRUE, the Wayland focus surface of the pointer will
|
||||
* not be forced to NULL while the pointer is hidden.
|
||||
* This function is only meant to be used by the magnifier of the shell
|
||||
* and will be removed in a future release.
|
||||
*/
|
||||
void
|
||||
meta_cursor_tracker_set_keep_focus_while_hidden (MetaCursorTracker *tracker,
|
||||
gboolean keep_focus)
|
||||
{
|
||||
if (keep_focus == tracker->keep_focus_while_hidden)
|
||||
return;
|
||||
tracker->keep_focus_while_hidden = keep_focus;
|
||||
|
||||
sync_cursor (tracker);
|
||||
|
||||
g_signal_emit (tracker, signals[VISIBILITY_CHANGED], 0);
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
meta_cursor_tracker_get_displayed_cursor (MetaCursorTracker *tracker)
|
||||
{
|
||||
|
@ -214,6 +214,8 @@ meta_dbus_session_watcher_finalize (GObject *object)
|
||||
MetaDbusSessionWatcher *session_watcher = META_DBUS_SESSION_WATCHER (object);
|
||||
|
||||
g_hash_table_destroy (session_watcher->clients);
|
||||
|
||||
G_OBJECT_CLASS (meta_dbus_session_watcher_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1648,6 +1648,7 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
|
||||
MetaMonitorModeSpec *monitor_mode_spec;
|
||||
g_autoptr (GVariant) properties_variant = NULL;
|
||||
gboolean enable_underscanning = FALSE;
|
||||
gboolean set_underscanning = FALSE;
|
||||
|
||||
g_variant_get (monitor_config_variant, "(ss@a{sv})",
|
||||
&connector,
|
||||
@ -1670,7 +1671,18 @@ create_monitor_config_from_variant (MetaMonitorManager *manager,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_variant_lookup (properties_variant, "underscanning", "b", &enable_underscanning);
|
||||
set_underscanning =
|
||||
g_variant_lookup (properties_variant, "underscanning", "b",
|
||||
&enable_underscanning);
|
||||
if (set_underscanning)
|
||||
{
|
||||
if (enable_underscanning && !meta_monitor_supports_underscanning (monitor))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Underscanning requested but unsupported");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
monitor_spec = meta_monitor_spec_clone (meta_monitor_get_spec (monitor));
|
||||
|
||||
|
@ -226,11 +226,15 @@ meta_screen_cast_window_stream_initable_init (GInitable *initable,
|
||||
G_CALLBACK (on_window_unmanaged),
|
||||
window_stream);
|
||||
|
||||
if (meta_is_stage_views_scaled ())
|
||||
scale = (int) ceilf (meta_logical_monitor_get_scale (logical_monitor));
|
||||
else
|
||||
scale = 1;
|
||||
|
||||
/* 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->logical_width = logical_monitor->rect.width;
|
||||
window_stream->logical_height = logical_monitor->rect.height;
|
||||
window_stream->stream_width = logical_monitor->rect.width * scale;
|
||||
|
@ -583,7 +583,6 @@ on_udev_device_added (MetaUdev *udev,
|
||||
{
|
||||
g_warning ("Failed to hotplug secondary gpu '%s': %s",
|
||||
device_path, error->message);
|
||||
g_error_free (error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright 2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -322,6 +323,7 @@ update_monitor_crtc_cursor (MetaMonitor *monitor,
|
||||
&crtc_x, &crtc_y);
|
||||
|
||||
transform = meta_logical_monitor_get_transform (data->in_logical_monitor);
|
||||
transform = meta_monitor_logical_to_crtc_transform (monitor, transform);
|
||||
if (meta_monitor_transform_is_rotated (transform))
|
||||
{
|
||||
crtc_width = monitor_crtc_mode->crtc_mode->height;
|
||||
@ -1175,6 +1177,42 @@ on_monitors_changed (MetaMonitorManager *monitors,
|
||||
force_update_hw_cursor (native);
|
||||
}
|
||||
|
||||
static void
|
||||
init_hw_cursor_support_for_gpu (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||
int kms_fd;
|
||||
struct gbm_device *gbm_device;
|
||||
uint64_t width, height;
|
||||
|
||||
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
||||
if (!gbm_device)
|
||||
return;
|
||||
|
||||
cursor_renderer_gpu_data =
|
||||
meta_create_cursor_renderer_native_gpu_data (gpu_kms);
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
if (drmGetCap (kms_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (kms_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = width;
|
||||
cursor_renderer_gpu_data->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = 64;
|
||||
cursor_renderer_gpu_data->cursor_height = 64;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_gpu_added_for_cursor (MetaBackend *backend,
|
||||
MetaGpuKms *gpu_kms)
|
||||
{
|
||||
init_hw_cursor_support_for_gpu (gpu_kms);
|
||||
}
|
||||
|
||||
static void
|
||||
init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
|
||||
{
|
||||
@ -1187,30 +1225,8 @@ init_hw_cursor_support (MetaCursorRendererNative *cursor_renderer_native)
|
||||
for (l = gpus; l; l = l->next)
|
||||
{
|
||||
MetaGpuKms *gpu_kms = l->data;
|
||||
MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data;
|
||||
int kms_fd;
|
||||
struct gbm_device *gbm_device;
|
||||
uint64_t width, height;
|
||||
|
||||
gbm_device = meta_gbm_device_from_gpu (gpu_kms);
|
||||
if (!gbm_device)
|
||||
continue;
|
||||
|
||||
cursor_renderer_gpu_data =
|
||||
meta_create_cursor_renderer_native_gpu_data (gpu_kms);
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
if (drmGetCap (kms_fd, DRM_CAP_CURSOR_WIDTH, &width) == 0 &&
|
||||
drmGetCap (kms_fd, DRM_CAP_CURSOR_HEIGHT, &height) == 0)
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = width;
|
||||
cursor_renderer_gpu_data->cursor_height = height;
|
||||
}
|
||||
else
|
||||
{
|
||||
cursor_renderer_gpu_data->cursor_width = 64;
|
||||
cursor_renderer_gpu_data->cursor_height = 64;
|
||||
}
|
||||
init_hw_cursor_support_for_gpu (gpu_kms);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1230,6 +1246,8 @@ meta_cursor_renderer_native_new (MetaBackend *backend)
|
||||
g_signal_connect_object (monitor_manager, "monitors-changed-internal",
|
||||
G_CALLBACK (on_monitors_changed),
|
||||
cursor_renderer_native, 0);
|
||||
g_signal_connect (backend, "gpu-added",
|
||||
G_CALLBACK (on_gpu_added_for_cursor), NULL);
|
||||
|
||||
priv->backend = backend;
|
||||
priv->hw_state_invalidated = TRUE;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Red Hat
|
||||
* Copyright (C) 2019 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -149,12 +150,28 @@ dispatch_in_impl (MetaKmsImpl *impl,
|
||||
return meta_kms_impl_device_dispatch (impl_device, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
dispatch_idle_in_impl (MetaKmsImpl *impl,
|
||||
gpointer user_data,
|
||||
GError **error)
|
||||
{
|
||||
meta_kms_impl_dispatch_idle (impl);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
meta_kms_device_dispatch_sync (MetaKmsDevice *device,
|
||||
GError **error)
|
||||
{
|
||||
int callback_count;
|
||||
|
||||
if (!meta_kms_run_impl_task_sync (device->kms,
|
||||
dispatch_idle_in_impl,
|
||||
device->impl_device,
|
||||
error))
|
||||
return -1;
|
||||
|
||||
callback_count = meta_kms_flush_callbacks (device->kms);
|
||||
if (callback_count > 0)
|
||||
return TRUE;
|
||||
|
@ -326,6 +326,16 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
|
||||
meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl_device->impl));
|
||||
|
||||
drm_resources = drmModeGetResources (impl_device->fd);
|
||||
if (!drm_resources)
|
||||
{
|
||||
g_list_free_full (impl_device->planes, g_object_unref);
|
||||
g_list_free_full (impl_device->crtcs, g_object_unref);
|
||||
g_list_free_full (impl_device->connectors, g_object_unref);
|
||||
impl_device->planes = NULL;
|
||||
impl_device->crtcs = NULL;
|
||||
impl_device->connectors = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
update_connectors (impl_device, drm_resources);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Red Hat
|
||||
* Copyright (C) 2019-2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -246,7 +247,8 @@ process_mode_set (MetaKmsImpl *impl,
|
||||
if (ret != 0)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
|
||||
"Failed to set mode on CRTC %u: %s",
|
||||
"Failed to set mode %s on CRTC %u: %s",
|
||||
mode_set->drm_mode ? mode_set->drm_mode->name : "off",
|
||||
meta_kms_crtc_get_id (crtc),
|
||||
g_strerror (-ret));
|
||||
return FALSE;
|
||||
@ -322,6 +324,13 @@ retry_page_flip_data_free (RetryPageFlipData *retry_page_flip_data)
|
||||
g_free (retry_page_flip_data);
|
||||
}
|
||||
|
||||
static CachedModeSet *
|
||||
get_cached_mode_set (MetaKmsImplSimple *impl_simple,
|
||||
MetaKmsCrtc *crtc)
|
||||
{
|
||||
return g_hash_table_lookup (impl_simple->cached_mode_sets, crtc);
|
||||
}
|
||||
|
||||
static float
|
||||
get_cached_crtc_refresh_rate (MetaKmsImplSimple *impl_simple,
|
||||
MetaKmsCrtc *crtc)
|
||||
@ -518,7 +527,7 @@ mode_set_fallback_feedback_idle (gpointer user_data)
|
||||
g_clear_pointer (&impl_simple->mode_set_fallback_feedback_source,
|
||||
g_source_unref);
|
||||
|
||||
if (!impl_simple->pending_page_flip_retries)
|
||||
if (impl_simple->pending_page_flip_retries)
|
||||
{
|
||||
impl_simple->postponed_mode_set_fallback_datas =
|
||||
g_steal_pointer (&impl_simple->mode_set_fallback_page_flip_datas);
|
||||
@ -641,16 +650,35 @@ process_page_flip (MetaKmsImpl *impl,
|
||||
meta_kms_page_flip_data_ref (page_flip_data));
|
||||
}
|
||||
|
||||
if (ret != 0)
|
||||
meta_kms_page_flip_data_unref (page_flip_data);
|
||||
|
||||
if (ret == -EBUSY)
|
||||
{
|
||||
float refresh_rate;
|
||||
CachedModeSet *cached_mode_set;
|
||||
|
||||
refresh_rate = get_cached_crtc_refresh_rate (impl_simple, crtc);
|
||||
schedule_retry_page_flip (impl_simple,
|
||||
crtc,
|
||||
plane_assignment->fb_id,
|
||||
refresh_rate,
|
||||
page_flip_data);
|
||||
cached_mode_set = get_cached_mode_set (impl_simple, crtc);
|
||||
if (cached_mode_set)
|
||||
{
|
||||
drmModeModeInfo *drm_mode;
|
||||
float refresh_rate;
|
||||
|
||||
drm_mode = cached_mode_set->drm_mode;
|
||||
refresh_rate = meta_calculate_drm_mode_refresh_rate (drm_mode);
|
||||
schedule_retry_page_flip (impl_simple,
|
||||
crtc,
|
||||
plane_assignment->fb_id,
|
||||
refresh_rate,
|
||||
page_flip_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Page flip of %u failed, and no mode set available",
|
||||
meta_kms_crtc_get_id (crtc));
|
||||
meta_kms_page_flip_data_unref (page_flip_data);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (ret == -EINVAL)
|
||||
{
|
||||
@ -772,12 +800,14 @@ meta_kms_impl_simple_handle_page_flip_callback (MetaKmsImpl *impl,
|
||||
{
|
||||
impl_simple->postponed_page_flip_datas =
|
||||
g_list_append (impl_simple->postponed_page_flip_datas,
|
||||
page_flip_data);
|
||||
meta_kms_page_flip_data_ref (page_flip_data));
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_kms_page_flip_data_flipped_in_impl (page_flip_data);
|
||||
}
|
||||
|
||||
meta_kms_page_flip_data_unref (page_flip_data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -804,6 +834,15 @@ meta_kms_impl_simple_discard_pending_page_flips (MetaKmsImpl *impl)
|
||||
g_source_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_impl_simple_dispatch_idle (MetaKmsImpl *impl)
|
||||
{
|
||||
MetaKmsImplSimple *impl_simple = META_KMS_IMPL_SIMPLE (impl);
|
||||
|
||||
if (impl_simple->mode_set_fallback_feedback_source)
|
||||
mode_set_fallback_feedback_idle (impl_simple);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_impl_simple_finalize (GObject *object)
|
||||
{
|
||||
@ -843,4 +882,5 @@ meta_kms_impl_simple_class_init (MetaKmsImplSimpleClass *klass)
|
||||
impl_class->process_update = meta_kms_impl_simple_process_update;
|
||||
impl_class->handle_page_flip_callback = meta_kms_impl_simple_handle_page_flip_callback;
|
||||
impl_class->discard_pending_page_flips = meta_kms_impl_simple_discard_pending_page_flips;
|
||||
impl_class->dispatch_idle = meta_kms_impl_simple_dispatch_idle;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Red Hat
|
||||
* Copyright (C) 2019 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -65,6 +66,12 @@ meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl)
|
||||
META_KMS_IMPL_GET_CLASS (impl)->discard_pending_page_flips (impl);
|
||||
}
|
||||
|
||||
void
|
||||
meta_kms_impl_dispatch_idle (MetaKmsImpl *impl)
|
||||
{
|
||||
META_KMS_IMPL_GET_CLASS (impl)->dispatch_idle (impl);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_impl_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Red Hat
|
||||
* Copyright (C) 2019 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -38,6 +39,7 @@ struct _MetaKmsImplClass
|
||||
void (* handle_page_flip_callback) (MetaKmsImpl *impl,
|
||||
MetaKmsPageFlipData *page_flip_data);
|
||||
void (* discard_pending_page_flips) (MetaKmsImpl *impl);
|
||||
void (* dispatch_idle) (MetaKmsImpl *impl);
|
||||
};
|
||||
|
||||
MetaKms * meta_kms_impl_get_kms (MetaKmsImpl *impl);
|
||||
@ -51,4 +53,6 @@ void meta_kms_impl_handle_page_flip_callback (MetaKmsImpl *impl,
|
||||
|
||||
void meta_kms_impl_discard_pending_page_flips (MetaKmsImpl *impl);
|
||||
|
||||
void meta_kms_impl_dispatch_idle (MetaKmsImpl *impl);
|
||||
|
||||
#endif /* META_KMS_IMPL_H */
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Red Hat
|
||||
* Copyright 2020 DisplayLink (UK) Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -385,6 +386,7 @@ meta_kms_add_source_in_impl (MetaKms *kms,
|
||||
simple_impl_source->kms = kms;
|
||||
|
||||
g_source_set_callback (source, func, user_data, user_data_destroy);
|
||||
g_source_set_ready_time (source, 0);
|
||||
g_source_attach (source, g_main_context_get_thread_default ());
|
||||
|
||||
return source;
|
||||
|
@ -295,7 +295,6 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
|
||||
MetaOutput *output;
|
||||
MetaOutputKms *output_kms;
|
||||
const MetaKmsConnectorState *connector_state;
|
||||
MetaMonitorTransform panel_orientation_transform;
|
||||
uint32_t connector_id;
|
||||
GArray *crtcs;
|
||||
GList *l;
|
||||
@ -318,8 +317,9 @@ meta_create_kms_output (MetaGpuKms *gpu_kms,
|
||||
|
||||
connector_state = meta_kms_connector_get_current_state (kms_connector);
|
||||
|
||||
panel_orientation_transform = connector_state->panel_orientation_transform;
|
||||
if (meta_monitor_transform_is_rotated (panel_orientation_transform))
|
||||
output->panel_orientation_transform =
|
||||
connector_state->panel_orientation_transform;
|
||||
if (meta_monitor_transform_is_rotated (output->panel_orientation_transform))
|
||||
{
|
||||
output->width_mm = connector_state->height_mm;
|
||||
output->height_mm = connector_state->width_mm;
|
||||
|
@ -82,6 +82,9 @@ paint_egl_image (MetaGles3 *gles3,
|
||||
0, 0, width, height,
|
||||
GL_COLOR_BUFFER_BIT,
|
||||
GL_NEAREST));
|
||||
|
||||
GLBAS (gles3, glDeleteTextures, (1, &texture));
|
||||
GLBAS (gles3, glDeleteFramebuffers, (1, &framebuffer));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -3053,7 +3053,6 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native,
|
||||
static CoglOffscreen *
|
||||
meta_renderer_native_create_offscreen (MetaRendererNative *renderer,
|
||||
CoglContext *context,
|
||||
MetaMonitorTransform transform,
|
||||
gint view_width,
|
||||
gint view_height,
|
||||
GError **error)
|
||||
@ -3256,6 +3255,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
MetaMonitorTransform view_transform;
|
||||
CoglOnscreen *onscreen = NULL;
|
||||
CoglOffscreen *offscreen = NULL;
|
||||
CoglOffscreen *shadowfb = NULL;
|
||||
float scale;
|
||||
int width, height;
|
||||
MetaRendererView *view;
|
||||
@ -3282,18 +3282,35 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
if (!onscreen)
|
||||
g_error ("Failed to allocate onscreen framebuffer: %s", error->message);
|
||||
|
||||
if (view_transform != META_MONITOR_TRANSFORM_NORMAL ||
|
||||
should_force_shadow_fb (renderer_native,
|
||||
renderer_native->primary_gpu_kms))
|
||||
if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
|
||||
{
|
||||
offscreen = meta_renderer_native_create_offscreen (renderer_native,
|
||||
cogl_context,
|
||||
view_transform,
|
||||
width,
|
||||
height,
|
||||
&error);
|
||||
if (!offscreen)
|
||||
g_error ("Failed to allocate back buffer texture: %s", error->message);
|
||||
|
||||
}
|
||||
|
||||
if (should_force_shadow_fb (renderer_native,
|
||||
renderer_native->primary_gpu_kms))
|
||||
{
|
||||
int shadow_width;
|
||||
int shadow_height;
|
||||
|
||||
/* The shadowfb must be the same size as the on-screen framebuffer */
|
||||
shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen));
|
||||
shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen));
|
||||
|
||||
shadowfb = meta_renderer_native_create_offscreen (renderer_native,
|
||||
cogl_context,
|
||||
shadow_width,
|
||||
shadow_height,
|
||||
&error);
|
||||
if (!shadowfb)
|
||||
g_error ("Failed to allocate shadow buffer texture: %s", error->message);
|
||||
}
|
||||
|
||||
view = g_object_new (META_TYPE_RENDERER_VIEW,
|
||||
@ -3301,10 +3318,12 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
|
||||
"scale", scale,
|
||||
"framebuffer", onscreen,
|
||||
"offscreen", offscreen,
|
||||
"shadowfb", shadowfb,
|
||||
"logical-monitor", logical_monitor,
|
||||
"transform", view_transform,
|
||||
NULL);
|
||||
g_clear_pointer (&offscreen, cogl_object_unref);
|
||||
g_clear_pointer (&shadowfb, cogl_object_unref);
|
||||
|
||||
meta_onscreen_native_set_view (onscreen, view);
|
||||
|
||||
|
@ -67,6 +67,10 @@ struct _MetaBackendX11Private
|
||||
XSyncAlarm user_active_alarm;
|
||||
XSyncCounter counter;
|
||||
|
||||
int current_touch_replay_sync_serial;
|
||||
int pending_touch_replay_sync_serial;
|
||||
Atom touch_replay_sync_atom;
|
||||
|
||||
int xinput_opcode;
|
||||
int xinput_event_base;
|
||||
int xinput_error_base;
|
||||
@ -175,6 +179,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11,
|
||||
backend_x11_class->translate_device_event (x11, device_event);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
{
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
|
||||
if (!device_event->send_event &&
|
||||
device_event->time != META_CURRENT_TIME &&
|
||||
priv->current_touch_replay_sync_serial !=
|
||||
priv->pending_touch_replay_sync_serial &&
|
||||
XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
|
||||
{
|
||||
/* Emulated pointer events received after XIRejectTouch is received
|
||||
* on a passive touch grab will contain older timestamps, update those
|
||||
* so we dont get InvalidTime at grabs.
|
||||
*/
|
||||
device_event->time = priv->latest_evtime;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
translate_device_event (MetaBackendX11 *x11,
|
||||
XIDeviceEvent *device_event)
|
||||
@ -184,19 +208,7 @@ translate_device_event (MetaBackendX11 *x11,
|
||||
meta_backend_x11_translate_device_event (x11, device_event);
|
||||
|
||||
if (!device_event->send_event && device_event->time != META_CURRENT_TIME)
|
||||
{
|
||||
if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime))
|
||||
{
|
||||
/* Emulated pointer events received after XIRejectTouch is received
|
||||
* on a passive touch grab will contain older timestamps, update those
|
||||
* so we dont get InvalidTime at grabs.
|
||||
*/
|
||||
device_event->time = priv->latest_evtime;
|
||||
}
|
||||
|
||||
/* Update the internal latest evtime, for any possible later use */
|
||||
priv->latest_evtime = device_event->time;
|
||||
}
|
||||
priv->latest_evtime = device_event->time;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -261,6 +273,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11,
|
||||
case XI_Motion:
|
||||
case XI_ButtonPress:
|
||||
case XI_ButtonRelease:
|
||||
maybe_translate_touch_replay_pointer_event (x11,
|
||||
(XIDeviceEvent *) input_event);
|
||||
/* Intentional fall-through */
|
||||
case XI_KeyPress:
|
||||
case XI_KeyRelease:
|
||||
case XI_TouchBegin:
|
||||
@ -329,6 +344,17 @@ handle_host_xevent (MetaBackend *backend,
|
||||
gboolean bypass_clutter = FALSE;
|
||||
MetaDisplay *display;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case ClientMessage:
|
||||
if (event->xclient.window == meta_backend_x11_get_xwindow (x11) &&
|
||||
event->xclient.message_type == priv->touch_replay_sync_atom)
|
||||
priv->current_touch_replay_sync_serial = event->xclient.data.l[0];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
XGetEventData (priv->xdisplay, &event->xcookie);
|
||||
|
||||
display = meta_get_display ();
|
||||
@ -533,6 +559,10 @@ meta_backend_x11_post_init (MetaBackend *backend)
|
||||
monitor_manager = meta_backend_get_monitor_manager (backend);
|
||||
g_signal_connect (monitor_manager, "monitors-changed-internal",
|
||||
G_CALLBACK (on_monitors_changed), backend);
|
||||
|
||||
priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay,
|
||||
"_MUTTER_TOUCH_SEQUENCE_SYNC",
|
||||
False);
|
||||
}
|
||||
|
||||
static ClutterBackend *
|
||||
@ -590,6 +620,43 @@ meta_backend_x11_ungrab_device (MetaBackend *backend,
|
||||
return (ret == Success);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_finish_touch_sequence (MetaBackend *backend,
|
||||
ClutterEventSequence *sequence,
|
||||
MetaSequenceState state)
|
||||
{
|
||||
MetaBackendX11 *x11 = META_BACKEND_X11 (backend);
|
||||
MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11);
|
||||
int event_mode;
|
||||
|
||||
if (state == META_SEQUENCE_ACCEPTED)
|
||||
event_mode = XIAcceptTouch;
|
||||
else if (state == META_SEQUENCE_REJECTED)
|
||||
event_mode = XIRejectTouch;
|
||||
else
|
||||
g_return_if_reached ();
|
||||
|
||||
XIAllowTouchEvents (priv->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
meta_x11_event_sequence_get_touch_detail (sequence),
|
||||
DefaultRootWindow (priv->xdisplay), event_mode);
|
||||
|
||||
if (state == META_SEQUENCE_REJECTED)
|
||||
{
|
||||
XClientMessageEvent ev;
|
||||
|
||||
ev = (XClientMessageEvent) {
|
||||
.type = ClientMessage,
|
||||
.window = meta_backend_x11_get_xwindow (x11),
|
||||
.message_type = priv->touch_replay_sync_atom,
|
||||
.format = 32,
|
||||
.data.l[0] = ++priv->pending_touch_replay_sync_serial,
|
||||
};
|
||||
XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11),
|
||||
False, 0, (XEvent *) &ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_backend_x11_warp_pointer (MetaBackend *backend,
|
||||
int x,
|
||||
@ -781,6 +848,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
backend_class->post_init = meta_backend_x11_post_init;
|
||||
backend_class->grab_device = meta_backend_x11_grab_device;
|
||||
backend_class->ungrab_device = meta_backend_x11_ungrab_device;
|
||||
backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence;
|
||||
backend_class->warp_pointer = meta_backend_x11_warp_pointer;
|
||||
backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor;
|
||||
backend_class->get_keymap = meta_backend_x11_get_keymap;
|
||||
@ -791,6 +859,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass)
|
||||
static void
|
||||
meta_backend_x11_init (MetaBackendX11 *x11)
|
||||
{
|
||||
XInitThreads ();
|
||||
}
|
||||
|
||||
Display *
|
||||
|
@ -1291,6 +1291,22 @@ handle_raw_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterInputDevice *
|
||||
get_source_device_checked (MetaDeviceManagerX11 *manager_xi2,
|
||||
XIDeviceEvent *xev)
|
||||
{
|
||||
ClutterInputDevice *source_device;
|
||||
|
||||
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->sourceid));
|
||||
|
||||
if (!source_device)
|
||||
g_warning ("Impossible to get the source device with id %d for event of "
|
||||
"type %d", xev->sourceid, xev->evtype);
|
||||
|
||||
return source_device;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
XEvent *xevent,
|
||||
@ -1379,6 +1395,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
char buffer[7] = { 0, };
|
||||
gunichar n;
|
||||
|
||||
source_device = get_source_device_checked (manager_xi2, xev);
|
||||
if (!source_device)
|
||||
return FALSE;
|
||||
|
||||
event->key.type = event->type = (xev->evtype == XI_KeyPress)
|
||||
? CLUTTER_KEY_PRESS
|
||||
: CLUTTER_KEY_RELEASE;
|
||||
@ -1413,8 +1433,6 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
event_x11->caps_lock_set =
|
||||
clutter_keymap_get_caps_lock_state (CLUTTER_KEYMAP (keymap_x11));
|
||||
|
||||
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->sourceid));
|
||||
clutter_event_set_source_device (event, source_device);
|
||||
|
||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
@ -1458,8 +1476,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
{
|
||||
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
|
||||
|
||||
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->sourceid));
|
||||
source_device = get_source_device_checked (manager_xi2, xev);
|
||||
if (!source_device)
|
||||
return FALSE;
|
||||
|
||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
|
||||
@ -1626,7 +1646,7 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
break;
|
||||
}
|
||||
|
||||
if (source_device != NULL && device->stage != NULL)
|
||||
if (device->stage != NULL)
|
||||
_clutter_input_device_set_stage (source_device, device->stage);
|
||||
|
||||
if (xev->flags & XIPointerEmulated)
|
||||
@ -1644,8 +1664,10 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
XIDeviceEvent *xev = (XIDeviceEvent *) xi_event;
|
||||
double delta_x, delta_y;
|
||||
|
||||
source_device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->sourceid));
|
||||
source_device = get_source_device_checked (manager_xi2, xev);
|
||||
if (!source_device)
|
||||
return FALSE;
|
||||
|
||||
device = g_hash_table_lookup (manager_xi2->devices_by_id,
|
||||
GINT_TO_POINTER (xev->deviceid));
|
||||
|
||||
@ -1716,7 +1738,7 @@ meta_device_manager_x11_translate_event (MetaDeviceManagerX11 *manager_xi2,
|
||||
event->motion.y,
|
||||
&xev->valuators);
|
||||
|
||||
if (source_device != NULL && device->stage != NULL)
|
||||
if (device->stage != NULL)
|
||||
_clutter_input_device_set_stage (source_device, device->stage);
|
||||
|
||||
if (xev->flags & XIPointerEmulated)
|
||||
|
@ -118,9 +118,12 @@ get_property (ClutterInputDevice *device,
|
||||
|
||||
device_id = clutter_input_device_get_device_id (device);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
rc = XIGetProperty (xdisplay, device_id, property_atom,
|
||||
0, 10, False, type, &type_ret, &format_ret,
|
||||
&nitems_ret, &bytes_after_ret, &data_ret);
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
if (rc == Success && type_ret == type && format_ret == format && nitems_ret >= nitems)
|
||||
{
|
||||
if (nitems_ret > nitems)
|
||||
|
@ -896,12 +896,16 @@ meta_stage_x11_translate_event (MetaStageX11 *stage_x11,
|
||||
g_debug ("Client message for stage, win:0x%x",
|
||||
(unsigned int) xevent->xany.window);
|
||||
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
if (handle_wm_protocols_event (backend_x11, stage_x11, xevent))
|
||||
{
|
||||
event->any.type = CLUTTER_DELETE;
|
||||
event->any.stage = stage;
|
||||
res = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -63,7 +63,6 @@
|
||||
#include "clutter/clutter-mutter.h"
|
||||
#include "cogl/cogl-trace.h"
|
||||
#include "compositor/meta-window-actor-x11.h"
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "compositor/meta-window-actor-private.h"
|
||||
#include "compositor/meta-window-group-private.h"
|
||||
#include "core/core.h"
|
||||
@ -83,6 +82,7 @@
|
||||
#include "x11/meta-x11-display-private.h"
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "wayland/meta-wayland-private.h"
|
||||
#endif
|
||||
|
||||
@ -607,6 +607,7 @@ meta_compositor_add_window (MetaCompositor *compositor,
|
||||
|
||||
window_actor = g_object_new (window_actor_type,
|
||||
"meta-window", window,
|
||||
"show-on-set-parent", FALSE,
|
||||
NULL);
|
||||
|
||||
if (window->layer == META_LAYER_OVERRIDE_REDIRECT)
|
||||
|
@ -573,6 +573,8 @@ meta_background_actor_paint (ClutterActor *actor)
|
||||
paint_clipped_rectangle (fb, self->pipeline, &rect,
|
||||
&self->texture_area);
|
||||
}
|
||||
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -195,6 +195,8 @@ meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
|
||||
if (klass->destroy)
|
||||
{
|
||||
retval = TRUE;
|
||||
meta_plugin_manager_kill_window_effects (plugin_mgr,
|
||||
actor);
|
||||
klass->destroy (plugin, actor);
|
||||
}
|
||||
break;
|
||||
|
@ -243,6 +243,8 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
meta_shaped_texture_set_mask_texture (stex, NULL);
|
||||
meta_shaped_texture_reset_pipelines (stex);
|
||||
|
||||
g_clear_pointer (&stex->opaque_region, cairo_region_destroy);
|
||||
|
||||
g_clear_pointer (&stex->snippet, cogl_object_unref);
|
||||
|
||||
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
|
||||
@ -458,16 +460,11 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
{
|
||||
int width, height;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
if (stex->texture)
|
||||
cogl_object_unref (stex->texture);
|
||||
|
||||
stex->texture = cogl_tex;
|
||||
cogl_clear_object (&stex->texture);
|
||||
|
||||
if (cogl_tex != NULL)
|
||||
{
|
||||
cogl_object_ref (cogl_tex);
|
||||
stex->texture = cogl_object_ref (cogl_tex);
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
|
||||
}
|
||||
@ -492,8 +489,6 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
|
||||
if (stex->create_mipmaps)
|
||||
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
|
||||
|
||||
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -939,6 +934,9 @@ meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||
{
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
if (stex->texture == texture)
|
||||
return;
|
||||
|
||||
set_cogl_texture (stex, texture);
|
||||
}
|
||||
|
||||
|
@ -2183,21 +2183,25 @@ meta_window_actor_get_image (MetaWindowActor *self,
|
||||
if (clutter_actor_get_n_children (actor) == 1)
|
||||
{
|
||||
MetaShapedTexture *stex;
|
||||
MetaRectangle surface_clip;
|
||||
int geometry_scale;
|
||||
MetaRectangle *surface_clip = NULL;
|
||||
|
||||
geometry_scale =
|
||||
meta_window_actor_get_geometry_scale (self);
|
||||
if (clip)
|
||||
{
|
||||
|
||||
surface_clip = (MetaRectangle) {
|
||||
.x = clip->x / geometry_scale,
|
||||
.y = clip->y / geometry_scale,
|
||||
.width = clip->width / geometry_scale,
|
||||
.height = clip->height / geometry_scale,
|
||||
};
|
||||
int geometry_scale;
|
||||
|
||||
geometry_scale =
|
||||
meta_window_actor_get_geometry_scale (self);
|
||||
|
||||
surface_clip = g_alloca (sizeof (MetaRectangle));
|
||||
surface_clip->x = clip->x / geometry_scale,
|
||||
surface_clip->y = clip->y / geometry_scale;
|
||||
surface_clip->width = clip->width / geometry_scale;
|
||||
surface_clip->height = clip->height / geometry_scale;
|
||||
}
|
||||
|
||||
stex = meta_surface_actor_get_texture (priv->surface);
|
||||
return meta_shaped_texture_get_image (stex, &surface_clip);
|
||||
return meta_shaped_texture_get_image (stex, surface_clip);
|
||||
}
|
||||
|
||||
clutter_actor_get_size (actor, &width, &height);
|
||||
|
@ -590,6 +590,7 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
MetaWindowType type;
|
||||
MetaRectangle icon_geometry;
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
ClutterTimeline *timeline = NULL;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
|
||||
|
||||
@ -602,24 +603,28 @@ minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
}
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
timeline = actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MINIMIZE_TIMEOUT,
|
||||
"scale-x", 0.0,
|
||||
"scale-y", 0.0,
|
||||
"x", (double)icon_geometry.x,
|
||||
"y", (double)icon_geometry.y,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (timeline)
|
||||
{
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_minimize = actor_animate (actor,
|
||||
CLUTTER_EASE_IN_SINE,
|
||||
MINIMIZE_TIMEOUT,
|
||||
"scale-x", 0.0,
|
||||
"scale-y", 0.0,
|
||||
"x", (double)icon_geometry.x,
|
||||
"y", (double)icon_geometry.y,
|
||||
NULL);
|
||||
apriv->tml_minimize = timeline;
|
||||
data->plugin = plugin;
|
||||
data->actor = actor;
|
||||
g_signal_connect (apriv->tml_minimize, "completed",
|
||||
G_CALLBACK (on_minimize_effect_complete),
|
||||
data);
|
||||
|
||||
}
|
||||
else
|
||||
meta_plugin_minimize_completed (plugin, window_actor);
|
||||
@ -708,21 +713,27 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
MetaWindowType type;
|
||||
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
|
||||
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
|
||||
ClutterTimeline *timeline = NULL;
|
||||
|
||||
type = meta_window_get_window_type (meta_window);
|
||||
|
||||
if (type == META_WINDOW_NORMAL)
|
||||
{
|
||||
timeline = actor_animate (actor,
|
||||
CLUTTER_EASE_OUT_QUAD,
|
||||
DESTROY_TIMEOUT,
|
||||
"opacity", 0,
|
||||
"scale-x", 0.8,
|
||||
"scale-y", 0.8,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (timeline)
|
||||
{
|
||||
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
|
||||
ActorPrivate *apriv = get_actor_private (window_actor);
|
||||
|
||||
apriv->tml_destroy = actor_animate (actor,
|
||||
CLUTTER_EASE_OUT_QUAD,
|
||||
DESTROY_TIMEOUT,
|
||||
"opacity", 0,
|
||||
"scale-x", 0.8,
|
||||
"scale-y", 0.8,
|
||||
NULL);
|
||||
apriv->tml_destroy = timeline;
|
||||
data->plugin = plugin;
|
||||
data->actor = actor;
|
||||
g_signal_connect (apriv->tml_destroy, "completed",
|
||||
@ -737,9 +748,8 @@ destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
|
||||
* Tile preview private data accessor
|
||||
*/
|
||||
static void
|
||||
free_display_tile_preview (gpointer data)
|
||||
free_display_tile_preview (DisplayTilePreview *preview)
|
||||
{
|
||||
DisplayTilePreview *preview = data;
|
||||
|
||||
if (G_LIKELY (preview != NULL)) {
|
||||
clutter_actor_destroy (preview->actor);
|
||||
@ -747,15 +757,27 @@ free_display_tile_preview (gpointer data)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_closing (MetaDisplay *display,
|
||||
DisplayTilePreview *preview)
|
||||
{
|
||||
free_display_tile_preview (preview);
|
||||
}
|
||||
|
||||
static DisplayTilePreview *
|
||||
get_display_tile_preview (MetaDisplay *display)
|
||||
{
|
||||
DisplayTilePreview *preview = g_object_get_qdata (G_OBJECT (display), display_tile_preview_data_quark);
|
||||
DisplayTilePreview *preview;
|
||||
|
||||
if (G_UNLIKELY (display_tile_preview_data_quark == 0))
|
||||
display_tile_preview_data_quark = g_quark_from_static_string (DISPLAY_TILE_PREVIEW_DATA_KEY);
|
||||
if (!display_tile_preview_data_quark)
|
||||
{
|
||||
display_tile_preview_data_quark =
|
||||
g_quark_from_static_string (DISPLAY_TILE_PREVIEW_DATA_KEY);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!preview))
|
||||
preview = g_object_get_qdata (G_OBJECT (display),
|
||||
display_tile_preview_data_quark);
|
||||
if (!preview)
|
||||
{
|
||||
preview = g_slice_new0 (DisplayTilePreview);
|
||||
|
||||
@ -764,9 +786,13 @@ get_display_tile_preview (MetaDisplay *display)
|
||||
clutter_actor_set_opacity (preview->actor, 100);
|
||||
|
||||
clutter_actor_add_child (meta_get_window_group_for_display (display), preview->actor);
|
||||
g_object_set_qdata_full (G_OBJECT (display),
|
||||
display_tile_preview_data_quark, preview,
|
||||
free_display_tile_preview);
|
||||
g_signal_connect (display,
|
||||
"closing",
|
||||
G_CALLBACK (on_display_closing),
|
||||
preview);
|
||||
g_object_set_qdata (G_OBJECT (display),
|
||||
display_tile_preview_data_quark,
|
||||
preview);
|
||||
}
|
||||
|
||||
return preview;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <X11/extensions/Xdamage.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "backends/meta-cursor-sprite-xcursor.h"
|
||||
#include "backends/meta-cursor-tracker-private.h"
|
||||
#include "backends/meta-idle-monitor-dbus.h"
|
||||
@ -155,6 +156,7 @@ enum
|
||||
SHOWING_DESKTOP_CHANGED,
|
||||
RESTACKED,
|
||||
WORKAREAS_CHANGED,
|
||||
CLOSING,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
@ -492,6 +494,12 @@ meta_display_class_init (MetaDisplayClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
display_signals[CLOSING] =
|
||||
g_signal_new ("closing",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_FOCUS_WINDOW,
|
||||
@ -622,27 +630,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker,
|
||||
MetaSequenceState state,
|
||||
MetaDisplay *display)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
switch (state)
|
||||
{
|
||||
if (state == META_SEQUENCE_ACCEPTED)
|
||||
meta_display_cancel_touch (display);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ());
|
||||
int event_mode;
|
||||
case META_SEQUENCE_NONE:
|
||||
case META_SEQUENCE_PENDING_END:
|
||||
return;
|
||||
case META_SEQUENCE_ACCEPTED:
|
||||
meta_display_cancel_touch (display);
|
||||
|
||||
if (state == META_SEQUENCE_ACCEPTED)
|
||||
event_mode = XIAcceptTouch;
|
||||
else if (state == META_SEQUENCE_REJECTED)
|
||||
event_mode = XIRejectTouch;
|
||||
else
|
||||
return;
|
||||
/* Intentional fall-through */
|
||||
case META_SEQUENCE_REJECTED:
|
||||
{
|
||||
MetaBackend *backend;
|
||||
|
||||
XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend),
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
meta_x11_event_sequence_get_touch_detail (sequence),
|
||||
DefaultRootWindow (display->x11_display->xdisplay), event_mode);
|
||||
backend = meta_get_backend ();
|
||||
meta_backend_finish_touch_sequence (backend, sequence, state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -974,6 +978,8 @@ meta_display_close (MetaDisplay *display,
|
||||
|
||||
display->closing += 1;
|
||||
|
||||
g_signal_emit (display, display_signals[CLOSING], 0);
|
||||
|
||||
meta_compositor_unmanage (display->compositor);
|
||||
|
||||
meta_display_unmanage_windows (display, timestamp);
|
||||
|
@ -63,6 +63,15 @@
|
||||
#define META_KEY_BINDING_PRIMARY_LAYOUT 0
|
||||
#define META_KEY_BINDING_SECONDARY_LAYOUT 1
|
||||
|
||||
/* Only for special modifier keys */
|
||||
#define IGNORED_MODIFIERS (CLUTTER_LOCK_MASK | \
|
||||
CLUTTER_MOD2_MASK | \
|
||||
CLUTTER_BUTTON1_MASK | \
|
||||
CLUTTER_BUTTON2_MASK | \
|
||||
CLUTTER_BUTTON3_MASK | \
|
||||
CLUTTER_BUTTON4_MASK | \
|
||||
CLUTTER_BUTTON5_MASK)
|
||||
|
||||
static gboolean add_builtin_keybinding (MetaDisplay *display,
|
||||
const char *name,
|
||||
GSettings *settings,
|
||||
@ -2114,6 +2123,7 @@ process_special_modifier_key (MetaDisplay *display,
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->type == CLUTTER_KEY_PRESS &&
|
||||
((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
|
||||
resolved_key_combo_has_keycode (resolved_key_combo,
|
||||
event->hardware_keycode))
|
||||
{
|
||||
|
@ -32,9 +32,15 @@ static struct {
|
||||
const char *mimetype_glob;
|
||||
ssize_t max_transfer_size;
|
||||
} supported_mimetypes[] = {
|
||||
{ "image/tiff", MAX_IMAGE_SIZE },
|
||||
{ "image/bmp", MAX_IMAGE_SIZE },
|
||||
{ "image/gif", MAX_IMAGE_SIZE },
|
||||
{ "image/jpeg", MAX_IMAGE_SIZE },
|
||||
{ "image/webp", MAX_IMAGE_SIZE },
|
||||
{ "image/png", MAX_IMAGE_SIZE },
|
||||
{ "image/svg+xml", MAX_IMAGE_SIZE },
|
||||
{ "text/plain", MAX_TEXT_SIZE },
|
||||
{ "text/plain;charset=utf-8", MAX_TEXT_SIZE },
|
||||
{ "image/*", MAX_IMAGE_SIZE },
|
||||
};
|
||||
|
||||
static gboolean
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "backends/meta-backend-private.h"
|
||||
#include "clutter/clutter.h"
|
||||
#include "meta/window.h"
|
||||
|
||||
@ -39,14 +40,6 @@
|
||||
typedef struct _MetaGestureTracker MetaGestureTracker;
|
||||
typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_SEQUENCE_NONE,
|
||||
META_SEQUENCE_ACCEPTED,
|
||||
META_SEQUENCE_REJECTED,
|
||||
META_SEQUENCE_PENDING_END
|
||||
} MetaSequenceState;
|
||||
|
||||
struct _MetaGestureTracker
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
32
src/core/meta-selection-private.h
Normal file
32
src/core/meta-selection-private.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Red Hat
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Written by:
|
||||
* Carlos Garnacho <carlosg@gnome.org>
|
||||
*/
|
||||
|
||||
#ifndef META_SELECTION_PRIVATE_H
|
||||
#define META_SELECTION_PRIVATE_H
|
||||
|
||||
#include "meta/meta-selection.h"
|
||||
|
||||
MetaSelectionSource *
|
||||
meta_selection_get_current_owner (MetaSelection *selection,
|
||||
MetaSelectionType selection_type);
|
||||
|
||||
#endif /* META_SELECTION_PRIVATE_H */
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "core/meta-selection-private.h"
|
||||
#include "meta/meta-selection.h"
|
||||
|
||||
typedef struct TransferRequest TransferRequest;
|
||||
@ -50,6 +51,9 @@ static guint signals[N_SIGNALS] = { 0 };
|
||||
|
||||
G_DEFINE_TYPE (MetaSelection, meta_selection, G_TYPE_OBJECT)
|
||||
|
||||
static void read_selection_source_async (GTask *task,
|
||||
TransferRequest *request);
|
||||
|
||||
static void
|
||||
meta_selection_class_init (MetaSelectionClass *klass)
|
||||
{
|
||||
@ -198,6 +202,7 @@ write_cb (GOutputStream *stream,
|
||||
GAsyncResult *result,
|
||||
GTask *task)
|
||||
{
|
||||
TransferRequest *request;
|
||||
GError *error = NULL;
|
||||
|
||||
g_output_stream_write_bytes_finish (stream, result, &error);
|
||||
@ -208,8 +213,17 @@ write_cb (GOutputStream *stream,
|
||||
return;
|
||||
}
|
||||
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
request = g_task_get_task_data (task);
|
||||
|
||||
if (request->len > 0)
|
||||
{
|
||||
read_selection_source_async (task, request);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -228,8 +242,26 @@ read_cb (GInputStream *stream,
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (g_bytes_get_size (bytes) == 0)
|
||||
{
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
request = g_task_get_task_data (task);
|
||||
|
||||
if (request->len < g_bytes_get_size (bytes))
|
||||
{
|
||||
GBytes *copy;
|
||||
|
||||
/* Trim content */
|
||||
copy = g_bytes_new_from_bytes (bytes, 0, request->len);
|
||||
g_bytes_unref (bytes);
|
||||
bytes = copy;
|
||||
}
|
||||
|
||||
request->len -= g_bytes_get_size (bytes);
|
||||
g_output_stream_write_bytes_async (request->ostream,
|
||||
bytes,
|
||||
G_PRIORITY_DEFAULT,
|
||||
@ -239,6 +271,18 @@ read_cb (GInputStream *stream,
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
read_selection_source_async (GTask *task,
|
||||
TransferRequest *request)
|
||||
{
|
||||
g_input_stream_read_bytes_async (request->istream,
|
||||
(gsize) request->len,
|
||||
G_PRIORITY_DEFAULT,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback) read_cb,
|
||||
task);
|
||||
}
|
||||
|
||||
static void
|
||||
source_read_cb (MetaSelectionSource *source,
|
||||
GAsyncResult *result,
|
||||
@ -271,12 +315,7 @@ source_read_cb (MetaSelectionSource *source,
|
||||
}
|
||||
else
|
||||
{
|
||||
g_input_stream_read_bytes_async (request->istream,
|
||||
(gsize) request->len,
|
||||
G_PRIORITY_DEFAULT,
|
||||
g_task_get_cancellable (task),
|
||||
(GAsyncReadyCallback) read_cb,
|
||||
task);
|
||||
read_selection_source_async (task, request);
|
||||
}
|
||||
}
|
||||
|
||||
@ -345,3 +384,13 @@ meta_selection_transfer_finish (MetaSelection *selection,
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
MetaSelectionSource *
|
||||
meta_selection_get_current_owner (MetaSelection *selection,
|
||||
MetaSelectionType selection_type)
|
||||
{
|
||||
g_return_val_if_fail (META_IS_SELECTION (selection), NULL);
|
||||
g_return_val_if_fail (selection_type < META_N_SELECTION_TYPES, NULL);
|
||||
|
||||
return selection->owners[selection_type];
|
||||
}
|
||||
|
@ -858,8 +858,11 @@ static void
|
||||
ensure_above (MetaWindow *above,
|
||||
MetaWindow *below)
|
||||
{
|
||||
if (WINDOW_HAS_TRANSIENT_TYPE(above) &&
|
||||
above->layer < below->layer)
|
||||
gboolean is_transient;
|
||||
|
||||
is_transient = WINDOW_HAS_TRANSIENT_TYPE (above) ||
|
||||
above->transient_for == below;
|
||||
if (is_transient && above->layer < below->layer)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Promoting window %s from layer %u to %u due to contraint\n",
|
||||
|
@ -629,6 +629,7 @@ void meta_window_unmanage (MetaWindow *window,
|
||||
void meta_window_unmanage_on_idle (MetaWindow *window);
|
||||
void meta_window_queue (MetaWindow *window,
|
||||
guint queuebits);
|
||||
META_EXPORT_TEST
|
||||
void meta_window_tile (MetaWindow *window,
|
||||
MetaTileMode mode);
|
||||
MetaTileMode meta_window_get_tile_mode (MetaWindow *window);
|
||||
|
@ -1289,7 +1289,10 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
window->initial_workspace);
|
||||
}
|
||||
|
||||
set_workspace_state (window, on_all_workspaces, workspace);
|
||||
/* Ignore when a window requests to be placed on a non-existent workspace
|
||||
*/
|
||||
if (on_all_workspaces || workspace != NULL)
|
||||
set_workspace_state (window, on_all_workspaces, workspace);
|
||||
}
|
||||
|
||||
/* override-redirect windows are subtly different from other windows
|
||||
@ -1306,8 +1309,9 @@ _meta_window_shared_new (MetaDisplay *display,
|
||||
"Putting window %s on same workspace as parent %s\n",
|
||||
window->desc, window->transient_for->desc);
|
||||
|
||||
g_warn_if_fail (!window->transient_for->override_redirect);
|
||||
set_workspace_state (window,
|
||||
should_be_on_all_workspaces (window->transient_for),
|
||||
window->transient_for->on_all_workspaces,
|
||||
window->transient_for->workspace);
|
||||
}
|
||||
else if (window->on_all_workspaces)
|
||||
@ -3192,7 +3196,10 @@ meta_window_tile (MetaWindow *window,
|
||||
|
||||
/* Don't do anything if no tiling is requested */
|
||||
if (window->tile_mode == META_TILE_NONE)
|
||||
return;
|
||||
{
|
||||
window->tile_monitor_number = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->tile_mode == META_TILE_MAXIMIZED)
|
||||
directions = META_MAXIMIZE_BOTH;
|
||||
@ -3923,11 +3930,16 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
if (!new)
|
||||
new = meta_monitor_manager_get_primary_logical_monitor (monitor_manager);
|
||||
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
{
|
||||
if (new)
|
||||
window->tile_monitor_number = new->number;
|
||||
else
|
||||
window->tile_monitor_number = -1;
|
||||
}
|
||||
|
||||
if (new && old)
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
window->tile_monitor_number = new->number;
|
||||
|
||||
/* This will eventually reach meta_window_update_monitor that
|
||||
* will send leave/enter-monitor events. The old != new monitor
|
||||
* check will always fail (due to the new logical_monitors set) so
|
||||
@ -4817,9 +4829,12 @@ set_workspace_state (MetaWindow *window,
|
||||
{
|
||||
MetaWorkspaceManager *workspace_manager = window->display->workspace_manager;
|
||||
|
||||
/* If we're on all workspaces, then our new workspace must be NULL. */
|
||||
/* If we're on all workspaces, then our new workspace must be NULL,
|
||||
* otherwise it must be set, unless we're unmanaging. */
|
||||
if (on_all_workspaces)
|
||||
g_assert (workspace == NULL);
|
||||
g_assert_null (workspace);
|
||||
else
|
||||
g_assert_true (window->unmanaging || workspace != NULL);
|
||||
|
||||
/* If this is an override-redirect window, ensure that the only
|
||||
* times we're setting the workspace state is either during construction
|
||||
|
@ -62,4 +62,11 @@ META_EXPORT
|
||||
void meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
|
||||
gboolean visible);
|
||||
|
||||
META_EXPORT
|
||||
gboolean meta_cursor_tracker_get_keep_focus_while_hidden (MetaCursorTracker *tracker);
|
||||
|
||||
META_EXPORT
|
||||
void meta_cursor_tracker_set_keep_focus_while_hidden (MetaCursorTracker *tracker,
|
||||
gboolean keep_focus);
|
||||
|
||||
#endif
|
||||
|
@ -131,6 +131,7 @@ stacking_tests = [
|
||||
'mixed-windows',
|
||||
'set-parent',
|
||||
'override-redirect',
|
||||
'set-override-redirect-parent',
|
||||
'set-parent-exported',
|
||||
]
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "backends/meta-monitor-config-migration.h"
|
||||
#include "backends/meta-monitor-config-store.h"
|
||||
#include "backends/meta-output.h"
|
||||
#include "core/window-private.h"
|
||||
#include "meta-backend-test.h"
|
||||
#include "tests/meta-monitor-manager-test.h"
|
||||
#include "tests/monitor-test-utils.h"
|
||||
@ -378,15 +379,22 @@ create_monitor_test_clients (void)
|
||||
}
|
||||
|
||||
static void
|
||||
check_monitor_test_clients_state (void)
|
||||
check_test_client_state (TestClient *test_client)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (!test_client_wait (wayland_monitor_test_client, &error))
|
||||
g_error ("Failed to sync Wayland test client: %s", error->message);
|
||||
if (!test_client_wait (test_client, &error))
|
||||
{
|
||||
g_error ("Failed to sync test client '%s': %s",
|
||||
test_client_get_id (test_client), error->message);
|
||||
}
|
||||
}
|
||||
|
||||
if (!test_client_wait (x11_monitor_test_client, &error))
|
||||
g_error ("Failed to sync X11 test client: %s", error->message);
|
||||
static void
|
||||
check_monitor_test_clients_state (void)
|
||||
{
|
||||
check_test_client_state (wayland_monitor_test_client);
|
||||
check_test_client_state (x11_monitor_test_client);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5753,6 +5761,128 @@ meta_test_monitor_migrated_wiggle_discard (void)
|
||||
g_error ("Failed to remove test data output file: %s", error->message);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
quit_main_loop (gpointer data)
|
||||
{
|
||||
GMainLoop *loop = data;
|
||||
|
||||
g_main_loop_quit (loop);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
dispatch (void)
|
||||
{
|
||||
GMainLoop *loop;
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
quit_main_loop,
|
||||
loop,
|
||||
NULL);
|
||||
g_main_loop_run (loop);
|
||||
}
|
||||
|
||||
static TestClient *
|
||||
create_test_window (const char *window_name)
|
||||
{
|
||||
TestClient *test_client;
|
||||
static int client_count = 0;
|
||||
g_autofree char *client_name = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
client_name = g_strdup_printf ("test_client_%d", client_count++);
|
||||
test_client = test_client_new (client_name, META_WINDOW_CLIENT_TYPE_WAYLAND,
|
||||
&error);
|
||||
if (!test_client)
|
||||
g_error ("Failed to launch test client: %s", error->message);
|
||||
|
||||
if (!test_client_do (test_client, &error,
|
||||
"create", window_name,
|
||||
NULL))
|
||||
g_error ("Failed to create window: %s", error->message);
|
||||
|
||||
return test_client;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_monitor_wm_tiling (void)
|
||||
{
|
||||
MonitorTestCase test_case = initial_test_case;
|
||||
MetaMonitorTestSetup *test_setup;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
|
||||
/*
|
||||
* 1) Start with two monitors connected.
|
||||
* 2) Tile it on the second monitor.
|
||||
* 3) Unplug both monitors.
|
||||
* 4) Replug in first monitor.
|
||||
*/
|
||||
|
||||
const char *test_window_name= "window1";
|
||||
TestClient *test_client = create_test_window (test_window_name);
|
||||
|
||||
if (!test_client_do (test_client, &error,
|
||||
"show", test_window_name,
|
||||
NULL))
|
||||
g_error ("Failed to show the window: %s", error->message);
|
||||
|
||||
MetaWindow *test_window =
|
||||
test_client_find_window (test_client,
|
||||
test_window_name,
|
||||
&error);
|
||||
if (!test_window)
|
||||
g_error ("Failed to find the window: %s", error->message);
|
||||
test_client_wait_for_window_shown (test_client, test_window);
|
||||
|
||||
meta_window_tile (test_window, META_TILE_MAXIMIZED);
|
||||
meta_window_move_to_monitor (test_window, 1);
|
||||
check_test_client_state (test_client);
|
||||
|
||||
fprintf(stderr, ":::: %s:%d %s() - UNPLUGGING\n", __FILE__, __LINE__, __func__);
|
||||
|
||||
test_case.setup.n_outputs = 0;
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
test_case.setup.n_outputs = 1;
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
|
||||
dispatch ();
|
||||
|
||||
/*
|
||||
* 1) Start with two monitors connected.
|
||||
* 2) Tile a window on the second monitor.
|
||||
* 3) Untile window.
|
||||
* 4) Unplug monitor.
|
||||
* 5) Tile window again.
|
||||
*/
|
||||
|
||||
test_case.setup.n_outputs = 2;
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
|
||||
meta_window_move_to_monitor (test_window, 1);
|
||||
meta_window_tile (test_window, META_TILE_NONE);
|
||||
|
||||
test_case.setup.n_outputs = 1;
|
||||
test_setup = create_monitor_test_setup (&test_case,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
emulate_hotplug (test_setup);
|
||||
|
||||
meta_window_tile (test_window, META_TILE_MAXIMIZED);
|
||||
|
||||
test_client_destroy (test_client);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_monitor_migrated_wiggle (void)
|
||||
{
|
||||
@ -6008,6 +6138,9 @@ init_monitor_tests (void)
|
||||
meta_test_monitor_migrated_wiggle);
|
||||
add_monitor_test ("/backends/monitor/migrated/wiggle-discard",
|
||||
meta_test_monitor_migrated_wiggle_discard);
|
||||
|
||||
add_monitor_test ("/backends/monitor/wm/tiling",
|
||||
meta_test_monitor_wm_tiling);
|
||||
}
|
||||
|
||||
void
|
||||
|
24
src/tests/stacking/set-override-redirect-parent.metatest
Normal file
24
src/tests/stacking/set-override-redirect-parent.metatest
Normal file
@ -0,0 +1,24 @@
|
||||
new_client 1 x11
|
||||
create 1/1 override
|
||||
show 1/1
|
||||
|
||||
create 1/2
|
||||
set_parent 1/2 1
|
||||
show 1/2
|
||||
|
||||
create 1/3
|
||||
set_parent 1/3 2
|
||||
show 1/3
|
||||
|
||||
|
||||
new_client 2 x11
|
||||
create 2/1
|
||||
show 2/1
|
||||
|
||||
create 2/2 override
|
||||
set_parent 2/2 1
|
||||
show 2/2
|
||||
|
||||
create 2/3
|
||||
set_parent 2/3 2
|
||||
show 2/3
|
@ -342,39 +342,6 @@ test_case_check_xserver_stacking (TestCase *test,
|
||||
return *error == NULL;
|
||||
}
|
||||
|
||||
typedef struct _WaitForShownData
|
||||
{
|
||||
GMainLoop *loop;
|
||||
MetaWindow *window;
|
||||
guint shown_handler_id;
|
||||
} WaitForShownData;
|
||||
|
||||
static void
|
||||
on_window_shown (MetaWindow *window,
|
||||
WaitForShownData *data)
|
||||
{
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_wait_for_showing_before_redraw (gpointer user_data)
|
||||
{
|
||||
WaitForShownData *data = user_data;
|
||||
|
||||
if (meta_window_is_hidden (data->window))
|
||||
{
|
||||
data->shown_handler_id = g_signal_connect (data->window, "shown",
|
||||
G_CALLBACK (on_window_shown),
|
||||
data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
test_case_do (TestCase *test,
|
||||
int argc,
|
||||
@ -533,18 +500,7 @@ test_case_do (TestCase *test,
|
||||
if (!window)
|
||||
return FALSE;
|
||||
|
||||
WaitForShownData data = {
|
||||
.loop = g_main_loop_new (NULL, FALSE),
|
||||
.window = window,
|
||||
};
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
test_case_wait_for_showing_before_redraw,
|
||||
&data,
|
||||
NULL);
|
||||
g_main_loop_run (data.loop);
|
||||
if (data.shown_handler_id)
|
||||
g_signal_handler_disconnect (window, data.shown_handler_id);
|
||||
g_main_loop_unref (data.loop);
|
||||
test_client_wait_for_window_shown (client, window);
|
||||
}
|
||||
else if (strcmp (argv[0], "hide") == 0 ||
|
||||
strcmp (argv[0], "activate") == 0 ||
|
||||
|
@ -359,6 +359,57 @@ test_client_find_window (TestClient *client,
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct _WaitForShownData
|
||||
{
|
||||
GMainLoop *loop;
|
||||
MetaWindow *window;
|
||||
guint shown_handler_id;
|
||||
} WaitForShownData;
|
||||
|
||||
static void
|
||||
on_window_shown (MetaWindow *window,
|
||||
WaitForShownData *data)
|
||||
{
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wait_for_showing_before_redraw (gpointer user_data)
|
||||
{
|
||||
WaitForShownData *data = user_data;
|
||||
|
||||
if (meta_window_is_hidden (data->window))
|
||||
{
|
||||
data->shown_handler_id = g_signal_connect (data->window, "shown",
|
||||
G_CALLBACK (on_window_shown),
|
||||
data);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_main_loop_quit (data->loop);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
test_client_wait_for_window_shown (TestClient *client,
|
||||
MetaWindow *window)
|
||||
{
|
||||
WaitForShownData data = {
|
||||
.loop = g_main_loop_new (NULL, FALSE),
|
||||
.window = window,
|
||||
};
|
||||
meta_later_add (META_LATER_BEFORE_REDRAW,
|
||||
wait_for_showing_before_redraw,
|
||||
&data,
|
||||
NULL);
|
||||
g_main_loop_run (data.loop);
|
||||
if (data.shown_handler_id)
|
||||
g_signal_handler_disconnect (window, data.shown_handler_id);
|
||||
g_main_loop_unref (data.loop);
|
||||
}
|
||||
|
||||
gboolean
|
||||
test_client_alarm_filter (MetaX11Display *x11_display,
|
||||
XSyncAlarmNotifyEvent *event,
|
||||
|
@ -70,6 +70,9 @@ MetaWindow * test_client_find_window (TestClient *client,
|
||||
const char *window_id,
|
||||
GError **error);
|
||||
|
||||
void test_client_wait_for_window_shown (TestClient *client,
|
||||
MetaWindow *window);
|
||||
|
||||
gboolean test_client_quit (TestClient *client,
|
||||
GError **error);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "compositor/meta-surface-actor-wayland.h"
|
||||
#include "compositor/meta-window-actor-wayland.h"
|
||||
#include "compositor/region-utils.h"
|
||||
#include "wayland/meta-wayland-buffer.h"
|
||||
#include "wayland/meta-wayland-surface.h"
|
||||
#include "wayland/meta-window-wayland.h"
|
||||
|
||||
@ -38,6 +39,8 @@ struct _MetaWaylandActorSurfacePrivate
|
||||
MetaSurfaceActor *actor;
|
||||
|
||||
gulong actor_destroyed_handler_id;
|
||||
|
||||
struct wl_list frame_callback_list;
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaWaylandActorSurface,
|
||||
@ -78,6 +81,7 @@ meta_wayland_actor_surface_dispose (GObject *object)
|
||||
MetaWaylandActorSurface *actor_surface = META_WAYLAND_ACTOR_SURFACE (object);
|
||||
MetaWaylandActorSurfacePrivate *priv =
|
||||
meta_wayland_actor_surface_get_instance_private (actor_surface);
|
||||
MetaWaylandFrameCallback *cb, *next;
|
||||
|
||||
if (priv->actor)
|
||||
{
|
||||
@ -85,6 +89,9 @@ meta_wayland_actor_surface_dispose (GObject *object)
|
||||
clear_surface_actor (actor_surface);
|
||||
}
|
||||
|
||||
wl_list_for_each_safe (cb, next, &priv->frame_callback_list, link)
|
||||
wl_resource_destroy (cb->resource);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_actor_surface_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -113,6 +120,9 @@ meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor
|
||||
if (!priv->actor)
|
||||
return;
|
||||
|
||||
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
|
||||
&priv->frame_callback_list);
|
||||
wl_list_init (&priv->frame_callback_list);
|
||||
meta_surface_actor_wayland_add_frame_callbacks (surface_actor_wayland,
|
||||
&pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
@ -138,13 +148,33 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaSurfaceActor *surface_actor;
|
||||
MetaShapedTexture *stex;
|
||||
GNode *n;
|
||||
MetaWaylandBuffer *buffer;
|
||||
cairo_rectangle_int_t surface_rect;
|
||||
int geometry_scale;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
surface_actor = priv->actor;
|
||||
stex = meta_surface_actor_get_texture (surface_actor);
|
||||
meta_shaped_texture_set_buffer_scale (stex, surface->scale);
|
||||
|
||||
buffer = surface->buffer_ref.buffer;
|
||||
if (buffer)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
snippet = meta_wayland_buffer_create_snippet (buffer);
|
||||
is_y_inverted = meta_wayland_buffer_is_y_inverted (buffer);
|
||||
|
||||
meta_shaped_texture_set_texture (stex, surface->texture);
|
||||
meta_shaped_texture_set_snippet (stex, snippet);
|
||||
meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
|
||||
meta_shaped_texture_set_buffer_scale (stex, surface->scale);
|
||||
cogl_clear_object (&snippet);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_shaped_texture_set_texture (stex, NULL);
|
||||
}
|
||||
|
||||
/* Wayland surface coordinate space -> stage coordinate space */
|
||||
geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
||||
@ -204,19 +234,12 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
|
||||
meta_surface_actor_reset_viewport_dst_size (surface_actor);
|
||||
}
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandActorSurface *subsurface_actor_surface;
|
||||
MetaWaylandActorSurface *actor_surface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface_actor_surface =
|
||||
META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_sync_actor_state (subsurface_actor_surface);
|
||||
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_sync_actor_state (actor_surface);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +262,12 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
meta_wayland_actor_surface_get_instance_private (actor_surface);
|
||||
|
||||
if (!priv->actor)
|
||||
return;
|
||||
{
|
||||
wl_list_insert_list (&priv->frame_callback_list,
|
||||
&pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wl_list_empty (&pending->frame_callback_list) &&
|
||||
cairo_region_is_empty (pending->surface_damage) &&
|
||||
@ -264,6 +292,9 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
|
||||
MetaRectangle logical_monitor_layout;
|
||||
gboolean is_on_monitor;
|
||||
|
||||
if (!clutter_actor_is_mapped (actor))
|
||||
return FALSE;
|
||||
|
||||
clutter_actor_get_transformed_position (actor, &x, &y);
|
||||
clutter_actor_get_transformed_size (actor, &width, &height);
|
||||
|
||||
@ -292,8 +323,12 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_actor_surface_init (MetaWaylandActorSurface *role)
|
||||
meta_wayland_actor_surface_init (MetaWaylandActorSurface *actor_surface)
|
||||
{
|
||||
MetaWaylandActorSurfacePrivate *priv =
|
||||
meta_wayland_actor_surface_get_instance_private (actor_surface);
|
||||
|
||||
wl_list_init (&priv->frame_callback_list);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -337,6 +372,16 @@ meta_wayland_actor_surface_reset_actor (MetaWaylandActorSurface *actor_surface)
|
||||
meta_wayland_actor_surface_get_instance_private (actor_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (actor_surface));
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandActorSurface *actor_surface;
|
||||
|
||||
actor_surface = META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
|
||||
meta_wayland_actor_surface_reset_actor (actor_surface);
|
||||
meta_wayland_actor_surface_sync_actor_state (actor_surface);
|
||||
}
|
||||
|
||||
clear_surface_actor (actor_surface);
|
||||
|
||||
|
@ -198,7 +198,6 @@ shm_buffer_get_cogl_pixel_format (struct wl_shm_buffer *shm_buffer,
|
||||
static gboolean
|
||||
shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@ -224,7 +223,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
_cogl_texture_get_format (*texture) == format)
|
||||
{
|
||||
buffer->is_y_inverted = TRUE;
|
||||
*changed_texture = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -269,7 +267,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
return FALSE;
|
||||
|
||||
*texture = new_texture;
|
||||
*changed_texture = TRUE;
|
||||
buffer->is_y_inverted = TRUE;
|
||||
|
||||
return TRUE;
|
||||
@ -278,7 +275,6 @@ shm_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
static gboolean
|
||||
egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
@ -294,7 +290,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
if (buffer->egl_image.texture)
|
||||
{
|
||||
*changed_texture = *texture != buffer->egl_image.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
return TRUE;
|
||||
@ -362,7 +357,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_image.texture);
|
||||
*changed_texture = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -371,7 +365,6 @@ egl_image_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
static gboolean
|
||||
egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
MetaWaylandEglStream *stream = buffer->egl_stream.stream;
|
||||
@ -381,7 +374,6 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
if (!meta_wayland_egl_stream_attach (stream, error))
|
||||
return FALSE;
|
||||
|
||||
*changed_texture = *texture != buffer->egl_stream.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->egl_stream.texture);
|
||||
|
||||
@ -411,7 +403,6 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
gboolean
|
||||
meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (buffer->resource, FALSE);
|
||||
@ -428,17 +419,16 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
switch (buffer->type)
|
||||
{
|
||||
case META_WAYLAND_BUFFER_TYPE_SHM:
|
||||
return shm_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return shm_buffer_attach (buffer, texture, error);
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_IMAGE:
|
||||
return egl_image_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return egl_image_buffer_attach (buffer, texture, error);
|
||||
#ifdef HAVE_WAYLAND_EGLSTREAM
|
||||
case META_WAYLAND_BUFFER_TYPE_EGL_STREAM:
|
||||
return egl_stream_buffer_attach (buffer, texture, changed_texture, error);
|
||||
return egl_stream_buffer_attach (buffer, texture, error);
|
||||
#endif
|
||||
case META_WAYLAND_BUFFER_TYPE_DMA_BUF:
|
||||
return meta_wayland_dma_buf_buffer_attach (buffer,
|
||||
texture,
|
||||
changed_texture,
|
||||
error);
|
||||
case META_WAYLAND_BUFFER_TYPE_UNKNOWN:
|
||||
g_assert_not_reached ();
|
||||
@ -456,7 +446,7 @@ meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer)
|
||||
if (!buffer->egl_stream.stream)
|
||||
return NULL;
|
||||
|
||||
return meta_wayland_egl_stream_create_snippet ();
|
||||
return meta_wayland_egl_stream_create_snippet (buffer->egl_stream.stream);
|
||||
#else
|
||||
return NULL;
|
||||
#endif /* HAVE_WAYLAND_EGLSTREAM */
|
||||
|
@ -82,7 +82,6 @@ gboolean meta_wayland_buffer_is_realized (MetaWaylandBuff
|
||||
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_buffer_create_snippet (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_is_y_inverted (MetaWaylandBuffer *buffer);
|
||||
|
@ -25,16 +25,10 @@
|
||||
#ifndef META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
#define META_WAYLAND_DATA_DEVICE_PRIVATE_H
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND (meta_wayland_data_source_wayland_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourceWayland,
|
||||
meta_wayland_data_source_wayland,
|
||||
META, WAYLAND_DATA_SOURCE_WAYLAND,
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#define META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY (meta_wayland_data_source_primary_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaWaylandDataSourcePrimary,
|
||||
meta_wayland_data_source_primary,
|
||||
META, WAYLAND_DATA_SOURCE_PRIMARY,
|
||||
MetaWaylandDataSourceWayland);
|
||||
MetaWaylandDataSource);
|
||||
|
||||
#endif /* META_WAYLAND_DATA_DEVICE_PRIVATE_H */
|
||||
|
@ -65,6 +65,7 @@ struct _MetaWaylandDataOffer
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrivate
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
MetaWaylandDataOffer *offer;
|
||||
struct wl_array mime_types;
|
||||
gboolean has_target;
|
||||
@ -74,35 +75,30 @@ typedef struct _MetaWaylandDataSourcePrivate
|
||||
MetaWaylandSeat *seat;
|
||||
guint actions_set : 1;
|
||||
guint in_ask : 1;
|
||||
guint drop_performed : 1;
|
||||
} MetaWaylandDataSourcePrivate;
|
||||
|
||||
typedef struct _MetaWaylandDataSourceWayland
|
||||
{
|
||||
MetaWaylandDataSource parent;
|
||||
|
||||
struct wl_resource *resource;
|
||||
} MetaWaylandDataSourceWayland;
|
||||
|
||||
typedef struct _MetaWaylandDataSourcePrimary
|
||||
{
|
||||
MetaWaylandDataSourceWayland parent;
|
||||
MetaWaylandDataSource parent;
|
||||
} MetaWaylandDataSourcePrimary;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandDataSource, meta_wayland_data_source,
|
||||
G_TYPE_OBJECT);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourceWayland, meta_wayland_data_source_wayland,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
G_DEFINE_TYPE (MetaWaylandDataSourcePrimary, meta_wayland_data_source_primary,
|
||||
META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND);
|
||||
META_TYPE_WAYLAND_DATA_SOURCE);
|
||||
|
||||
static void unset_selection_source (MetaWaylandDataDevice *data_device,
|
||||
MetaSelectionType selection_type);
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource);
|
||||
meta_wayland_data_source_new (struct wl_resource *resource);
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_new (struct wl_resource *resource);
|
||||
|
||||
static void
|
||||
meta_wayland_source_cancel (MetaWaylandDataSource *source);
|
||||
|
||||
static void
|
||||
drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was);
|
||||
|
||||
@ -110,6 +106,31 @@ static struct wl_resource * create_and_send_clipboard_offer (MetaWaylandDataDevi
|
||||
struct wl_resource *target);
|
||||
static struct wl_resource * create_and_send_primary_offer (MetaWaylandDataDevice *data_device,
|
||||
struct wl_resource *target);
|
||||
static struct wl_resource * meta_wayland_data_source_get_resource (MetaWaylandDataSource *source);
|
||||
|
||||
static void
|
||||
move_resources (struct wl_list *destination,
|
||||
struct wl_list *source)
|
||||
{
|
||||
wl_list_insert_list (destination, source);
|
||||
wl_list_init (source);
|
||||
}
|
||||
|
||||
static void
|
||||
move_resources_for_client (struct wl_list *destination,
|
||||
struct wl_list *source,
|
||||
struct wl_client *client)
|
||||
{
|
||||
struct wl_resource *resource, *tmp;
|
||||
wl_resource_for_each_safe (resource, tmp, source)
|
||||
{
|
||||
if (wl_resource_get_client (resource) == client)
|
||||
{
|
||||
wl_list_remove (wl_resource_get_link (resource));
|
||||
wl_list_insert (destination, wl_resource_get_link (resource));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unbind_resource (struct wl_resource *resource)
|
||||
@ -142,6 +163,10 @@ data_offer_choose_action (MetaWaylandDataOffer *offer)
|
||||
MetaWaylandDataSource *source = offer->source;
|
||||
uint32_t actions, user_action, available_actions;
|
||||
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
return WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
|
||||
actions = meta_wayland_data_source_get_actions (source);
|
||||
user_action = meta_wayland_data_source_get_user_action (source);
|
||||
|
||||
@ -189,6 +214,25 @@ data_offer_update_action (MetaWaylandDataOffer *offer)
|
||||
}
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
meta_wayland_data_source_get_resource (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->resource;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_set_resource (MetaWaylandDataSource *source,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
priv->resource = resource;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_target (MetaWaylandDataSource *source,
|
||||
const char *mime_type)
|
||||
@ -334,9 +378,9 @@ meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
priv->actions_set = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
void
|
||||
meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
@ -352,6 +396,15 @@ meta_wayland_data_source_set_user_action (MetaWaylandDataSource
|
||||
data_offer_update_action (offer);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_wayland_data_source_get_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
return priv->drop_performed;
|
||||
}
|
||||
|
||||
static void
|
||||
data_offer_accept (struct wl_client *client,
|
||||
struct wl_resource *resource,
|
||||
@ -566,16 +619,18 @@ destroy_data_offer (struct wl_resource *resource)
|
||||
|
||||
if (offer == meta_wayland_data_source_get_current_offer (offer->source))
|
||||
{
|
||||
if (seat->data_device.dnd_data_source == offer->source &&
|
||||
wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
if (seat->data_device.dnd_data_source == offer->source)
|
||||
{
|
||||
if (wl_resource_get_version (offer->resource) <
|
||||
WL_DATA_OFFER_ACTION_SINCE_VERSION)
|
||||
meta_wayland_data_source_notify_finish (offer->source);
|
||||
else if (meta_wayland_data_source_get_drop_performed (offer->source))
|
||||
meta_wayland_source_cancel (offer->source);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (seat->data_device.dnd_data_source == offer->source)
|
||||
unset_selection_source (&seat->data_device, META_SELECTION_DND);
|
||||
meta_wayland_data_source_cancel (offer->source);
|
||||
meta_wayland_data_source_set_current_offer (offer->source, NULL);
|
||||
meta_wayland_data_source_set_has_target (offer->source, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -659,12 +714,10 @@ data_source_set_actions (struct wl_client *client,
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
|
||||
if (priv->actions_set)
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"cannot set actions more than once");
|
||||
return;
|
||||
@ -672,7 +725,7 @@ data_source_set_actions (struct wl_client *client,
|
||||
|
||||
if (dnd_actions & ~(ALL_ACTIONS))
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid actions mask %x", dnd_actions);
|
||||
return;
|
||||
@ -680,7 +733,7 @@ data_source_set_actions (struct wl_client *client,
|
||||
|
||||
if (meta_wayland_data_source_get_seat (source))
|
||||
{
|
||||
wl_resource_post_error (source_wayland->resource,
|
||||
wl_resource_post_error (priv->resource,
|
||||
WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
|
||||
"invalid action change after "
|
||||
"wl_data_device.start_drag");
|
||||
@ -872,6 +925,12 @@ meta_wayland_drag_grab_set_focus (MetaWaylandDragGrab *drag_grab,
|
||||
client = wl_resource_get_client (surface->resource);
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&seat->data_device.resource_list, client);
|
||||
if (!data_device_resource)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&seat->data_device.focus_resource_list,
|
||||
client);
|
||||
}
|
||||
|
||||
if (source && data_device_resource)
|
||||
offer = create_and_send_dnd_offer (source, data_device_resource);
|
||||
@ -1023,7 +1082,7 @@ meta_wayland_data_source_fake_read (MetaWaylandDataSource *source,
|
||||
|
||||
static void
|
||||
drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
const ClutterEvent *event)
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandDragGrab *drag_grab = (MetaWaylandDragGrab*) grab;
|
||||
MetaWaylandSeat *seat = drag_grab->seat;
|
||||
@ -1059,11 +1118,11 @@ drag_grab_button (MetaWaylandPointerGrab *grab,
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_wayland_data_source_cancel (source);
|
||||
meta_wayland_data_source_set_current_offer (source, NULL);
|
||||
if (source)
|
||||
meta_wayland_data_source_set_current_offer (source, NULL);
|
||||
meta_wayland_data_device_set_dnd_source (&seat->data_device, NULL);
|
||||
unset_selection_source (&seat->data_device, META_SELECTION_DND);
|
||||
success= FALSE;
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
/* Finish drag and let actor self-destruct */
|
||||
@ -1134,8 +1193,6 @@ drag_grab_data_source_destroyed (gpointer data, GObject *where_the_object_was)
|
||||
MetaWaylandDragGrab *drag_grab = data;
|
||||
|
||||
drag_grab->drag_data_source = NULL;
|
||||
meta_wayland_data_device_set_dnd_source (&drag_grab->seat->data_device, NULL);
|
||||
unset_selection_source (&drag_grab->seat->data_device, META_SELECTION_DND);
|
||||
data_device_end_drag_grab (drag_grab);
|
||||
}
|
||||
|
||||
@ -1304,21 +1361,8 @@ static void
|
||||
selection_data_source_destroyed (gpointer data, GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client = NULL;
|
||||
|
||||
data_device->selection_data_source = NULL;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
wl_data_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
|
||||
wl_signal_emit (&data_device->selection_ownership_signal, NULL);
|
||||
unset_selection_source (data_device, META_SELECTION_CLIPBOARD);
|
||||
}
|
||||
|
||||
@ -1327,10 +1371,10 @@ meta_wayland_source_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_send (source_wayland->resource, mime_type, fd);
|
||||
wl_data_source_send_send (priv->resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
@ -1338,43 +1382,48 @@ static void
|
||||
meta_wayland_source_target (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
wl_data_source_send_target (source_wayland->resource, mime_type);
|
||||
wl_data_source_send_target (priv->resource, mime_type);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (source_wayland->resource)
|
||||
wl_data_source_send_cancelled (source_wayland->resource);
|
||||
if (!priv->resource)
|
||||
return;
|
||||
|
||||
wl_data_source_send_cancelled (priv->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_action (MetaWaylandDataSource *source,
|
||||
enum wl_data_device_manager_dnd_action action)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
wl_data_source_send_action (source_wayland->resource, action);
|
||||
wl_data_source_send_action (priv->resource, action);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_drop_performed (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
|
||||
wl_data_source_send_dnd_drop_performed (source_wayland->resource);
|
||||
{
|
||||
priv->drop_performed = TRUE;
|
||||
wl_data_source_send_dnd_drop_performed (priv->resource);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1382,8 +1431,8 @@ meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
|
||||
MetaWaylandDataDevice *data_device = &compositor->seat->data_device;
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
enum wl_data_device_manager_dnd_action action;
|
||||
|
||||
if (meta_wayland_source_get_in_ask (source))
|
||||
@ -1392,81 +1441,15 @@ meta_wayland_source_drag_finished (MetaWaylandDataSource *source)
|
||||
meta_wayland_source_action (source, action);
|
||||
}
|
||||
|
||||
if (wl_resource_get_version (source_wayland->resource) >=
|
||||
if (wl_resource_get_version (priv->resource) >=
|
||||
WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION)
|
||||
wl_data_source_send_dnd_finished (source_wayland->resource);
|
||||
wl_data_source_send_dnd_finished (priv->resource);
|
||||
|
||||
unset_selection_source (data_device, META_SELECTION_DND);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_source_finalize (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_wayland_data_source_wayland_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_init (MetaWaylandDataSourceWayland *source_wayland)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_wayland_class_init (MetaWaylandDataSourceWaylandClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_source_finalize;
|
||||
|
||||
data_source_class->send = meta_wayland_source_send;
|
||||
data_source_class->target = meta_wayland_source_target;
|
||||
data_source_class->cancel = meta_wayland_source_cancel;
|
||||
data_source_class->action = meta_wayland_source_action;
|
||||
data_source_class->drop_performed = meta_wayland_source_drop_performed;
|
||||
data_source_class->drag_finished = meta_wayland_source_drag_finished;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland;
|
||||
|
||||
source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
gtk_primary_selection_source_send_send (source_wayland->resource,
|
||||
mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland;
|
||||
|
||||
source_wayland = META_WAYLAND_DATA_SOURCE_WAYLAND (source);
|
||||
if (source_wayland->resource)
|
||||
gtk_primary_selection_source_send_cancelled (source_wayland->resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandDataSource *source = META_WAYLAND_DATA_SOURCE (object);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
@ -1488,6 +1471,7 @@ meta_wayland_data_source_init (MetaWaylandDataSource *source)
|
||||
|
||||
wl_array_init (&priv->mime_types);
|
||||
priv->current_dnd_action = -1;
|
||||
priv->drop_performed = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1495,7 +1479,49 @@ meta_wayland_data_source_class_init (MetaWaylandDataSourceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_data_source_finalize;
|
||||
object_class->finalize = meta_wayland_source_finalize;
|
||||
|
||||
klass->send = meta_wayland_source_send;
|
||||
klass->target = meta_wayland_source_target;
|
||||
klass->cancel = meta_wayland_source_cancel;
|
||||
klass->action = meta_wayland_source_action;
|
||||
klass->drop_performed = meta_wayland_source_drop_performed;
|
||||
klass->drag_finished = meta_wayland_source_drag_finished;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_send (MetaWaylandDataSource *source,
|
||||
const gchar *mime_type,
|
||||
gint fd)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
gtk_primary_selection_source_send_send (resource, mime_type, fd);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_cancel (MetaWaylandDataSource *source)
|
||||
{
|
||||
struct wl_resource *resource = meta_wayland_data_source_get_resource (source);
|
||||
|
||||
if (resource)
|
||||
gtk_primary_selection_source_send_cancelled (resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_init (MetaWaylandDataSourcePrimary *source_primary)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_data_source_primary_class_init (MetaWaylandDataSourcePrimaryClass *klass)
|
||||
{
|
||||
MetaWaylandDataSourceClass *data_source_class =
|
||||
META_WAYLAND_DATA_SOURCE_CLASS (klass);
|
||||
|
||||
data_source_class->send = meta_wayland_data_source_primary_send;
|
||||
data_source_class->cancel = meta_wayland_data_source_primary_cancel;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1598,6 +1624,16 @@ meta_wayland_data_device_get_drag_dest_funcs (void)
|
||||
return &meta_wayland_drag_dest_funcs;
|
||||
}
|
||||
|
||||
static void
|
||||
dnd_data_source_destroyed (gpointer data,
|
||||
GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
|
||||
data_device->dnd_data_source = NULL;
|
||||
unset_selection_source (data_device, META_SELECTION_DND);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
|
||||
MetaWaylandDataSource *source)
|
||||
@ -1606,16 +1642,20 @@ meta_wayland_data_device_set_dnd_source (MetaWaylandDataDevice *data_device,
|
||||
return;
|
||||
|
||||
if (data_device->dnd_data_source)
|
||||
g_object_remove_weak_pointer (G_OBJECT (data_device->dnd_data_source),
|
||||
(gpointer *)&data_device->dnd_data_source);
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (data_device->dnd_data_source),
|
||||
dnd_data_source_destroyed,
|
||||
data_device);
|
||||
}
|
||||
|
||||
data_device->dnd_data_source = source;
|
||||
|
||||
if (source)
|
||||
g_object_add_weak_pointer (G_OBJECT (data_device->dnd_data_source),
|
||||
(gpointer *)&data_device->dnd_data_source);
|
||||
|
||||
wl_signal_emit (&data_device->dnd_ownership_signal, source);
|
||||
{
|
||||
g_object_weak_ref (G_OBJECT (source),
|
||||
dnd_data_source_destroyed,
|
||||
data_device);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -1624,8 +1664,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
if (data_device->selection_data_source &&
|
||||
@ -1634,7 +1672,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (data_device->selection_data_source)
|
||||
{
|
||||
meta_wayland_data_source_cancel (data_device->selection_data_source);
|
||||
g_object_weak_unref (G_OBJECT (data_device->selection_data_source),
|
||||
selection_data_source_destroyed,
|
||||
data_device);
|
||||
@ -1661,20 +1698,6 @@ meta_wayland_data_device_set_selection (MetaWaylandDataDevice *data_device,
|
||||
set_selection_source (data_device, META_SELECTION_CLIPBOARD,
|
||||
selection_source);
|
||||
g_object_unref (selection_source);
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
|
||||
wl_signal_emit (&data_device->selection_ownership_signal, source);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1684,6 +1707,7 @@ data_device_set_selection (struct wl_client *client,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDataSourcePrivate *priv;
|
||||
MetaWaylandDataSource *source;
|
||||
|
||||
@ -1705,6 +1729,10 @@ data_device_set_selection (struct wl_client *client,
|
||||
}
|
||||
}
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
/* FIXME: Store serial and check against incoming serial here. */
|
||||
meta_wayland_data_device_set_selection (data_device, source, serial);
|
||||
}
|
||||
@ -1720,22 +1748,8 @@ primary_source_destroyed (gpointer data,
|
||||
GObject *object_was_here)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = data;
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_client *focus_client = NULL;
|
||||
|
||||
data_device->primary_data_source = NULL;
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
struct wl_resource *data_device_resource;
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, NULL);
|
||||
}
|
||||
|
||||
wl_signal_emit (&data_device->primary_ownership_signal, NULL);
|
||||
unset_selection_source (data_device, META_SELECTION_PRIMARY);
|
||||
}
|
||||
|
||||
@ -1745,20 +1759,9 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
guint32 serial)
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
struct wl_resource *data_device_resource;
|
||||
struct wl_client *focus_client;
|
||||
MetaSelectionSource *selection_source;
|
||||
|
||||
if (META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source))
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
resource = META_WAYLAND_DATA_SOURCE_WAYLAND (source)->resource;
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
}
|
||||
g_assert (!source || META_IS_WAYLAND_DATA_SOURCE_PRIMARY (source));
|
||||
|
||||
if (data_device->primary_data_source &&
|
||||
data_device->primary_serial - serial < UINT32_MAX / 2)
|
||||
@ -1766,7 +1769,6 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
|
||||
if (data_device->primary_data_source)
|
||||
{
|
||||
meta_wayland_data_source_cancel (data_device->primary_data_source);
|
||||
g_object_weak_unref (G_OBJECT (data_device->primary_data_source),
|
||||
primary_source_destroyed,
|
||||
data_device);
|
||||
@ -1792,20 +1794,6 @@ meta_wayland_data_device_set_primary (MetaWaylandDataDevice *data_device,
|
||||
set_selection_source (data_device, META_SELECTION_PRIMARY,
|
||||
selection_source);
|
||||
g_object_unref (selection_source);
|
||||
|
||||
focus_client = meta_wayland_keyboard_get_focus_client (seat->keyboard);
|
||||
if (focus_client)
|
||||
{
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
}
|
||||
|
||||
wl_signal_emit (&data_device->primary_ownership_signal, source);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1815,10 +1803,16 @@ primary_device_set_selection (struct wl_client *client,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandDataDevice *data_device = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSeat *seat = wl_container_of (data_device, seat, data_device);
|
||||
MetaWaylandDataSource *source = NULL;
|
||||
|
||||
if (source_resource)
|
||||
source = wl_resource_get_user_data (source_resource);
|
||||
|
||||
if (wl_resource_get_client (resource) !=
|
||||
meta_wayland_keyboard_get_focus_client (seat->keyboard))
|
||||
return;
|
||||
|
||||
meta_wayland_data_device_set_primary (data_device, source, serial);
|
||||
}
|
||||
|
||||
@ -1830,9 +1824,9 @@ static const struct gtk_primary_selection_device_interface primary_device_interf
|
||||
static void
|
||||
destroy_data_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
source->resource = NULL;
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
@ -1844,7 +1838,7 @@ create_data_source (struct wl_client *client,
|
||||
|
||||
source_resource = wl_resource_create (client, &wl_data_source_interface,
|
||||
wl_resource_get_version (resource), id);
|
||||
meta_wayland_data_source_wayland_new (source_resource);
|
||||
meta_wayland_data_source_new (source_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1864,10 +1858,7 @@ owner_changed_cb (MetaSelection *selection,
|
||||
|
||||
if (selection_type == META_SELECTION_PRIMARY)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&data_device->primary_resource_list,
|
||||
focus_client);
|
||||
if (data_device_resource)
|
||||
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
@ -1883,10 +1874,7 @@ owner_changed_cb (MetaSelection *selection,
|
||||
}
|
||||
else if (selection_type == META_SELECTION_CLIPBOARD)
|
||||
{
|
||||
data_device_resource =
|
||||
wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
|
||||
if (data_device_resource)
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer = NULL;
|
||||
|
||||
@ -1936,9 +1924,9 @@ static const struct wl_data_device_manager_interface manager_interface = {
|
||||
static void
|
||||
destroy_primary_source (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source = wl_resource_get_user_data (resource);
|
||||
MetaWaylandDataSource *source = wl_resource_get_user_data (resource);
|
||||
|
||||
source->resource = NULL;
|
||||
meta_wayland_data_source_set_resource (source, NULL);
|
||||
g_object_unref (source);
|
||||
}
|
||||
|
||||
@ -2021,10 +2009,9 @@ void
|
||||
meta_wayland_data_device_init (MetaWaylandDataDevice *data_device)
|
||||
{
|
||||
wl_list_init (&data_device->resource_list);
|
||||
wl_list_init (&data_device->focus_resource_list);
|
||||
wl_list_init (&data_device->primary_resource_list);
|
||||
wl_signal_init (&data_device->selection_ownership_signal);
|
||||
wl_signal_init (&data_device->primary_ownership_signal);
|
||||
wl_signal_init (&data_device->dnd_ownership_signal);
|
||||
wl_list_init (&data_device->primary_focus_resource_list);
|
||||
}
|
||||
|
||||
static struct wl_resource *
|
||||
@ -2106,22 +2093,34 @@ meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_device)
|
||||
return;
|
||||
|
||||
data_device->focus_client = focus_client;
|
||||
move_resources (&data_device->resource_list,
|
||||
&data_device->focus_resource_list);
|
||||
move_resources (&data_device->primary_resource_list,
|
||||
&data_device->primary_focus_resource_list);
|
||||
|
||||
if (!focus_client)
|
||||
return;
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
move_resources_for_client (&data_device->focus_resource_list,
|
||||
&data_device->resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
|
||||
offer = create_and_send_clipboard_offer (data_device, data_device_resource);
|
||||
wl_data_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
|
||||
data_device_resource = wl_resource_find_for_client (&data_device->primary_resource_list, focus_client);
|
||||
if (data_device_resource)
|
||||
move_resources_for_client (&data_device->primary_focus_resource_list,
|
||||
&data_device->primary_resource_list,
|
||||
focus_client);
|
||||
|
||||
wl_resource_for_each (data_device_resource, &data_device->primary_focus_resource_list)
|
||||
{
|
||||
struct wl_resource *offer;
|
||||
|
||||
offer = create_and_send_primary_offer (data_device, data_device_resource);
|
||||
gtk_primary_selection_device_send_selection (data_device_resource, offer);
|
||||
}
|
||||
@ -2159,29 +2158,37 @@ meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
|
||||
}
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_wayland_new (struct wl_resource *resource)
|
||||
meta_wayland_data_source_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_wayland =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_WAYLAND, NULL);
|
||||
MetaWaylandDataSource *source =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE, NULL);
|
||||
MetaWaylandDataSourcePrivate *priv =
|
||||
meta_wayland_data_source_get_instance_private (source);
|
||||
|
||||
source_wayland->resource = resource;
|
||||
meta_wayland_data_source_set_resource (source, resource);
|
||||
wl_resource_set_implementation (resource, &data_source_interface,
|
||||
source_wayland, destroy_data_source);
|
||||
source, destroy_data_source);
|
||||
|
||||
return META_WAYLAND_DATA_SOURCE (source_wayland);
|
||||
if (wl_resource_get_version (resource) < WL_DATA_SOURCE_ACTION_SINCE_VERSION)
|
||||
{
|
||||
priv->dnd_actions = priv->user_dnd_action =
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static MetaWaylandDataSource *
|
||||
meta_wayland_data_source_primary_new (struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandDataSourceWayland *source_primary =
|
||||
MetaWaylandDataSource *source_primary =
|
||||
g_object_new (META_TYPE_WAYLAND_DATA_SOURCE_PRIMARY, NULL);
|
||||
|
||||
source_primary->resource = resource;
|
||||
meta_wayland_data_source_set_resource (source_primary, resource);
|
||||
wl_resource_set_implementation (resource, &primary_source_interface,
|
||||
source_primary, destroy_primary_source);
|
||||
|
||||
return META_WAYLAND_DATA_SOURCE (source_primary);
|
||||
return source_primary;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -63,14 +63,12 @@ struct _MetaWaylandDataDevice
|
||||
MetaWaylandDataSource *primary_data_source;
|
||||
struct wl_listener selection_data_source_listener;
|
||||
struct wl_list resource_list;
|
||||
struct wl_list focus_resource_list;
|
||||
struct wl_list primary_resource_list;
|
||||
struct wl_list primary_focus_resource_list;
|
||||
MetaWaylandDragGrab *current_grab;
|
||||
struct wl_client *focus_client;
|
||||
|
||||
struct wl_signal selection_ownership_signal;
|
||||
struct wl_signal dnd_ownership_signal;
|
||||
struct wl_signal primary_ownership_signal;
|
||||
|
||||
guint selection_owner_signal_id;
|
||||
|
||||
MetaSelectionSource *owners[META_N_SELECTION_TYPES];
|
||||
@ -125,6 +123,8 @@ uint32_t meta_wayland_data_source_get_current_action (MetaWaylandDataSource *sou
|
||||
|
||||
void meta_wayland_data_source_set_actions (MetaWaylandDataSource *source,
|
||||
uint32_t dnd_actions);
|
||||
void meta_wayland_data_source_set_user_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
void meta_wayland_data_source_set_current_action (MetaWaylandDataSource *source,
|
||||
uint32_t action);
|
||||
|
||||
|
@ -158,13 +158,11 @@ meta_wayland_dma_buf_realize_texture (MetaWaylandBuffer *buffer,
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error)
|
||||
{
|
||||
if (!meta_wayland_dma_buf_realize_texture (buffer, error))
|
||||
return FALSE;
|
||||
|
||||
*changed_texture = *texture != buffer->dma_buf.texture;
|
||||
cogl_clear_object (texture);
|
||||
*texture = cogl_object_ref (buffer->dma_buf.texture);
|
||||
return TRUE;
|
||||
|
@ -44,7 +44,6 @@ gboolean meta_wayland_dma_buf_init (MetaWaylandCompositor *compositor);
|
||||
gboolean
|
||||
meta_wayland_dma_buf_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
CoglTexture **texture,
|
||||
gboolean *changed_texture,
|
||||
GError **error);
|
||||
|
||||
MetaWaylandDmaBufBuffer *
|
||||
|
@ -134,6 +134,7 @@ struct _MetaWaylandEglStream
|
||||
MetaWaylandBuffer *buffer;
|
||||
CoglTexture2D *texture;
|
||||
gboolean is_y_inverted;
|
||||
CoglSnippet *snippet;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWaylandEglStream, meta_wayland_egl_stream,
|
||||
@ -289,18 +290,22 @@ meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream)
|
||||
}
|
||||
|
||||
CoglSnippet *
|
||||
meta_wayland_egl_stream_create_snippet (void)
|
||||
meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
if (!stream->snippet)
|
||||
{
|
||||
CoglSnippet *snippet;
|
||||
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
"uniform samplerExternalOES tex_external;",
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet,
|
||||
"cogl_texel = texture2D (tex_external,\n"
|
||||
" cogl_tex_coord.xy);");
|
||||
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
|
||||
"uniform samplerExternalOES tex_external;",
|
||||
NULL);
|
||||
cogl_snippet_set_replace (snippet,
|
||||
"cogl_texel = texture2D (tex_external,\n"
|
||||
" cogl_tex_coord.xy);");
|
||||
stream->snippet = snippet;
|
||||
}
|
||||
|
||||
return snippet;
|
||||
return cogl_object_ref (stream->snippet);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -341,6 +346,8 @@ meta_wayland_egl_stream_finalize (GObject *object)
|
||||
|
||||
meta_egl_destroy_stream (egl, egl_display, stream->egl_stream, NULL);
|
||||
|
||||
cogl_clear_object (&stream->snippet);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_egl_stream_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ gboolean meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
|
||||
|
||||
CoglTexture2D * meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
|
||||
GError **error);
|
||||
CoglSnippet * meta_wayland_egl_stream_create_snippet (void);
|
||||
CoglSnippet * meta_wayland_egl_stream_create_snippet (MetaWaylandEglStream *stream);
|
||||
|
||||
gboolean meta_wayland_egl_stream_is_y_inverted (MetaWaylandEglStream *stream);
|
||||
|
||||
|
@ -599,7 +599,6 @@ meta_wayland_keyboard_disable (MetaWaylandKeyboard *keyboard)
|
||||
|
||||
meta_wayland_keyboard_end_grab (keyboard);
|
||||
meta_wayland_keyboard_set_focus (keyboard, NULL);
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
|
||||
wl_list_remove (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
@ -913,7 +912,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
||||
keyboard_handle_focus_surface_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_keyboard_finalize (GObject *object)
|
||||
{
|
||||
MetaWaylandKeyboard *keyboard = META_WAYLAND_KEYBOARD (object);
|
||||
|
||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_keyboard_class_init (MetaWaylandKeyboardClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->finalize = meta_wayland_keyboard_finalize;
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ zxdg_toplevel_v6_set_fullscreen (struct wl_client *client,
|
||||
if (output_resource)
|
||||
{
|
||||
MetaWaylandOutput *output = wl_resource_get_user_data (output_resource);
|
||||
if (output)
|
||||
if (output && output->logical_monitor)
|
||||
meta_window_move_to_monitor (window, output->logical_monitor->number);
|
||||
}
|
||||
|
||||
|
@ -228,7 +228,8 @@ sync_focus_surface (MetaWaylandPointer *pointer)
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
|
||||
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker))
|
||||
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
|
||||
!meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker))
|
||||
{
|
||||
meta_wayland_pointer_set_focus (pointer, NULL);
|
||||
return;
|
||||
@ -433,7 +434,8 @@ default_grab_focus (MetaWaylandPointerGrab *grab,
|
||||
if (!meta_wayland_seat_has_pointer (seat))
|
||||
return;
|
||||
|
||||
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker))
|
||||
if (!meta_cursor_tracker_get_pointer_visible (cursor_tracker) &&
|
||||
!meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker))
|
||||
return;
|
||||
|
||||
if (pointer->button_count > 0)
|
||||
@ -898,7 +900,8 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
|
||||
|
||||
g_return_if_fail (meta_cursor_tracker_get_pointer_visible (cursor_tracker) ||
|
||||
surface == NULL);
|
||||
meta_cursor_tracker_get_keep_focus_while_hidden (cursor_tracker) ||
|
||||
surface == NULL);
|
||||
|
||||
if (pointer->focus_surface == surface)
|
||||
return;
|
||||
@ -1206,20 +1209,13 @@ static gboolean
|
||||
pointer_can_grab_surface (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface;
|
||||
|
||||
if (pointer->focus_surface == surface)
|
||||
return TRUE;
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = n->data;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
if (pointer_can_grab_surface (pointer, subsurface))
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -504,9 +504,17 @@ gboolean
|
||||
meta_wayland_seat_can_popup (MetaWaylandSeat *seat,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandCompositor *compositor;
|
||||
MetaWaylandTabletSeat *tablet_seat;
|
||||
|
||||
compositor = meta_wayland_compositor_get_default ();
|
||||
tablet_seat =
|
||||
meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat);
|
||||
|
||||
return (meta_wayland_pointer_can_popup (seat->pointer, serial) ||
|
||||
meta_wayland_keyboard_can_popup (seat->keyboard, serial) ||
|
||||
meta_wayland_touch_can_popup (seat->touch, serial));
|
||||
meta_wayland_touch_can_popup (seat->touch, serial) ||
|
||||
meta_wayland_tablet_seat_can_popup (tablet_seat, serial));
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -43,23 +43,17 @@ meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_su
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaRectangle geometry;
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
geometry = (MetaRectangle) {
|
||||
.width = meta_wayland_surface_get_width (surface),
|
||||
.height = meta_wayland_surface_get_height (surface),
|
||||
};
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_union_geometry (subsurface,
|
||||
0, 0,
|
||||
|
@ -85,6 +85,7 @@ sync_actor_subsurface_state (MetaWaylandSurface *surface)
|
||||
transform_subsurface_position (surface, &x, &y);
|
||||
|
||||
clutter_actor_set_position (actor, x, y);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
|
||||
if (surface->buffer_ref.buffer)
|
||||
clutter_actor_show (actor);
|
||||
@ -198,7 +199,7 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaRectangle geometry;
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
geometry = (MetaRectangle) {
|
||||
.x = surface->offset_x + surface->sub.x,
|
||||
@ -209,16 +210,10 @@ meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
|
||||
|
||||
meta_rectangle_union (out_geometry, &geometry, out_geometry);
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface = n->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_union_geometry (subsurface,
|
||||
parent_x + geometry.x,
|
||||
@ -503,7 +498,6 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
|
||||
MetaWindow *toplevel_window;
|
||||
MetaWindowActor *window_actor;
|
||||
MetaSurfaceActor *surface_actor;
|
||||
|
||||
if (surface->wl_subsurface)
|
||||
{
|
||||
@ -552,9 +546,6 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
|
||||
window_actor = meta_window_actor_wayland_from_surface (surface);
|
||||
if (window_actor)
|
||||
meta_window_actor_wayland_rebuild_surface_tree (window_actor);
|
||||
|
||||
surface_actor = meta_wayland_surface_get_actor (surface);
|
||||
clutter_actor_set_reactive (CLUTTER_ACTOR (surface_actor), TRUE);
|
||||
}
|
||||
|
||||
static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = {
|
||||
|
@ -401,7 +401,7 @@ static void
|
||||
pending_buffer_resource_destroyed (MetaWaylandBuffer *buffer,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
g_signal_handler_disconnect (buffer, pending->buffer_destroy_handler_id);
|
||||
g_clear_signal_handler (&pending->buffer_destroy_handler_id, buffer);
|
||||
pending->buffer = NULL;
|
||||
}
|
||||
|
||||
@ -632,20 +632,6 @@ meta_wayland_surface_is_effectively_synchronized (MetaWaylandSurface *surface)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
parent_surface_state_applied (GNode *subsurface_node,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaWaylandSurface *surface = subsurface_node->data;
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
if (G_NODE_IS_LEAF (subsurface_node))
|
||||
return;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (surface->role);
|
||||
meta_wayland_subsurface_parent_state_applied (subsurface);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
@ -659,6 +645,7 @@ void
|
||||
meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
gboolean had_damage = FALSE;
|
||||
|
||||
if (surface->role)
|
||||
@ -695,11 +682,9 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
if (pending->buffer)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean changed_texture;
|
||||
|
||||
if (!meta_wayland_buffer_attach (pending->buffer,
|
||||
&surface->texture,
|
||||
&changed_texture,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Could not import pending buffer: %s", error->message);
|
||||
@ -710,24 +695,6 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
g_error_free (error);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (changed_texture && meta_wayland_surface_get_actor (surface))
|
||||
{
|
||||
MetaShapedTexture *stex;
|
||||
CoglTexture *texture;
|
||||
CoglSnippet *snippet;
|
||||
gboolean is_y_inverted;
|
||||
|
||||
stex = meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface));
|
||||
texture = surface->texture;
|
||||
snippet = meta_wayland_buffer_create_snippet (pending->buffer);
|
||||
is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
|
||||
|
||||
meta_shaped_texture_set_texture (stex, texture);
|
||||
meta_shaped_texture_set_snippet (stex, snippet);
|
||||
meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
|
||||
g_clear_pointer (&snippet, cogl_object_unref);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -832,10 +799,13 @@ cleanup:
|
||||
|
||||
pending_state_reset (pending);
|
||||
|
||||
g_node_children_foreach (surface->subsurface_branch_node,
|
||||
G_TRAVERSE_ALL,
|
||||
parent_surface_state_applied,
|
||||
NULL);
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
{
|
||||
MetaWaylandSubsurface *subsurface;
|
||||
|
||||
subsurface = META_WAYLAND_SUBSURFACE (subsurface_surface->role);
|
||||
meta_wayland_subsurface_parent_state_applied (subsurface);
|
||||
}
|
||||
|
||||
if (had_damage)
|
||||
{
|
||||
@ -1276,22 +1246,14 @@ meta_wayland_surface_update_outputs (MetaWaylandSurface *surface)
|
||||
static void
|
||||
meta_wayland_surface_update_outputs_recursively (MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface_surface;
|
||||
|
||||
meta_wayland_surface_update_outputs (surface);
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
{
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
meta_wayland_surface_update_outputs_recursively (n->data);
|
||||
}
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface_surface)
|
||||
meta_wayland_surface_update_outputs_recursively (subsurface_surface);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
meta_wayland_surface_set_window (MetaWaylandSurface *surface,
|
||||
MetaWindow *window)
|
||||
@ -1647,8 +1609,8 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
||||
ClutterActor *actor =
|
||||
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
||||
ClutterVertex sv = {
|
||||
.x = sx * surface->scale,
|
||||
.y = sy * surface->scale,
|
||||
.x = sx,
|
||||
.y = sy,
|
||||
};
|
||||
ClutterVertex v = { 0 };
|
||||
|
||||
|
@ -327,4 +327,38 @@ void meta_wayland_surface_notify_geometry_changed (MetaWaylandSur
|
||||
int meta_wayland_surface_get_width (MetaWaylandSurface *surface);
|
||||
int meta_wayland_surface_get_height (MetaWaylandSurface *surface);
|
||||
|
||||
static inline GNode *
|
||||
meta_get_next_subsurface_sibling (GNode *n)
|
||||
{
|
||||
GNode *next;
|
||||
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
next = g_node_next_sibling (n);
|
||||
if (!next)
|
||||
return NULL;
|
||||
if (!G_NODE_IS_LEAF (next))
|
||||
return next;
|
||||
else
|
||||
return meta_get_next_subsurface_sibling (next);
|
||||
}
|
||||
|
||||
static inline GNode *
|
||||
meta_get_first_subsurface_node (MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
|
||||
n = g_node_first_child (surface->subsurface_branch_node);
|
||||
if (!G_NODE_IS_LEAF (n))
|
||||
return n;
|
||||
else
|
||||
return meta_get_next_subsurface_sibling (n);
|
||||
}
|
||||
|
||||
#define META_WAYLAND_SURFACE_FOREACH_SUBSURFACE(surface, subsurface) \
|
||||
for (GNode *G_PASTE(__n, __LINE__) = meta_get_first_subsurface_node ((surface)); \
|
||||
(subsurface = (G_PASTE (__n, __LINE__) ? G_PASTE (__n, __LINE__)->data : NULL)); \
|
||||
G_PASTE (__n, __LINE__) = meta_get_next_subsurface_sibling (G_PASTE (__n, __LINE__)))
|
||||
|
||||
#endif
|
||||
|
@ -552,3 +552,20 @@ meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat,
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad))
|
||||
meta_wayland_tablet_pad_set_focus (pad, surface);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat,
|
||||
uint32_t serial)
|
||||
{
|
||||
MetaWaylandTabletTool *tool;
|
||||
GHashTableIter iter;
|
||||
|
||||
g_hash_table_iter_init (&iter, tablet_seat->tools);
|
||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool))
|
||||
{
|
||||
if (meta_wayland_tablet_tool_can_popup (tool, serial))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -75,5 +75,7 @@ MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylan
|
||||
MetaWaylandTabletPad *pad);
|
||||
GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat,
|
||||
MetaWaylandTablet *tablet);
|
||||
gboolean meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat,
|
||||
uint32_t serial);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_SEAT_H */
|
||||
|
@ -989,20 +989,13 @@ static gboolean
|
||||
tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
GNode *n;
|
||||
MetaWaylandSurface *subsurface;
|
||||
|
||||
if (tool->focus_surface == surface)
|
||||
return TRUE;
|
||||
|
||||
for (n = g_node_first_child (surface->subsurface_branch_node);
|
||||
n;
|
||||
n = g_node_next_sibling (n))
|
||||
META_WAYLAND_SURFACE_FOREACH_SUBSURFACE (surface, subsurface)
|
||||
{
|
||||
MetaWaylandSurface *subsurface = n->data;
|
||||
|
||||
if (G_NODE_IS_LEAF (n))
|
||||
continue;
|
||||
|
||||
if (tablet_tool_can_grab_surface (tool, subsurface))
|
||||
return TRUE;
|
||||
}
|
||||
@ -1018,3 +1011,10 @@ meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
return ((tool->down_serial == serial || tool->button_serial == serial) &&
|
||||
tablet_tool_can_grab_surface (tool, surface));
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool,
|
||||
uint32_t serial)
|
||||
{
|
||||
return tool->down_serial == serial || tool->button_serial == serial;
|
||||
}
|
||||
|
@ -85,5 +85,7 @@ void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *t
|
||||
gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool,
|
||||
MetaWaylandSurface *surface,
|
||||
uint32_t serial);
|
||||
gboolean meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool,
|
||||
uint32_t serial);
|
||||
|
||||
#endif /* META_WAYLAND_TABLET_TOOL_H */
|
||||
|
@ -431,7 +431,7 @@ xdg_toplevel_set_fullscreen (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandOutput *output = wl_resource_get_user_data (output_resource);
|
||||
|
||||
if (output)
|
||||
if (output && output->logical_monitor)
|
||||
{
|
||||
meta_window_move_to_monitor (window,
|
||||
output->logical_monitor->number);
|
||||
|
@ -562,7 +562,7 @@ meta_xwayland_data_source_fetch_mimetype_list (MetaWaylandDataSource *source,
|
||||
XGetWindowProperty (xdisplay, window, prop,
|
||||
0, /* offset */
|
||||
0x1fffffff, /* length */
|
||||
True, /* delete */
|
||||
False, /* delete */
|
||||
AnyPropertyType,
|
||||
&type_ret,
|
||||
&format_ret,
|
||||
@ -787,6 +787,10 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
xdnd_atoms[ATOM_DND_TYPE_LIST]);
|
||||
}
|
||||
|
||||
meta_wayland_data_source_set_actions (dnd->source,
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
|
||||
WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK);
|
||||
meta_wayland_drag_grab_set_focus (drag_grab, dnd->focus_surface);
|
||||
return TRUE;
|
||||
}
|
||||
@ -806,7 +810,7 @@ meta_xwayland_dnd_handle_client_message (MetaWaylandCompositor *compositor,
|
||||
clutter_event_set_time (motion, dnd->last_motion_time);
|
||||
|
||||
action = atom_to_action ((Atom) event->data.l[4]);
|
||||
meta_wayland_data_source_set_actions (dnd->source, action);
|
||||
meta_wayland_data_source_set_user_action (dnd->source, action);
|
||||
|
||||
meta_wayland_surface_drag_dest_motion (drag_focus, motion);
|
||||
xdnd_send_status (dnd, (Window) event->data.l[0],
|
||||
|
@ -1734,11 +1734,21 @@ process_selection_event (MetaX11Display *x11_display,
|
||||
|
||||
handled |= meta_x11_selection_handle_event (x11_display, event);
|
||||
|
||||
for (l = x11_display->selection.input_streams; l && !handled; l = l->next)
|
||||
handled |= meta_x11_selection_input_stream_xevent (l->data, event);
|
||||
for (l = x11_display->selection.input_streams; l && !handled;)
|
||||
{
|
||||
GList *next = l->next;
|
||||
|
||||
for (l = x11_display->selection.output_streams; l && !handled; l = l->next)
|
||||
handled |= meta_x11_selection_output_stream_xevent (l->data, event);
|
||||
handled |= meta_x11_selection_input_stream_xevent (l->data, event);
|
||||
l = next;
|
||||
}
|
||||
|
||||
for (l = x11_display->selection.output_streams; l && !handled;)
|
||||
{
|
||||
GList *next = l->next;
|
||||
|
||||
handled |= meta_x11_selection_output_stream_xevent (l->data, event);
|
||||
l = next;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
@ -1928,10 +1928,15 @@ meta_x11_display_set_input_focus_xwindow (MetaX11Display *x11_display,
|
||||
{
|
||||
gulong serial;
|
||||
|
||||
meta_display_unset_input_focus (x11_display->display, timestamp);
|
||||
if (meta_display_timestamp_too_old (x11_display->display, ×tamp))
|
||||
return;
|
||||
|
||||
serial = XNextRequest (x11_display->xdisplay);
|
||||
meta_x11_display_set_input_focus_internal (x11_display, window, timestamp);
|
||||
meta_x11_display_update_focus_window (x11_display, window, serial, TRUE);
|
||||
meta_display_update_focus_window (x11_display->display, NULL);
|
||||
meta_display_remove_autoraise_callback (x11_display->display);
|
||||
x11_display->display->last_focus_time = timestamp;
|
||||
}
|
||||
|
||||
static MetaX11DisplayLogicalMonitorData *
|
||||
|
@ -261,6 +261,20 @@ meta_x11_selection_input_stream_close_finish (GInputStream *stream,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_input_stream_dispose (GObject *object)
|
||||
{
|
||||
MetaX11SelectionInputStream *stream =
|
||||
META_X11_SELECTION_INPUT_STREAM (object);
|
||||
MetaX11SelectionInputStreamPrivate *priv =
|
||||
meta_x11_selection_input_stream_get_instance_private (stream);
|
||||
|
||||
priv->x11_display->selection.input_streams =
|
||||
g_list_remove (priv->x11_display->selection.input_streams, stream);
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_selection_input_stream_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_input_stream_finalize (GObject *object)
|
||||
{
|
||||
@ -284,6 +298,7 @@ meta_x11_selection_input_stream_class_init (MetaX11SelectionInputStreamClass *kl
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GInputStreamClass *istream_class = G_INPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_x11_selection_input_stream_dispose;
|
||||
object_class->finalize = meta_x11_selection_input_stream_finalize;
|
||||
|
||||
istream_class->read_fn = meta_x11_selection_input_stream_read;
|
||||
|
@ -57,12 +57,15 @@ struct _MetaX11SelectionOutputStreamPrivate
|
||||
|
||||
guint incr : 1;
|
||||
guint delete_pending : 1;
|
||||
guint pipe_error : 1;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaX11SelectionOutputStream,
|
||||
meta_x11_selection_output_stream,
|
||||
G_TYPE_OUTPUT_STREAM);
|
||||
|
||||
static size_t get_element_size (int format);
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_notify_selection (MetaX11SelectionOutputStream *stream)
|
||||
{
|
||||
@ -100,6 +103,9 @@ meta_x11_selection_output_stream_can_flush (MetaX11SelectionOutputStream *stream
|
||||
|
||||
if (priv->delete_pending)
|
||||
return FALSE;
|
||||
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)) &&
|
||||
priv->data->len < get_element_size (priv->format))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -113,7 +119,7 @@ get_max_request_size (MetaX11Display *display)
|
||||
if (size <= 0)
|
||||
size = XMaxRequestSize (display->xdisplay);
|
||||
|
||||
return size - 100;
|
||||
return (size - 100) * 4;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -123,7 +129,12 @@ meta_x11_selection_output_stream_needs_flush_unlocked (MetaX11SelectionOutputStr
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (priv->data->len == 0)
|
||||
return FALSE;
|
||||
{
|
||||
if (priv->incr)
|
||||
return g_output_stream_is_closing (G_OUTPUT_STREAM (stream));
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||
return TRUE;
|
||||
@ -171,13 +182,34 @@ get_element_size (int format)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_x11_selection_output_stream_check_pipe (MetaX11SelectionOutputStream *stream,
|
||||
GError **error)
|
||||
{
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (priv->pipe_error)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_BROKEN_PIPE,
|
||||
"Connection with client was broken");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *stream)
|
||||
{
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
Display *xdisplay;
|
||||
size_t element_size, n_elements;
|
||||
size_t element_size, n_elements, max_size;
|
||||
gboolean first_chunk = FALSE;
|
||||
int error_code;
|
||||
|
||||
g_assert (!priv->delete_pending);
|
||||
|
||||
@ -190,8 +222,12 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
|
||||
element_size = get_element_size (priv->format);
|
||||
n_elements = priv->data->len / element_size;
|
||||
max_size = get_max_request_size (priv->x11_display);
|
||||
|
||||
if (!g_output_stream_is_closing (G_OUTPUT_STREAM (stream)))
|
||||
if (!priv->incr)
|
||||
first_chunk = TRUE;
|
||||
|
||||
if (!priv->incr && priv->data->len > max_size)
|
||||
{
|
||||
XWindowAttributes attrs;
|
||||
|
||||
@ -207,14 +243,22 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
XChangeProperty (xdisplay,
|
||||
priv->xwindow,
|
||||
priv->xproperty,
|
||||
XInternAtom (priv->x11_display->xdisplay, "INCR", True),
|
||||
XInternAtom (priv->x11_display->xdisplay, "INCR", False),
|
||||
32,
|
||||
PropModeReplace,
|
||||
(guchar *) &(long) { n_elements },
|
||||
1);
|
||||
priv->delete_pending = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t copy_n_elements;
|
||||
|
||||
if (priv->incr && priv->data->len > 0)
|
||||
priv->delete_pending = TRUE;
|
||||
|
||||
copy_n_elements = MIN (n_elements, max_size / element_size);
|
||||
|
||||
XChangeProperty (xdisplay,
|
||||
priv->xwindow,
|
||||
priv->xproperty,
|
||||
@ -222,30 +266,45 @@ meta_x11_selection_output_stream_perform_flush (MetaX11SelectionOutputStream *st
|
||||
priv->format,
|
||||
PropModeReplace,
|
||||
priv->data->data,
|
||||
n_elements);
|
||||
g_byte_array_remove_range (priv->data, 0, n_elements * element_size);
|
||||
if (priv->data->len < element_size)
|
||||
priv->flush_requested = FALSE;
|
||||
copy_n_elements);
|
||||
g_byte_array_remove_range (priv->data, 0, copy_n_elements * element_size);
|
||||
}
|
||||
|
||||
meta_x11_selection_output_stream_notify_selection (stream);
|
||||
if (first_chunk)
|
||||
meta_x11_selection_output_stream_notify_selection (stream);
|
||||
|
||||
priv->delete_pending = TRUE;
|
||||
g_cond_broadcast (&priv->cond);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
|
||||
/* XXX: handle failure here and report EPIPE for future operations on the stream? */
|
||||
if (meta_x11_error_trap_pop_with_return (priv->x11_display))
|
||||
g_warning ("Failed to flush selection output stream");
|
||||
error_code = meta_x11_error_trap_pop_with_return (priv->x11_display);
|
||||
|
||||
if (priv->pending_task)
|
||||
if (error_code != Success)
|
||||
{
|
||||
char error_str[100];
|
||||
|
||||
priv->flush_requested = FALSE;
|
||||
priv->delete_pending = FALSE;
|
||||
priv->pipe_error = TRUE;
|
||||
|
||||
if (priv->pending_task)
|
||||
{
|
||||
XGetErrorText (xdisplay, error_code, error_str, sizeof (error_str));
|
||||
g_task_return_new_error (priv->pending_task,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_BROKEN_PIPE,
|
||||
"Failed to flush selection output stream: %s",
|
||||
error_str);
|
||||
g_clear_object (&priv->pending_task);
|
||||
}
|
||||
}
|
||||
else if (priv->pending_task && priv->data->len == 0 && !priv->delete_pending)
|
||||
{
|
||||
size_t result;
|
||||
|
||||
priv->flush_requested = FALSE;
|
||||
result = GPOINTER_TO_SIZE (g_task_get_task_data (priv->pending_task));
|
||||
g_task_return_int (priv->pending_task, result);
|
||||
g_object_unref (priv->pending_task);
|
||||
priv->pending_task = NULL;
|
||||
g_clear_object (&priv->pending_task);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,12 +313,17 @@ meta_x11_selection_output_stream_invoke_flush (gpointer data)
|
||||
{
|
||||
MetaX11SelectionOutputStream *stream =
|
||||
META_X11_SELECTION_OUTPUT_STREAM (data);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (meta_x11_selection_output_stream_needs_flush (stream) &&
|
||||
meta_x11_selection_output_stream_can_flush (stream))
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
if (priv->delete_pending || priv->data->len > 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
else
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static gssize
|
||||
@ -274,6 +338,9 @@ meta_x11_selection_output_stream_write (GOutputStream *output_stream,
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
||||
return -1;
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
g_byte_array_append (priv->data, buffer, count);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
@ -301,12 +368,19 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
||||
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, meta_x11_selection_output_stream_write_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
g_byte_array_append (priv->data, buffer, count);
|
||||
g_mutex_unlock (&priv->mutex);
|
||||
@ -317,16 +391,11 @@ meta_x11_selection_output_stream_write_async (GOutputStream *output_stream
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
else if (!meta_x11_selection_output_stream_can_flush (stream))
|
||||
{
|
||||
g_assert (priv->pending_task == NULL);
|
||||
priv->pending_task = task;
|
||||
g_task_set_task_data (task, GSIZE_TO_POINTER (count), NULL);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
if (meta_x11_selection_output_stream_can_flush (stream))
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
|
||||
g_task_return_int (task, count);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
@ -354,7 +423,7 @@ meta_x11_selection_output_request_flush (MetaX11SelectionOutputStream *stream)
|
||||
|
||||
g_mutex_lock (&priv->mutex);
|
||||
|
||||
if (priv->data->len >= get_element_size (priv->format))
|
||||
if (priv->data->len > 0)
|
||||
priv->flush_requested = TRUE;
|
||||
|
||||
needs_flush = meta_x11_selection_output_stream_needs_flush_unlocked (stream);
|
||||
@ -373,6 +442,8 @@ meta_x11_selection_output_stream_flush (GOutputStream *output_stream,
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, error))
|
||||
return FALSE;
|
||||
if (!meta_x11_selection_output_request_flush (stream))
|
||||
return TRUE;
|
||||
|
||||
@ -398,12 +469,19 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
||||
META_X11_SELECTION_OUTPUT_STREAM (output_stream);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
GError *error = NULL;
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (stream, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, meta_x11_selection_output_stream_flush_async);
|
||||
g_task_set_priority (task, io_priority);
|
||||
|
||||
if (!meta_x11_selection_output_stream_check_pipe (stream, &error))
|
||||
{
|
||||
g_task_return_error (task, error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!meta_x11_selection_output_stream_can_flush (stream))
|
||||
{
|
||||
if (meta_x11_selection_output_request_flush (stream))
|
||||
@ -420,10 +498,9 @@ meta_x11_selection_output_stream_flush_async (GOutputStream *output_stream
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (priv->pending_task == NULL);
|
||||
priv->pending_task = task;
|
||||
meta_x11_selection_output_stream_perform_flush (stream);
|
||||
g_task_return_boolean (task, TRUE);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -489,6 +566,20 @@ meta_x11_selection_output_stream_close_finish (GOutputStream *stream,
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_dispose (GObject *object)
|
||||
{
|
||||
MetaX11SelectionOutputStream *stream =
|
||||
META_X11_SELECTION_OUTPUT_STREAM (object);
|
||||
MetaX11SelectionOutputStreamPrivate *priv =
|
||||
meta_x11_selection_output_stream_get_instance_private (stream);
|
||||
|
||||
priv->x11_display->selection.output_streams =
|
||||
g_list_remove (priv->x11_display->selection.output_streams, stream);
|
||||
|
||||
G_OBJECT_CLASS (meta_x11_selection_output_stream_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_x11_selection_output_stream_finalize (GObject *object)
|
||||
{
|
||||
@ -514,6 +605,7 @@ meta_x11_selection_output_stream_class_init (MetaX11SelectionOutputStreamClass *
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GOutputStreamClass *output_stream_class = G_OUTPUT_STREAM_CLASS (klass);
|
||||
|
||||
object_class->dispose = meta_x11_selection_output_stream_dispose;
|
||||
object_class->finalize = meta_x11_selection_output_stream_finalize;
|
||||
|
||||
output_stream_class->write_fn = meta_x11_selection_output_stream_write;
|
||||
|
@ -23,10 +23,22 @@
|
||||
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
#include "core/meta-selection-private.h"
|
||||
#include "meta/meta-selection-source-memory.h"
|
||||
#include "x11/meta-selection-source-x11-private.h"
|
||||
#include "x11/meta-x11-selection-output-stream-private.h"
|
||||
#include "x11/meta-x11-selection-private.h"
|
||||
|
||||
#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8"
|
||||
#define STRING_MIMETYPE "text/plain"
|
||||
|
||||
/* Set an arbitrary (although generous) threshold to determine whether a
|
||||
* XFixesSelectionNotify corresponds to a XSetSelectionOwner from another
|
||||
* client. The selection timestamp is not updated if the owner client is
|
||||
* closed.
|
||||
*/
|
||||
#define SELECTION_CLEARED_BY_CLIENT(e) (e->timestamp - e->selection_timestamp < 50)
|
||||
|
||||
static gboolean
|
||||
atom_to_selection_type (Display *xdisplay,
|
||||
Atom selection,
|
||||
@ -141,6 +153,45 @@ transfer_cb (MetaSelection *selection,
|
||||
g_object_unref (output);
|
||||
}
|
||||
|
||||
static char *
|
||||
meta_x11_selection_find_target (MetaX11Display *x11_display,
|
||||
MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
Atom selection_atom)
|
||||
{
|
||||
GList* mimetypes = NULL;
|
||||
const gchar *atom_name;
|
||||
char *retval;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (selection, selection_type);
|
||||
atom_name = gdk_x11_get_xatom_name (selection_atom);
|
||||
|
||||
if (g_list_find_custom (mimetypes, atom_name, (GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (atom_name);
|
||||
}
|
||||
else if (strcmp (atom_name, "UTF8_STRING") == 0 &&
|
||||
g_list_find_custom (mimetypes, UTF8_STRING_MIMETYPE,
|
||||
(GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (UTF8_STRING_MIMETYPE);
|
||||
}
|
||||
else if (strcmp (atom_name, "STRING") == 0 &&
|
||||
g_list_find_custom (mimetypes, STRING_MIMETYPE,
|
||||
(GCompareFunc) g_strcmp0))
|
||||
{
|
||||
retval = g_strdup (STRING_MIMETYPE);
|
||||
}
|
||||
else
|
||||
{
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
XEvent *xevent)
|
||||
@ -197,15 +248,12 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean has_target;
|
||||
g_autofree char *target = NULL;
|
||||
|
||||
mimetypes = meta_selection_get_mimetypes (selection, selection_type);
|
||||
has_target = g_list_find_custom (mimetypes,
|
||||
gdk_x11_get_xatom_name (event->target),
|
||||
(GCompareFunc) g_strcmp0) != NULL;
|
||||
g_list_free_full (mimetypes, g_free);
|
||||
target = meta_x11_selection_find_target (x11_display, selection,
|
||||
selection_type, event->target);
|
||||
|
||||
if (has_target)
|
||||
if (target != NULL)
|
||||
{
|
||||
output = meta_x11_selection_output_stream_new (x11_display,
|
||||
event->requestor,
|
||||
@ -217,7 +265,7 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
|
||||
meta_selection_transfer_async (selection,
|
||||
selection_type,
|
||||
gdk_x11_get_xatom_name (event->target),
|
||||
target,
|
||||
-1,
|
||||
output,
|
||||
NULL,
|
||||
@ -226,7 +274,9 @@ meta_x11_selection_handle_selection_request (MetaX11Display *x11_display,
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
send_selection_notify (event, FALSE);
|
||||
{
|
||||
send_selection_notify (event, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@ -254,8 +304,9 @@ source_new_cb (GObject *object,
|
||||
source = meta_selection_source_x11_new_finish (res, &error);
|
||||
if (source)
|
||||
{
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_object_unref (source);
|
||||
}
|
||||
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
{
|
||||
@ -288,16 +339,27 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
|
||||
|
||||
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
|
||||
|
||||
if (event->owner == None)
|
||||
if (event->owner == None && x11_display->selection.owners[selection_type])
|
||||
{
|
||||
if (x11_display->selection.owners[selection_type])
|
||||
if (SELECTION_CLEARED_BY_CLIENT (event))
|
||||
{
|
||||
MetaSelectionSource *source;
|
||||
|
||||
/* Replace with an empty owner */
|
||||
source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
|
||||
g_set_object (&x11_display->selection.owners[selection_type], source);
|
||||
meta_selection_set_owner (selection, selection_type, source);
|
||||
g_object_unref (source);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* An X client went away, clear the selection */
|
||||
meta_selection_unset_owner (selection, selection_type,
|
||||
x11_display->selection.owners[selection_type]);
|
||||
g_clear_object (&x11_display->selection.owners[selection_type]);
|
||||
}
|
||||
}
|
||||
else if (event->owner != x11_display->selection.xwindow)
|
||||
else if (event->owner != None && event->owner != x11_display->selection.xwindow)
|
||||
{
|
||||
SourceNewData *data;
|
||||
|
||||
@ -331,14 +393,13 @@ meta_x11_selection_handle_event (MetaX11Display *x11_display,
|
||||
}
|
||||
|
||||
static void
|
||||
owner_changed_cb (MetaSelection *selection,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner,
|
||||
MetaX11Display *x11_display)
|
||||
notify_selection_owner (MetaX11Display *x11_display,
|
||||
MetaSelectionType selection_type,
|
||||
MetaSelectionSource *new_owner)
|
||||
{
|
||||
Display *xdisplay = x11_display->xdisplay;
|
||||
|
||||
if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner))
|
||||
if (new_owner && new_owner != x11_display->selection.owners[selection_type])
|
||||
{
|
||||
if (x11_display->selection.cancellables[selection_type])
|
||||
{
|
||||
@ -361,6 +422,7 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
||||
{
|
||||
XSetWindowAttributes attributes = { 0 };
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
MetaSelection *selection;
|
||||
guint mask, i;
|
||||
|
||||
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
|
||||
@ -381,18 +443,24 @@ meta_x11_selection_init (MetaX11Display *x11_display)
|
||||
XFixesSelectionWindowDestroyNotifyMask |
|
||||
XFixesSelectionClientCloseNotifyMask;
|
||||
|
||||
selection = meta_display_get_selection (display);
|
||||
|
||||
for (i = 0; i < META_N_SELECTION_TYPES; i++)
|
||||
{
|
||||
MetaSelectionSource *owner;
|
||||
|
||||
XFixesSelectSelectionInput (x11_display->xdisplay,
|
||||
x11_display->selection.xwindow,
|
||||
selection_to_atom (i, x11_display->xdisplay),
|
||||
mask);
|
||||
owner = meta_selection_get_current_owner (selection, i);
|
||||
notify_selection_owner (x11_display, i, owner);
|
||||
}
|
||||
|
||||
g_signal_connect (meta_display_get_selection (display),
|
||||
"owner-changed",
|
||||
G_CALLBACK (owner_changed_cb),
|
||||
x11_display);
|
||||
g_signal_connect_swapped (selection,
|
||||
"owner-changed",
|
||||
G_CALLBACK (notify_selection_owner),
|
||||
x11_display);
|
||||
}
|
||||
|
||||
void
|
||||
@ -401,7 +469,7 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display)
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
|
||||
g_signal_handlers_disconnect_by_func (meta_display_get_selection (display),
|
||||
owner_changed_cb,
|
||||
notify_selection_owner,
|
||||
x11_display);
|
||||
if (x11_display->selection.xwindow != None)
|
||||
{
|
||||
|
@ -1625,6 +1625,22 @@ reload_wm_hints (MetaWindow *window,
|
||||
meta_window_queue (window, META_QUEUE_UPDATE_ICON | META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_xtransient_for_loop (MetaWindow *window,
|
||||
MetaWindow *parent)
|
||||
{
|
||||
while (parent)
|
||||
{
|
||||
if (parent == window)
|
||||
return TRUE;
|
||||
|
||||
parent = meta_x11_display_lookup_x_window (parent->display->x11_display,
|
||||
parent->xtransient_for);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_transient_for (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
@ -1645,20 +1661,22 @@ reload_transient_for (MetaWindow *window,
|
||||
transient_for, window->desc);
|
||||
transient_for = None;
|
||||
}
|
||||
else if (parent->override_redirect)
|
||||
{
|
||||
meta_warning ("WM_TRANSIENT_FOR window %s for top-level %s is an "
|
||||
"override-redirect window and this is not correct "
|
||||
"according to the standard, so we'll fallback to "
|
||||
"the root window.\n", parent->desc, window->desc);
|
||||
transient_for = parent->display->x11_display->xroot;
|
||||
parent = NULL;
|
||||
}
|
||||
|
||||
/* Make sure there is not a loop */
|
||||
while (parent)
|
||||
if (check_xtransient_for_loop (window, parent))
|
||||
{
|
||||
if (parent == window)
|
||||
{
|
||||
meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n",
|
||||
transient_for, window->desc);
|
||||
transient_for = None;
|
||||
break;
|
||||
}
|
||||
|
||||
parent = meta_x11_display_lookup_x_window (parent->display->x11_display,
|
||||
parent->xtransient_for);
|
||||
meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create a "
|
||||
"loop.\n", transient_for, window->desc);
|
||||
transient_for = None;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1679,8 +1697,6 @@ reload_transient_for (MetaWindow *window,
|
||||
meta_window_set_transient_for (window, NULL);
|
||||
else
|
||||
{
|
||||
parent = meta_x11_display_lookup_x_window (window->display->x11_display,
|
||||
window->xtransient_for);
|
||||
meta_window_set_transient_for (window, parent);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user