Compare commits
58 Commits
3.28.3
...
cherry-pic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce808f6792 | ||
|
|
00cd99c3a7 | ||
|
|
8ddbe9d98b | ||
|
|
a22cb8832d | ||
|
|
082efaca96 | ||
|
|
80f942773a | ||
|
|
b5c2555601 | ||
|
|
0a85e6272e | ||
|
|
4dfe4256ae | ||
|
|
998e3279c2 | ||
|
|
1514880e92 | ||
|
|
6ed36cd6e3 | ||
|
|
49c06fd9b1 | ||
|
|
f7658ac5f0 | ||
|
|
037d9915d5 | ||
|
|
075bfc4e11 | ||
|
|
02e80af200 | ||
|
|
398f03bd0f | ||
|
|
d81dcd13e4 | ||
|
|
5d0365991f | ||
|
|
03dfcbab67 | ||
|
|
47505dc5f6 | ||
|
|
9d88fc8cb7 | ||
|
|
17ae09ad3f | ||
|
|
4ca83f3c47 | ||
|
|
b44f93ee9b | ||
|
|
59d2d5ef3b | ||
|
|
53b040be5c | ||
|
|
c647bd7807 | ||
|
|
9ac07b4005 | ||
|
|
527f6ef835 | ||
|
|
0b666dbeb2 | ||
|
|
24b87b364d | ||
|
|
15f01174ff | ||
|
|
f45af3315d | ||
|
|
007864ac64 | ||
|
|
f76cacd154 | ||
|
|
abe682efa0 | ||
|
|
83b7b17b64 | ||
|
|
30266605b5 | ||
|
|
2e0d758811 | ||
|
|
aa6d1614c0 | ||
|
|
255146e4a3 | ||
|
|
2ad5a39bd0 | ||
|
|
ce3278b4b7 | ||
|
|
0d134522d8 | ||
|
|
f4a7620dff | ||
|
|
a41ae88c09 | ||
|
|
1276cc97d1 | ||
|
|
5b9f5329bd | ||
|
|
d0d8078013 | ||
|
|
0a09a3c906 | ||
|
|
137f22236c | ||
|
|
513cc535f3 | ||
|
|
d74a046060 | ||
|
|
0c5e61a2ab | ||
|
|
44682a2cc5 | ||
|
|
62660bbd15 |
@@ -214,6 +214,8 @@ cally_util_simulate_snooper_install (void)
|
||||
G_CALLBACK (cally_util_stage_added_cb), cally_key_snooper);
|
||||
g_signal_connect (G_OBJECT (stage_manager), "stage-removed",
|
||||
G_CALLBACK (cally_util_stage_removed_cb), cally_key_snooper);
|
||||
|
||||
g_slist_free (stage_list);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -840,6 +840,8 @@ struct _ClutterActorPrivate
|
||||
guint needs_compute_expand : 1;
|
||||
guint needs_x_expand : 1;
|
||||
guint needs_y_expand : 1;
|
||||
guint needs_paint_volume_update : 1;
|
||||
guint had_effects_on_last_paint_volume_update : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -1092,6 +1094,11 @@ static void clutter_actor_set_child_transform_internal (ClutterActor *sel
|
||||
static void clutter_actor_realize_internal (ClutterActor *self);
|
||||
static void clutter_actor_unrealize_internal (ClutterActor *self);
|
||||
|
||||
static void clutter_actor_push_in_cloned_branch (ClutterActor *self,
|
||||
gulong count);
|
||||
static void clutter_actor_pop_in_cloned_branch (ClutterActor *self,
|
||||
gulong count);
|
||||
|
||||
/* Helper macro which translates by the anchor coord, applies the
|
||||
given transformation and then translates back */
|
||||
#define TRANSFORM_ABOUT_ANCHOR_COORD(a,m,c,_transform) G_STMT_START { \
|
||||
@@ -1504,6 +1511,8 @@ clutter_actor_real_map (ClutterActor *self)
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_MAPPED);
|
||||
|
||||
self->priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
stage = _clutter_actor_get_stage_internal (self);
|
||||
priv->pick_id = _clutter_stage_acquire_pick_id (CLUTTER_STAGE (stage), self);
|
||||
|
||||
@@ -2737,6 +2746,7 @@ clutter_actor_real_queue_relayout (ClutterActor *self)
|
||||
priv->needs_width_request = TRUE;
|
||||
priv->needs_height_request = TRUE;
|
||||
priv->needs_allocation = TRUE;
|
||||
priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
/* reset the cached size requests */
|
||||
memset (priv->width_requests, 0,
|
||||
@@ -2821,7 +2831,7 @@ _clutter_actor_fully_transform_vertices (ClutterActor *self,
|
||||
/* Note: we pass NULL as the ancestor because we don't just want the modelview
|
||||
* that gets us to stage coordinates, we want to go all the way to eye
|
||||
* coordinates */
|
||||
_clutter_actor_apply_relative_transformation_matrix (self, NULL, &modelview);
|
||||
_clutter_actor_get_relative_transformation_matrix (self, NULL, &modelview);
|
||||
|
||||
/* Fetch the projection and viewport */
|
||||
_clutter_stage_get_projection_matrix (CLUTTER_STAGE (stage), &projection);
|
||||
@@ -4285,6 +4295,9 @@ clutter_actor_remove_child_internal (ClutterActor *self,
|
||||
|
||||
self->priv->age += 1;
|
||||
|
||||
if (self->priv->in_cloned_branch)
|
||||
clutter_actor_pop_in_cloned_branch (child, self->priv->in_cloned_branch);
|
||||
|
||||
/* if the child that got removed was visible and set to
|
||||
* expand then we want to reset the parent's state in
|
||||
* case the child was the only thing that was making it
|
||||
@@ -8518,6 +8531,7 @@ clutter_actor_init (ClutterActor *self)
|
||||
priv->needs_width_request = TRUE;
|
||||
priv->needs_height_request = TRUE;
|
||||
priv->needs_allocation = TRUE;
|
||||
priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
priv->cached_width_age = 1;
|
||||
priv->cached_height_age = 1;
|
||||
@@ -10084,6 +10098,9 @@ clutter_actor_allocate (ClutterActor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
if (CLUTTER_ACTOR_IS_MAPPED (self))
|
||||
self->priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
if (!stage_allocation_changed)
|
||||
{
|
||||
/* If the actor didn't move but needs_allocation is set, we just
|
||||
@@ -12902,6 +12919,9 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
|
||||
self->priv->age += 1;
|
||||
|
||||
if (self->priv->in_cloned_branch)
|
||||
clutter_actor_push_in_cloned_branch (child, self->priv->in_cloned_branch);
|
||||
|
||||
/* if push_internal() has been called then we automatically set
|
||||
* the flag on the actor
|
||||
*/
|
||||
@@ -12972,6 +12992,9 @@ clutter_actor_add_child_internal (ClutterActor *self,
|
||||
child->priv->needs_height_request = TRUE;
|
||||
child->priv->needs_allocation = TRUE;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_MAPPED (child))
|
||||
child->priv->needs_paint_volume_update = TRUE;
|
||||
|
||||
/* we only queue a relayout here, because any possible
|
||||
* redraw has already been queued either by show() or
|
||||
* by our call to queue_redraw() above
|
||||
@@ -17463,7 +17486,7 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self,
|
||||
*/
|
||||
effects = _clutter_meta_group_peek_metas (priv->effects);
|
||||
for (l = effects;
|
||||
l != NULL || (l != NULL && l->data != priv->current_effect);
|
||||
l != NULL && l->data != priv->current_effect;
|
||||
l = l->next)
|
||||
{
|
||||
if (!_clutter_effect_get_paint_volume (l->data, pv))
|
||||
@@ -17499,6 +17522,32 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_clutter_actor_has_active_paint_volume_override_effects (ClutterActor *self)
|
||||
{
|
||||
const GList *l;
|
||||
|
||||
if (self->priv->effects == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* We just need to all effects current effect to see
|
||||
* if anyone wants to override the paint volume. If so, then
|
||||
* we need to recompute, since the paint volume returned can
|
||||
* change from call to call. */
|
||||
for (l = _clutter_meta_group_peek_metas (self->priv->effects);
|
||||
l != NULL;
|
||||
l = l->next)
|
||||
{
|
||||
ClutterEffect *effect = l->data;
|
||||
|
||||
if (clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect)) &&
|
||||
_clutter_effect_has_custom_paint_volume (effect))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The public clutter_actor_get_paint_volume API returns a const
|
||||
* pointer since we return a pointer directly to the cached
|
||||
* PaintVolume associated with the actor and don't want the user to
|
||||
@@ -17509,16 +17558,37 @@ _clutter_actor_get_paint_volume_real (ClutterActor *self,
|
||||
static ClutterPaintVolume *
|
||||
_clutter_actor_get_paint_volume_mutable (ClutterActor *self)
|
||||
{
|
||||
gboolean has_paint_volume_override_effects;
|
||||
ClutterActorPrivate *priv;
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
has_paint_volume_override_effects = _clutter_actor_has_active_paint_volume_override_effects (self);
|
||||
|
||||
if (priv->paint_volume_valid)
|
||||
clutter_paint_volume_free (&priv->paint_volume);
|
||||
{
|
||||
/* If effects are applied, the actor paint volume
|
||||
* needs to be recomputed on each paint, since those
|
||||
* paint volumes could change over the duration of the
|
||||
* effect.
|
||||
*
|
||||
* We also need to update the paint volume if we went
|
||||
* from having effects to not having effects on the last
|
||||
* paint volume update. */
|
||||
if (!priv->needs_paint_volume_update &&
|
||||
priv->current_effect == NULL &&
|
||||
!has_paint_volume_override_effects &&
|
||||
!priv->had_effects_on_last_paint_volume_update)
|
||||
return &priv->paint_volume;
|
||||
clutter_paint_volume_free (&priv->paint_volume);
|
||||
}
|
||||
|
||||
priv->had_effects_on_last_paint_volume_update = has_paint_volume_override_effects;
|
||||
|
||||
if (_clutter_actor_get_paint_volume_real (self, &priv->paint_volume))
|
||||
{
|
||||
priv->paint_volume_valid = TRUE;
|
||||
priv->needs_paint_volume_update = FALSE;
|
||||
return &priv->paint_volume;
|
||||
}
|
||||
else
|
||||
@@ -20688,29 +20758,31 @@ clutter_actor_get_child_transform (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_push_in_cloned_branch (ClutterActor *self)
|
||||
clutter_actor_push_in_cloned_branch (ClutterActor *self,
|
||||
gulong count)
|
||||
{
|
||||
ClutterActor *iter;
|
||||
|
||||
for (iter = self->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
clutter_actor_push_in_cloned_branch (iter);
|
||||
clutter_actor_push_in_cloned_branch (iter, count);
|
||||
|
||||
self->priv->in_cloned_branch += 1;
|
||||
self->priv->in_cloned_branch += count;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_pop_in_cloned_branch (ClutterActor *self)
|
||||
clutter_actor_pop_in_cloned_branch (ClutterActor *self,
|
||||
gulong count)
|
||||
{
|
||||
ClutterActor *iter;
|
||||
|
||||
self->priv->in_cloned_branch -= 1;
|
||||
self->priv->in_cloned_branch -= count;
|
||||
|
||||
for (iter = self->priv->first_child;
|
||||
iter != NULL;
|
||||
iter = iter->priv->next_sibling)
|
||||
clutter_actor_pop_in_cloned_branch (iter);
|
||||
clutter_actor_pop_in_cloned_branch (iter, count);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -20726,7 +20798,7 @@ _clutter_actor_attach_clone (ClutterActor *actor,
|
||||
|
||||
g_hash_table_add (priv->clones, clone);
|
||||
|
||||
clutter_actor_push_in_cloned_branch (actor);
|
||||
clutter_actor_push_in_cloned_branch (actor, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -20741,7 +20813,7 @@ _clutter_actor_detach_clone (ClutterActor *actor,
|
||||
g_hash_table_lookup (priv->clones, clone) == NULL)
|
||||
return;
|
||||
|
||||
clutter_actor_pop_in_cloned_branch (actor);
|
||||
clutter_actor_pop_in_cloned_branch (actor, 1);
|
||||
|
||||
g_hash_table_remove (priv->clones, clone);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ gboolean _clutter_effect_pre_paint (ClutterEffect
|
||||
void _clutter_effect_post_paint (ClutterEffect *effect);
|
||||
gboolean _clutter_effect_get_paint_volume (ClutterEffect *effect,
|
||||
ClutterPaintVolume *volume);
|
||||
gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect *effect);
|
||||
void _clutter_effect_paint (ClutterEffect *effect,
|
||||
ClutterEffectPaintFlags flags);
|
||||
void _clutter_effect_pick (ClutterEffect *effect,
|
||||
|
||||
@@ -308,6 +308,14 @@ _clutter_effect_get_paint_volume (ClutterEffect *effect,
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume (effect, volume);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_effect_has_custom_paint_volume (ClutterEffect *effect)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_EFFECT (effect), FALSE);
|
||||
|
||||
return CLUTTER_EFFECT_GET_CLASS (effect)->get_paint_volume != clutter_effect_real_get_paint_volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_effect_queue_repaint:
|
||||
* @effect: A #ClutterEffect which needs redrawing
|
||||
|
||||
@@ -1782,7 +1782,7 @@ selection_paint (ClutterText *self)
|
||||
CoglColor cogl_color = { 0, };
|
||||
CoglFramebuffer *fb;
|
||||
|
||||
fb = _clutter_actor_get_active_framebuffer (actor);
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
if (G_UNLIKELY (fb == NULL))
|
||||
return;
|
||||
|
||||
@@ -2391,13 +2391,7 @@ clutter_text_paint (ClutterActor *self)
|
||||
float alloc_width;
|
||||
float alloc_height;
|
||||
|
||||
/* FIXME: this should not be needed, but apparently the text-cache
|
||||
* test unit manages to get in a situation where the active frame
|
||||
* buffer is NULL
|
||||
*/
|
||||
fb = _clutter_actor_get_active_framebuffer (self);
|
||||
if (fb == NULL)
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
/* Note that if anything in this paint method changes it needs to be
|
||||
reflected in the get_paint_volume implementation which is tightly
|
||||
|
||||
@@ -185,6 +185,26 @@ clutter_virtual_input_device_evdev_notify_absolute_motion (ClutterVirtualInputDe
|
||||
NULL);
|
||||
}
|
||||
|
||||
static int
|
||||
translate_to_evdev_button (int clutter_button)
|
||||
{
|
||||
switch (clutter_button)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRIMARY:
|
||||
return BTN_LEFT;
|
||||
case CLUTTER_BUTTON_SECONDARY:
|
||||
return BTN_RIGHT;
|
||||
case CLUTTER_BUTTON_MIDDLE:
|
||||
return BTN_MIDDLE;
|
||||
default:
|
||||
/*
|
||||
* For compatibility reasons, all additional buttons go after the old
|
||||
* 4-7 scroll ones.
|
||||
*/
|
||||
return clutter_button + (BTN_LEFT - 1) - 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *virtual_device,
|
||||
uint64_t time_us,
|
||||
@@ -194,30 +214,33 @@ clutter_virtual_input_device_evdev_notify_button (ClutterVirtualInputDevice *vir
|
||||
ClutterVirtualInputDeviceEvdev *virtual_evdev =
|
||||
CLUTTER_VIRTUAL_INPUT_DEVICE_EVDEV (virtual_device);
|
||||
int button_count;
|
||||
int evdev_button;
|
||||
|
||||
if (time_us == CLUTTER_CURRENT_TIME)
|
||||
time_us = g_get_monotonic_time ();
|
||||
|
||||
if (get_button_type (button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||
evdev_button = translate_to_evdev_button (button);
|
||||
|
||||
if (get_button_type (evdev_button) != EVDEV_BUTTON_TYPE_BUTTON)
|
||||
{
|
||||
g_warning ("Unknown/invalid virtual device button 0x%x pressed",
|
||||
button);
|
||||
evdev_button);
|
||||
return;
|
||||
}
|
||||
|
||||
button_count = update_button_count (virtual_evdev, button, button_state);
|
||||
button_count = update_button_count (virtual_evdev, evdev_button, button_state);
|
||||
if (button_count < 0 || button_count > 1)
|
||||
{
|
||||
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", button,
|
||||
g_warning ("Received multiple virtual 0x%x button %s (ignoring)", evdev_button,
|
||||
button_state == CLUTTER_BUTTON_STATE_PRESSED ? "presses" : "releases");
|
||||
update_button_count (virtual_evdev, button, 1 - button_state);
|
||||
update_button_count (virtual_evdev, evdev_button, 1 - button_state);
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_seat_evdev_notify_button (virtual_evdev->seat,
|
||||
virtual_evdev->device,
|
||||
time_us,
|
||||
button,
|
||||
evdev_button,
|
||||
button_state);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
|
||||
typedef struct _ClutterKeymapX11Class ClutterKeymapX11Class;
|
||||
typedef struct _DirectionCacheEntry DirectionCacheEntry;
|
||||
typedef struct _ClutterKeymapKey ClutterKeymapKey;
|
||||
|
||||
struct _ClutterKeymapKey
|
||||
{
|
||||
guint keycode;
|
||||
guint group;
|
||||
guint level;
|
||||
};
|
||||
|
||||
struct _DirectionCacheEntry
|
||||
{
|
||||
@@ -59,6 +67,7 @@ struct _ClutterKeymapX11
|
||||
|
||||
ClutterModifierType num_lock_mask;
|
||||
ClutterModifierType scroll_lock_mask;
|
||||
ClutterModifierType level3_shift_mask;
|
||||
|
||||
PangoDirection current_direction;
|
||||
|
||||
@@ -69,6 +78,7 @@ struct _ClutterKeymapX11
|
||||
Atom current_group_atom;
|
||||
guint current_cache_serial;
|
||||
DirectionCacheEntry group_direction_cache[4];
|
||||
int current_group;
|
||||
#endif
|
||||
|
||||
guint caps_lock_state : 1;
|
||||
@@ -198,6 +208,9 @@ get_xkb (ClutterKeymapX11 *keymap_x11)
|
||||
if (keymap_x11->scroll_lock_mask == 0)
|
||||
keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy,
|
||||
XK_Scroll_Lock);
|
||||
if (keymap_x11->level3_shift_mask == 0)
|
||||
keymap_x11->level3_shift_mask = XkbKeysymToModifiers (backend_x11->xdpy,
|
||||
XK_ISO_Level3_Shift);
|
||||
|
||||
return keymap_x11->xkb_desc;
|
||||
}
|
||||
@@ -469,6 +482,7 @@ static void
|
||||
clutter_keymap_x11_init (ClutterKeymapX11 *keymap)
|
||||
{
|
||||
keymap->current_direction = PANGO_DIRECTION_NEUTRAL;
|
||||
keymap->current_group = -1;
|
||||
}
|
||||
|
||||
static ClutterTranslateReturn
|
||||
@@ -498,7 +512,8 @@ clutter_keymap_x11_translate_event (ClutterEventTranslator *translator,
|
||||
{
|
||||
case XkbStateNotify:
|
||||
CLUTTER_NOTE (EVENT, "Updating keyboard state");
|
||||
update_direction (keymap_x11, XkbStateGroup (&xkb_event->state));
|
||||
keymap_x11->current_group = XkbStateGroup (&xkb_event->state);
|
||||
update_direction (keymap_x11, keymap_x11->current_group);
|
||||
update_locked_mods (keymap_x11, xkb_event->state.locked_mods);
|
||||
retval = CLUTTER_TRANSLATE_REMOVE;
|
||||
break;
|
||||
@@ -665,3 +680,164 @@ _clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap)
|
||||
#endif
|
||||
return PANGO_DIRECTION_NEUTRAL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_keymap_x11_get_entries_for_keyval (ClutterKeymapX11 *keymap_x11,
|
||||
guint keyval,
|
||||
ClutterKeymapKey **keys,
|
||||
gint *n_keys)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb)
|
||||
{
|
||||
XkbDescRec *xkb = get_xkb (keymap_x11);
|
||||
GArray *retval;
|
||||
gint keycode;
|
||||
|
||||
keycode = keymap_x11->min_keycode;
|
||||
retval = g_array_new (FALSE, FALSE, sizeof (ClutterKeymapKey));
|
||||
|
||||
while (keycode <= keymap_x11->max_keycode)
|
||||
{
|
||||
gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode);
|
||||
gint group = 0;
|
||||
gint level = 0;
|
||||
gint total_syms = XkbKeyNumSyms (xkb, keycode);
|
||||
gint i = 0;
|
||||
KeySym *entry;
|
||||
|
||||
/* entry is an array with all syms for group 0, all
|
||||
* syms for group 1, etc. and for each group the
|
||||
* shift level syms are in order
|
||||
*/
|
||||
entry = XkbKeySymsPtr (xkb, keycode);
|
||||
|
||||
while (i < total_syms)
|
||||
{
|
||||
g_assert (i == (group * max_shift_levels + level));
|
||||
|
||||
if (entry[i] == keyval)
|
||||
{
|
||||
ClutterKeymapKey key;
|
||||
|
||||
key.keycode = keycode;
|
||||
key.group = group;
|
||||
key.level = level;
|
||||
|
||||
g_array_append_val (retval, key);
|
||||
|
||||
g_assert (XkbKeySymEntry (xkb, keycode, level, group) ==
|
||||
keyval);
|
||||
}
|
||||
|
||||
++level;
|
||||
|
||||
if (level == max_shift_levels)
|
||||
{
|
||||
level = 0;
|
||||
++group;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
++keycode;
|
||||
}
|
||||
|
||||
if (retval->len > 0)
|
||||
{
|
||||
*keys = (ClutterKeymapKey*) retval->data;
|
||||
*n_keys = retval->len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*keys = NULL;
|
||||
*n_keys = 0;
|
||||
}
|
||||
|
||||
g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
|
||||
|
||||
return *n_keys > 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
|
||||
uint32_t level,
|
||||
gboolean enable)
|
||||
{
|
||||
#ifdef HAVE_XKB
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
uint32_t modifiers[] = {
|
||||
0,
|
||||
ShiftMask,
|
||||
keymap_x11->level3_shift_mask,
|
||||
keymap_x11->level3_shift_mask | ShiftMask,
|
||||
};
|
||||
uint32_t value = 0;
|
||||
|
||||
if (!backend_x11->use_xkb)
|
||||
return;
|
||||
|
||||
level = CLAMP (level, 0, G_N_ELEMENTS (modifiers) - 1);
|
||||
|
||||
if (enable)
|
||||
value = modifiers[level];
|
||||
else
|
||||
value = 0;
|
||||
|
||||
XkbLatchModifiers (clutter_x11_get_default_display (),
|
||||
XkbUseCoreKbd, modifiers[level],
|
||||
value);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
clutter_keymap_x11_get_current_group (ClutterKeymapX11 *keymap_x11)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend);
|
||||
XkbStateRec state_rec;
|
||||
|
||||
if (keymap_x11->current_group >= 0)
|
||||
return keymap_x11->current_group;
|
||||
|
||||
XkbGetState (backend_x11->xdpy, XkbUseCoreKbd, &state_rec);
|
||||
return XkbStateGroup (&state_rec);
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
|
||||
guint keyval,
|
||||
guint *keycode_out,
|
||||
guint *level_out)
|
||||
{
|
||||
ClutterKeymapKey *keys;
|
||||
gint i, n_keys, group;
|
||||
gboolean found = FALSE;
|
||||
|
||||
g_return_val_if_fail (keycode_out != NULL, FALSE);
|
||||
g_return_val_if_fail (level_out != NULL, FALSE);
|
||||
|
||||
group = clutter_keymap_x11_get_current_group (keymap_x11);
|
||||
|
||||
if (!clutter_keymap_x11_get_entries_for_keyval (keymap_x11, keyval, &keys, &n_keys))
|
||||
return FALSE;
|
||||
|
||||
for (i = 0; i < n_keys && !found; i++)
|
||||
{
|
||||
if (keys[i].group == group)
|
||||
{
|
||||
*keycode_out = keys[i].keycode;
|
||||
*level_out = keys[i].level;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (keys);
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,14 @@ gboolean _clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap,
|
||||
|
||||
PangoDirection _clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap);
|
||||
|
||||
gboolean clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11,
|
||||
guint keyval,
|
||||
guint *keycode_out,
|
||||
guint *level_out);
|
||||
void clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11,
|
||||
uint32_t level,
|
||||
gboolean enable);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_KEYMAP_X11_H__ */
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
#include "clutter-virtual-input-device.h"
|
||||
#include "x11/clutter-virtual-input-device-x11.h"
|
||||
#include "x11/clutter-backend-x11.h"
|
||||
#include "x11/clutter-keymap-x11.h"
|
||||
|
||||
struct _ClutterVirtualInputDeviceX11
|
||||
{
|
||||
@@ -135,11 +137,25 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu
|
||||
uint32_t keyval,
|
||||
ClutterKeyState key_state)
|
||||
{
|
||||
KeyCode keycode;
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
|
||||
ClutterKeymapX11 *keymap = backend_x11->keymap;
|
||||
uint32_t keycode, level;
|
||||
|
||||
if (!clutter_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level))
|
||||
{
|
||||
g_warning ("No keycode found for keyval %x in current group", keyval);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_state == CLUTTER_KEY_STATE_PRESSED)
|
||||
clutter_keymap_x11_latch_modifiers (keymap, level, TRUE);
|
||||
|
||||
keycode = XKeysymToKeycode (clutter_x11_get_default_display (), keyval);
|
||||
XTestFakeKeyEvent (clutter_x11_get_default_display (),
|
||||
keycode, key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
||||
(KeyCode) keycode,
|
||||
key_state == CLUTTER_KEY_STATE_PRESSED, 0);
|
||||
|
||||
if (key_state == CLUTTER_KEY_STATE_RELEASED)
|
||||
clutter_keymap_x11_latch_modifiers (keymap, level, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -14,6 +14,7 @@ stackingdir = $(pkgdatadir)/tests/stacking
|
||||
dist_stacking_DATA = \
|
||||
tests/stacking/basic-x11.metatest \
|
||||
tests/stacking/basic-wayland.metatest \
|
||||
tests/stacking/closed-transient.metatest \
|
||||
tests/stacking/minimized.metatest \
|
||||
tests/stacking/mixed-windows.metatest \
|
||||
tests/stacking/set-parent.metatest \
|
||||
|
||||
@@ -246,7 +246,8 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||
/* Monitor inhibitors */
|
||||
monitor->session_proxy =
|
||||
g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS |
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
|
||||
NULL,
|
||||
"org.gnome.SessionManager",
|
||||
"/org/gnome/SessionManager",
|
||||
@@ -262,8 +263,11 @@ meta_idle_monitor_init (MetaIdleMonitor *monitor)
|
||||
|
||||
v = g_dbus_proxy_get_cached_property (monitor->session_proxy,
|
||||
"InhibitedActions");
|
||||
monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
|
||||
g_variant_unref (v);
|
||||
if (v)
|
||||
{
|
||||
monitor->inhibited = g_variant_get_uint32 (v) & GSM_INHIBITOR_FLAG_IDLE;
|
||||
g_variant_unref (v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -181,6 +181,7 @@ struct _MetaMonitorManager
|
||||
|
||||
GnomePnpIds *pnp_ids;
|
||||
UpClient *up_client;
|
||||
gboolean lid_is_closed;
|
||||
|
||||
gulong experimental_features_changed_handler_id;
|
||||
|
||||
|
||||
@@ -351,7 +351,13 @@ lid_is_closed_changed (UpClient *client,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *manager = user_data;
|
||||
gboolean lid_is_closed;
|
||||
|
||||
lid_is_closed = up_client_get_lid_is_closed (manager->up_client);
|
||||
if (lid_is_closed == manager->lid_is_closed)
|
||||
return;
|
||||
|
||||
manager->lid_is_closed = lid_is_closed;
|
||||
meta_monitor_manager_lid_is_closed_changed (manager);
|
||||
}
|
||||
|
||||
@@ -361,7 +367,7 @@ meta_monitor_manager_real_is_lid_closed (MetaMonitorManager *manager)
|
||||
if (!manager->up_client)
|
||||
return FALSE;
|
||||
|
||||
return up_client_get_lid_is_closed (manager->up_client);
|
||||
return manager->lid_is_closed;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -733,8 +739,12 @@ meta_monitor_manager_constructed (GObject *object)
|
||||
if (manager_class->is_lid_closed == meta_monitor_manager_real_is_lid_closed)
|
||||
{
|
||||
manager->up_client = up_client_new ();
|
||||
g_signal_connect_object (manager->up_client, "notify::lid-is-closed",
|
||||
G_CALLBACK (lid_is_closed_changed), manager, 0);
|
||||
if (manager->up_client)
|
||||
{
|
||||
g_signal_connect_object (manager->up_client, "notify::lid-is-closed",
|
||||
G_CALLBACK (lid_is_closed_changed), manager, 0);
|
||||
manager->lid_is_closed = up_client_get_lid_is_closed (manager->up_client);
|
||||
}
|
||||
}
|
||||
|
||||
g_signal_connect_object (manager, "notify::power-save-mode",
|
||||
@@ -1323,9 +1333,13 @@ meta_monitor_manager_handle_get_current_state (MetaDBusDisplayConfig *skeleton,
|
||||
GVariantBuilder mode_properties_builder;
|
||||
MetaCrtcModeFlag mode_flags;
|
||||
|
||||
if (!meta_monitor_mode_should_be_advertised (monitor_mode))
|
||||
continue;
|
||||
|
||||
mode_id = meta_monitor_mode_get_id (monitor_mode);
|
||||
meta_monitor_mode_get_resolution (monitor_mode,
|
||||
&mode_width, &mode_height);
|
||||
|
||||
refresh_rate = meta_monitor_mode_get_refresh_rate (monitor_mode);
|
||||
|
||||
preferred_scale =
|
||||
|
||||
@@ -203,13 +203,9 @@ meta_monitor_get_main_output (MetaMonitor *monitor)
|
||||
gboolean
|
||||
meta_monitor_is_active (MetaMonitor *monitor)
|
||||
{
|
||||
MetaOutput *output;
|
||||
MetaCrtc *crtc;
|
||||
MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor);
|
||||
|
||||
output = meta_monitor_get_main_output (monitor);
|
||||
crtc = meta_output_get_assigned_crtc (output);
|
||||
|
||||
return crtc && crtc->current_mode;
|
||||
return !!priv->current_mode;
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -1411,6 +1407,18 @@ meta_monitor_get_current_mode (MetaMonitor *monitor)
|
||||
return priv->current_mode;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_current_mode_known (MetaMonitor *monitor)
|
||||
{
|
||||
MetaOutput *output;
|
||||
MetaCrtc *crtc;
|
||||
|
||||
output = meta_monitor_get_main_output (monitor);
|
||||
crtc = meta_output_get_assigned_crtc (output);
|
||||
|
||||
return meta_monitor_is_active (monitor) == (crtc && crtc->current_mode);
|
||||
}
|
||||
|
||||
void
|
||||
meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
||||
{
|
||||
@@ -1430,6 +1438,8 @@ meta_monitor_derive_current_mode (MetaMonitor *monitor)
|
||||
}
|
||||
|
||||
priv->current_mode = current_mode;
|
||||
|
||||
g_warn_if_fail (is_current_mode_known (monitor));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1553,6 +1563,22 @@ meta_monitor_calculate_mode_scale (MetaMonitor *monitor,
|
||||
return calculate_scale (monitor, monitor_mode);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_logical_size_large_enough (gint width, gint height)
|
||||
{
|
||||
return width >= MINIMUM_LOGICAL_WIDTH &&
|
||||
height >= MINIMUM_LOGICAL_HEIGHT;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode)
|
||||
{
|
||||
g_return_val_if_fail (monitor_mode != NULL, FALSE);
|
||||
|
||||
return is_logical_size_large_enough (monitor_mode->spec.width,
|
||||
monitor_mode->spec.height);
|
||||
}
|
||||
|
||||
static float
|
||||
get_closest_scale_factor_for_resolution (float width,
|
||||
float height,
|
||||
@@ -1573,8 +1599,7 @@ get_closest_scale_factor_for_resolution (float width,
|
||||
|
||||
if (scale < MINIMUM_SCALE_FACTOR ||
|
||||
scale > MAXIMUM_SCALE_FACTOR ||
|
||||
floorf (scaled_w) < MINIMUM_LOGICAL_WIDTH ||
|
||||
floorf (scaled_h) < MINIMUM_LOGICAL_HEIGHT)
|
||||
!is_logical_size_large_enough (floorf (scaled_w), floorf (scaled_h)))
|
||||
goto out;
|
||||
|
||||
if (floorf (scaled_w) == scaled_w && floorf (scaled_h) == scaled_h)
|
||||
|
||||
@@ -219,6 +219,8 @@ gboolean meta_monitor_mode_foreach_output (MetaMonitor *monitor,
|
||||
gpointer user_data,
|
||||
GError **error);
|
||||
|
||||
gboolean meta_monitor_mode_should_be_advertised (MetaMonitorMode *monitor_mode);
|
||||
|
||||
MetaMonitorSpec * meta_monitor_spec_clone (MetaMonitorSpec *monitor_id);
|
||||
|
||||
gboolean meta_monitor_spec_equals (MetaMonitorSpec *monitor_id,
|
||||
|
||||
@@ -47,6 +47,12 @@ typedef struct _MetaKmsSource
|
||||
MetaGpuKms *gpu_kms;
|
||||
} MetaKmsSource;
|
||||
|
||||
typedef struct _MetaGpuKmsFlipClosureContainer
|
||||
{
|
||||
GClosure *flip_closure;
|
||||
MetaGpuKms *gpu_kms;
|
||||
} MetaGpuKmsFlipClosureContainer;
|
||||
|
||||
struct _MetaGpuKms
|
||||
{
|
||||
MetaGpu parent;
|
||||
@@ -62,6 +68,8 @@ struct _MetaGpuKms
|
||||
int max_buffer_height;
|
||||
|
||||
gboolean page_flips_not_supported;
|
||||
|
||||
gboolean resources_init_failed_before;
|
||||
};
|
||||
|
||||
G_DEFINE_QUARK (MetaGpuKmsError, meta_gpu_kms_error)
|
||||
@@ -143,7 +151,10 @@ meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
|
||||
connectors, n_connectors,
|
||||
mode) != 0)
|
||||
{
|
||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||
if (mode)
|
||||
g_warning ("Failed to set CRTC mode %s: %m", crtc->current_mode->name);
|
||||
else
|
||||
g_warning ("Failed to disable CRTC");
|
||||
g_free (connectors);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -204,11 +215,26 @@ meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
typedef struct _GpuClosureContainer
|
||||
MetaGpuKmsFlipClosureContainer *
|
||||
meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
||||
GClosure *flip_closure)
|
||||
{
|
||||
GClosure *flip_closure;
|
||||
MetaGpuKms *gpu_kms;
|
||||
} GpuClosureContainer;
|
||||
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||
|
||||
closure_container = g_new0 (MetaGpuKmsFlipClosureContainer, 1);
|
||||
*closure_container = (MetaGpuKmsFlipClosureContainer) {
|
||||
.flip_closure = flip_closure,
|
||||
.gpu_kms = gpu_kms
|
||||
};
|
||||
|
||||
return closure_container;
|
||||
}
|
||||
|
||||
void
|
||||
meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container)
|
||||
{
|
||||
g_free (closure_container);
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||
@@ -234,14 +260,11 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||
|
||||
if (!gpu_kms->page_flips_not_supported)
|
||||
{
|
||||
GpuClosureContainer *closure_container;
|
||||
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||
int kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
|
||||
closure_container = g_new0 (GpuClosureContainer, 1);
|
||||
*closure_container = (GpuClosureContainer) {
|
||||
.flip_closure = flip_closure,
|
||||
.gpu_kms = gpu_kms
|
||||
};
|
||||
closure_container = meta_gpu_kms_wrap_flip_closure (gpu_kms,
|
||||
flip_closure);
|
||||
|
||||
ret = drmModePageFlip (kms_fd,
|
||||
crtc->crtc_id,
|
||||
@@ -250,7 +273,7 @@ meta_gpu_kms_flip_crtc (MetaGpuKms *gpu_kms,
|
||||
closure_container);
|
||||
if (ret != 0 && ret != -EACCES)
|
||||
{
|
||||
g_free (closure_container);
|
||||
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||
g_warning ("Failed to flip: %s", strerror (-ret));
|
||||
gpu_kms->page_flips_not_supported = TRUE;
|
||||
}
|
||||
@@ -281,12 +304,12 @@ page_flip_handler (int fd,
|
||||
unsigned int usec,
|
||||
void *user_data)
|
||||
{
|
||||
GpuClosureContainer *closure_container = user_data;
|
||||
MetaGpuKmsFlipClosureContainer *closure_container = user_data;
|
||||
GClosure *flip_closure = closure_container->flip_closure;
|
||||
MetaGpuKms *gpu_kms = closure_container->gpu_kms;
|
||||
|
||||
invoke_flip_closure (flip_closure, gpu_kms);
|
||||
g_free (closure_container);
|
||||
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@@ -706,20 +729,34 @@ init_outputs (MetaGpuKms *gpu_kms,
|
||||
setup_output_clones (gpu);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_kms_resources_init (MetaKmsResources *resources,
|
||||
int fd)
|
||||
static gboolean
|
||||
meta_kms_resources_init (MetaKmsResources *resources,
|
||||
int fd,
|
||||
GError **error)
|
||||
|
||||
{
|
||||
drmModeRes *drm_resources;
|
||||
unsigned int i;
|
||||
|
||||
drm_resources = drmModeGetResources (fd);
|
||||
|
||||
if (!drm_resources)
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Calling drmModeGetResources() failed");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
resources->resources = drm_resources;
|
||||
|
||||
resources->n_encoders = (unsigned int) drm_resources->count_encoders;
|
||||
resources->encoders = g_new (drmModeEncoder *, resources->n_encoders);
|
||||
for (i = 0; i < resources->n_encoders; i++)
|
||||
resources->encoders[i] = drmModeGetEncoder (fd, drm_resources->encoders[i]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -731,7 +768,7 @@ meta_kms_resources_release (MetaKmsResources *resources)
|
||||
drmModeFreeEncoder (resources->encoders[i]);
|
||||
g_free (resources->encoders);
|
||||
|
||||
drmModeFreeResources (resources->resources);
|
||||
g_clear_pointer (&resources->resources, drmModeFreeResources);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -742,8 +779,18 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_gpu_get_monitor_manager (gpu);
|
||||
MetaKmsResources resources;
|
||||
g_autoptr (GError) local_error = NULL;
|
||||
|
||||
meta_kms_resources_init (&resources, gpu_kms->fd);
|
||||
if (!meta_kms_resources_init (&resources, gpu_kms->fd, &local_error))
|
||||
{
|
||||
if (!gpu_kms->resources_init_failed_before)
|
||||
{
|
||||
g_warning ("meta_kms_resources_init failed: %s, assuming we have no outputs",
|
||||
local_error->message);
|
||||
gpu_kms->resources_init_failed_before = TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gpu_kms->max_buffer_width = resources.resources->max_width;
|
||||
gpu_kms->max_buffer_height = resources.resources->max_height;
|
||||
@@ -768,6 +815,12 @@ meta_gpu_kms_read_current (MetaGpu *gpu,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms)
|
||||
{
|
||||
return gpu_kms->n_connectors > 0;
|
||||
}
|
||||
|
||||
MetaGpuKms *
|
||||
meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
||||
const char *kms_file_path,
|
||||
@@ -801,6 +854,13 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
||||
*/
|
||||
drm_resources = drmModeGetResources (kms_fd);
|
||||
|
||||
if (!drm_resources)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No resources");
|
||||
meta_launcher_close_restricted (launcher, kms_fd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n_connectors = drm_resources->count_connectors;
|
||||
|
||||
drmModeFreeResources (drm_resources);
|
||||
@@ -824,6 +884,8 @@ meta_gpu_kms_new (MetaMonitorManagerKms *monitor_manager_kms,
|
||||
|
||||
drmSetClientCap (gpu_kms->fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
||||
|
||||
meta_gpu_kms_read_current (META_GPU (gpu_kms), NULL);
|
||||
|
||||
source = g_source_new (&kms_event_funcs, sizeof (MetaKmsSource));
|
||||
kms_source = (MetaKmsSource *) source;
|
||||
kms_source->fd_tag = g_source_add_unix_fd (source,
|
||||
|
||||
@@ -40,6 +40,8 @@ GQuark meta_gpu_kms_error_quark (void);
|
||||
#define META_TYPE_GPU_KMS (meta_gpu_kms_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaGpuKms, meta_gpu_kms, META, GPU_KMS, MetaGpu)
|
||||
|
||||
typedef struct _MetaGpuKmsFlipClosureContainer MetaGpuKmsFlipClosureContainer;
|
||||
|
||||
typedef struct _MetaKmsResources
|
||||
{
|
||||
drmModeRes *resources;
|
||||
@@ -59,6 +61,8 @@ gboolean meta_gpu_kms_apply_crtc_mode (MetaGpuKms *gpu_kms,
|
||||
int y,
|
||||
uint32_t fb_id);
|
||||
|
||||
gboolean meta_gpu_kms_can_have_outputs (MetaGpuKms *gpu_kms);
|
||||
|
||||
gboolean meta_gpu_kms_is_crtc_active (MetaGpuKms *gpu_kms,
|
||||
MetaCrtc *crtc);
|
||||
|
||||
@@ -92,4 +96,9 @@ gboolean meta_drm_mode_equal (const drmModeModeInfo *one,
|
||||
|
||||
float meta_calculate_drm_mode_refresh_rate (const drmModeModeInfo *mode);
|
||||
|
||||
MetaGpuKmsFlipClosureContainer * meta_gpu_kms_wrap_flip_closure (MetaGpuKms *gpu_kms,
|
||||
GClosure *flip_closure);
|
||||
|
||||
void meta_gpu_kms_flip_closure_container_free (MetaGpuKmsFlipClosureContainer *closure_container);
|
||||
|
||||
#endif /* META_GPU_KMS_H */
|
||||
|
||||
@@ -642,10 +642,12 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
|
||||
GError **error)
|
||||
{
|
||||
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (initable);
|
||||
MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms);
|
||||
const char *subsystems[2] = { "drm", NULL };
|
||||
GList *gpu_paths;
|
||||
g_autofree char *primary_gpu_path = NULL;
|
||||
GList *l;
|
||||
gboolean can_have_outputs;
|
||||
|
||||
manager_kms->udev = g_udev_client_new (subsystems);
|
||||
|
||||
@@ -694,6 +696,24 @@ meta_monitor_manager_kms_initable_init (GInitable *initable,
|
||||
}
|
||||
g_list_free_full (gpu_paths, g_free);
|
||||
|
||||
can_have_outputs = FALSE;
|
||||
for (l = meta_monitor_manager_get_gpus (manager); l; l = l->next)
|
||||
{
|
||||
MetaGpuKms *gpu_kms = l->data;
|
||||
|
||||
if (meta_gpu_kms_can_have_outputs (gpu_kms))
|
||||
{
|
||||
can_have_outputs = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!can_have_outputs)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||
"No GPUs with outputs found");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
@@ -993,14 +993,29 @@ meta_renderer_native_choose_egl_config (CoglDisplay *cogl_display,
|
||||
CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaEgl *egl = meta_backend_get_egl (backend);
|
||||
MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
|
||||
EGLDisplay egl_display = cogl_renderer_egl->edpy;
|
||||
|
||||
return choose_egl_config_from_gbm_format (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
out_config,
|
||||
error);
|
||||
switch (renderer_gpu_data->mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
return choose_egl_config_from_gbm_format (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
out_config,
|
||||
error);
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
return meta_egl_choose_first_config (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
out_config,
|
||||
error);
|
||||
#endif
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -1271,6 +1286,7 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
|
||||
MetaRendererNativeGpuData *renderer_gpu_data;
|
||||
EGLDisplay *egl_display;
|
||||
MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
|
||||
MetaGpuKmsFlipClosureContainer *closure_container;
|
||||
EGLAttrib *acquire_attribs;
|
||||
GError *error = NULL;
|
||||
|
||||
@@ -1280,9 +1296,12 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
|
||||
if (renderer_gpu_data->egl.no_egl_output_drm_flip_event)
|
||||
return FALSE;
|
||||
|
||||
closure_container =
|
||||
meta_gpu_kms_wrap_flip_closure (onscreen_native->render_gpu, flip_closure);
|
||||
|
||||
acquire_attribs = (EGLAttrib[]) {
|
||||
EGL_DRM_FLIP_EVENT_DATA_NV,
|
||||
(EGLAttrib) flip_closure,
|
||||
(EGLAttrib) closure_container,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
@@ -1301,6 +1320,7 @@ flip_egl_stream (MetaOnscreenNative *onscreen_native,
|
||||
renderer_gpu_data->egl.no_egl_output_drm_flip_event = TRUE;
|
||||
}
|
||||
g_error_free (error);
|
||||
meta_gpu_kms_flip_closure_container_free (closure_container);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1607,12 +1627,23 @@ gbm_get_next_fb_id (MetaGpuKms *gpu_kms,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < gbm_bo_get_plane_count (next_bo); i++)
|
||||
if (gbm_bo_get_handle_for_plane (next_bo, 0).s32 == -1)
|
||||
{
|
||||
strides[i] = gbm_bo_get_stride_for_plane (next_bo, i);
|
||||
handles[i] = gbm_bo_get_handle_for_plane (next_bo, i).u32;
|
||||
offsets[i] = gbm_bo_get_offset (next_bo, i);
|
||||
modifiers[i] = gbm_bo_get_modifier (next_bo);
|
||||
/* Failed to fetch handle to plane, falling back to old method */
|
||||
strides[0] = gbm_bo_get_stride (next_bo);
|
||||
handles[0] = gbm_bo_get_handle (next_bo).u32;
|
||||
offsets[0] = 0;
|
||||
modifiers[0] = DRM_FORMAT_MOD_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < gbm_bo_get_plane_count (next_bo); i++)
|
||||
{
|
||||
strides[i] = gbm_bo_get_stride_for_plane (next_bo, i);
|
||||
handles[i] = gbm_bo_get_handle_for_plane (next_bo, i).u32;
|
||||
offsets[i] = gbm_bo_get_offset (next_bo, i);
|
||||
modifiers[i] = gbm_bo_get_modifier (next_bo);
|
||||
}
|
||||
}
|
||||
|
||||
kms_fd = meta_gpu_kms_get_fd (gpu_kms);
|
||||
@@ -2720,9 +2751,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
MetaMonitor *main_monitor;
|
||||
MetaOutput *main_output;
|
||||
MetaCrtc *crtc;
|
||||
MetaMonitorTransform crtc_transform;
|
||||
|
||||
main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
||||
main_output = meta_monitor_get_main_output (main_monitor);
|
||||
crtc = meta_output_get_assigned_crtc (main_output);
|
||||
crtc_transform =
|
||||
meta_monitor_logical_to_crtc_transform (main_monitor,
|
||||
logical_monitor->transform);
|
||||
|
||||
/*
|
||||
* Pick any monitor and output and check; all CRTCs of a logical monitor will
|
||||
@@ -2731,10 +2767,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
|
||||
if (meta_monitor_manager_is_transform_handled (monitor_manager,
|
||||
crtc,
|
||||
crtc->transform))
|
||||
crtc_transform))
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
else
|
||||
return crtc->transform;
|
||||
return crtc_transform;
|
||||
}
|
||||
|
||||
static MetaRendererView *
|
||||
@@ -2907,10 +2943,11 @@ meta_renderer_native_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
create_secondary_egl_config (MetaEgl *egl,
|
||||
EGLDisplay egl_display,
|
||||
EGLConfig *egl_config,
|
||||
GError **error)
|
||||
create_secondary_egl_config (MetaEgl *egl,
|
||||
MetaRendererNativeMode mode,
|
||||
EGLDisplay egl_display,
|
||||
EGLConfig *egl_config,
|
||||
GError **error)
|
||||
{
|
||||
EGLint attributes[] = {
|
||||
EGL_RED_SIZE, 1,
|
||||
@@ -2923,12 +2960,26 @@ create_secondary_egl_config (MetaEgl *egl,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
return choose_egl_config_from_gbm_format (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
egl_config,
|
||||
error);
|
||||
switch (mode)
|
||||
{
|
||||
case META_RENDERER_NATIVE_MODE_GBM:
|
||||
return choose_egl_config_from_gbm_format (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
egl_config,
|
||||
error);
|
||||
#ifdef HAVE_EGL_DEVICE
|
||||
case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
|
||||
return meta_egl_choose_first_config (egl,
|
||||
egl_display,
|
||||
attributes,
|
||||
egl_config,
|
||||
error);
|
||||
#endif
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static EGLContext
|
||||
@@ -2972,7 +3023,8 @@ init_secondary_gpu_data_gpu (MetaRendererNativeGpuData *renderer_gpu_data,
|
||||
EGLContext egl_context;
|
||||
char **missing_gl_extensions;
|
||||
|
||||
if (!create_secondary_egl_config (egl,egl_display, &egl_config, error))
|
||||
if (!create_secondary_egl_config (egl, renderer_gpu_data->mode, egl_display,
|
||||
&egl_config, error))
|
||||
return FALSE;
|
||||
|
||||
egl_context = create_secondary_egl_context (egl, egl_display, egl_config, error);
|
||||
|
||||
@@ -547,8 +547,9 @@ meta_backend_x11_grab_device (MetaBackend *backend,
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
int ret;
|
||||
|
||||
if (timestamp != CurrentTime)
|
||||
timestamp = MAX (timestamp, priv->latest_evtime);
|
||||
if (timestamp != CurrentTime &&
|
||||
XSERVER_TIME_IS_BEFORE (timestamp, priv->latest_evtime))
|
||||
timestamp = priv->latest_evtime;
|
||||
|
||||
XISetMask (mask.mask, XI_ButtonPress);
|
||||
XISetMask (mask.mask, XI_ButtonRelease);
|
||||
|
||||
@@ -51,10 +51,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
MetaMonitor *main_monitor;
|
||||
MetaOutput *main_output;
|
||||
MetaCrtc *crtc;
|
||||
MetaMonitorTransform crtc_transform;
|
||||
|
||||
main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
|
||||
main_output = meta_monitor_get_main_output (main_monitor);
|
||||
crtc = meta_output_get_assigned_crtc (main_output);
|
||||
crtc_transform =
|
||||
meta_monitor_logical_to_crtc_transform (main_monitor,
|
||||
logical_monitor->transform);
|
||||
/*
|
||||
* Pick any monitor and output and check; all CRTCs of a logical monitor will
|
||||
* always have the same transform assigned to them.
|
||||
@@ -62,10 +66,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager,
|
||||
|
||||
if (meta_monitor_manager_is_transform_handled (monitor_manager,
|
||||
crtc,
|
||||
crtc->transform))
|
||||
crtc_transform))
|
||||
return META_MONITOR_TRANSFORM_NORMAL;
|
||||
else
|
||||
return crtc->transform;
|
||||
return crtc_transform;
|
||||
}
|
||||
|
||||
static MetaRendererView *
|
||||
|
||||
@@ -798,6 +798,7 @@ meta_compositor_hide_window (MetaCompositor *compositor,
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
meta_window_actor_hide (window_actor, effect);
|
||||
meta_stack_tracker_queue_sync_stack (compositor->display->screen->stack_tracker);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -944,6 +945,9 @@ get_top_visible_window_actor (MetaCompositor *compositor)
|
||||
MetaWindow *window = meta_window_actor_get_meta_window (window_actor);
|
||||
MetaRectangle buffer_rect;
|
||||
|
||||
if (!window->visible_to_compositor)
|
||||
continue;
|
||||
|
||||
meta_window_get_buffer_rect (window, &buffer_rect);
|
||||
|
||||
if (meta_rectangle_overlap (&compositor->display->screen->rect,
|
||||
|
||||
@@ -38,6 +38,20 @@
|
||||
|
||||
#include "meta-cullable.h"
|
||||
|
||||
/* MAX_MIPMAPPING_FPS needs to be as small as possible for the best GPU
|
||||
* performance, but higher than the refresh rate of commonly slow updating
|
||||
* windows like top or a blinking cursor, so that such windows do get
|
||||
* mipmapped.
|
||||
*/
|
||||
#define MAX_MIPMAPPING_FPS 5
|
||||
#define MIN_MIPMAP_AGE_USEC (G_USEC_PER_SEC / MAX_MIPMAPPING_FPS)
|
||||
|
||||
/* MIN_FAST_UPDATES_BEFORE_UNMIPMAP allows windows to update themselves
|
||||
* occasionally without causing mipmapping to be disabled, so long as such
|
||||
* an update takes fewer update_area calls than:
|
||||
*/
|
||||
#define MIN_FAST_UPDATES_BEFORE_UNMIPMAP 20
|
||||
|
||||
static void meta_shaped_texture_dispose (GObject *object);
|
||||
|
||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
||||
@@ -95,6 +109,11 @@ struct _MetaShapedTexturePrivate
|
||||
guint tex_width, tex_height;
|
||||
guint fallback_width, fallback_height;
|
||||
|
||||
gint64 prev_invalidation, last_invalidation;
|
||||
guint fast_updates;
|
||||
guint remipmap_timeout_id;
|
||||
gint64 earliest_remipmap;
|
||||
|
||||
guint create_mipmaps : 1;
|
||||
};
|
||||
|
||||
@@ -191,6 +210,12 @@ meta_shaped_texture_dispose (GObject *object)
|
||||
MetaShapedTexture *self = (MetaShapedTexture *) object;
|
||||
MetaShapedTexturePrivate *priv = self->priv;
|
||||
|
||||
if (priv->remipmap_timeout_id)
|
||||
{
|
||||
g_source_remove (priv->remipmap_timeout_id);
|
||||
priv->remipmap_timeout_id = 0;
|
||||
}
|
||||
|
||||
if (priv->paint_tower)
|
||||
meta_texture_tower_free (priv->paint_tower);
|
||||
priv->paint_tower = NULL;
|
||||
@@ -372,6 +397,21 @@ set_cogl_texture (MetaShapedTexture *stex,
|
||||
meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
texture_is_idle_and_not_mipmapped (gpointer user_data)
|
||||
{
|
||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (user_data);
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if ((g_get_monotonic_time () - priv->earliest_remipmap) < 0)
|
||||
return G_SOURCE_CONTINUE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
priv->remipmap_timeout_id = 0;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
@@ -381,9 +421,10 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
guchar opacity;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglTexture *paint_tex;
|
||||
CoglTexture *paint_tex = NULL;
|
||||
ClutterActorBox alloc;
|
||||
CoglPipelineFilter filter;
|
||||
gint64 now = g_get_monotonic_time ();
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
@@ -406,13 +447,34 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||
* support for TFP textures will result in fallbacks to XGetImage.
|
||||
*/
|
||||
if (priv->create_mipmaps)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
else
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
if (priv->create_mipmaps && priv->last_invalidation)
|
||||
{
|
||||
gint64 age = now - priv->last_invalidation;
|
||||
|
||||
if (age >= MIN_MIPMAP_AGE_USEC ||
|
||||
priv->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
||||
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
|
||||
}
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
{
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
|
||||
if (priv->create_mipmaps)
|
||||
{
|
||||
/* Minus 1000 to ensure we don't fail the age test in timeout */
|
||||
priv->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
|
||||
|
||||
if (!priv->remipmap_timeout_id)
|
||||
priv->remipmap_timeout_id =
|
||||
g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000,
|
||||
texture_is_idle_and_not_mipmapped,
|
||||
stex);
|
||||
}
|
||||
}
|
||||
|
||||
tex_width = priv->tex_width;
|
||||
tex_height = priv->tex_height;
|
||||
@@ -632,46 +694,11 @@ effective_unobscured_region (MetaShapedTexture *self)
|
||||
return priv->unobscured_region;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_unobscured_bounds (MetaShapedTexture *self,
|
||||
cairo_rectangle_int_t *unobscured_bounds)
|
||||
{
|
||||
cairo_region_t *unobscured_region = effective_unobscured_region (self);
|
||||
|
||||
if (unobscured_region)
|
||||
{
|
||||
cairo_region_get_extents (unobscured_region, unobscured_bounds);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
MetaShapedTexture *self = META_SHAPED_TEXTURE (actor);
|
||||
ClutterActorBox box;
|
||||
cairo_rectangle_int_t unobscured_bounds;
|
||||
|
||||
if (!clutter_actor_has_allocation (actor))
|
||||
return FALSE;
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &box);
|
||||
|
||||
if (get_unobscured_bounds (self, &unobscured_bounds))
|
||||
{
|
||||
box.x1 = MAX (unobscured_bounds.x, box.x1);
|
||||
box.x2 = MIN (unobscured_bounds.x + unobscured_bounds.width, box.x2);
|
||||
box.y1 = MAX (unobscured_bounds.y, box.y1);
|
||||
box.y2 = MIN (unobscured_bounds.y + unobscured_bounds.height, box.y2);
|
||||
}
|
||||
box.x2 = MAX (box.x2, box.x1);
|
||||
box.y2 = MAX (box.y2, box.y1);
|
||||
|
||||
clutter_paint_volume_union_box (volume, &box);
|
||||
return TRUE;
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -758,6 +785,20 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
||||
|
||||
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
|
||||
|
||||
priv->prev_invalidation = priv->last_invalidation;
|
||||
priv->last_invalidation = g_get_monotonic_time ();
|
||||
|
||||
if (priv->prev_invalidation)
|
||||
{
|
||||
gint64 interval = priv->last_invalidation - priv->prev_invalidation;
|
||||
gboolean fast_update = interval < MIN_MIPMAP_AGE_USEC;
|
||||
|
||||
if (!fast_update)
|
||||
priv->fast_updates = 0;
|
||||
else if (priv->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
||||
priv->fast_updates++;
|
||||
}
|
||||
|
||||
unobscured_region = effective_unobscured_region (stex);
|
||||
if (unobscured_region)
|
||||
{
|
||||
|
||||
@@ -101,6 +101,13 @@ meta_surface_actor_pick (ClutterActor *actor,
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_surface_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_surface_actor_dispose (GObject *object)
|
||||
{
|
||||
@@ -120,6 +127,7 @@ meta_surface_actor_class_init (MetaSurfaceActorClass *klass)
|
||||
|
||||
object_class->dispose = meta_surface_actor_dispose;
|
||||
actor_class->pick = meta_surface_actor_pick;
|
||||
actor_class->get_paint_volume = meta_surface_actor_get_paint_volume;
|
||||
|
||||
signals[REPAINT_SCHEDULED] = g_signal_new ("repaint-scheduled",
|
||||
G_TYPE_FROM_CLASS (object_class),
|
||||
|
||||
@@ -115,5 +115,8 @@ meta_window_kill (MetaWindow *window)
|
||||
void
|
||||
meta_window_free_delete_dialog (MetaWindow *window)
|
||||
{
|
||||
if (window->close_dialog &&
|
||||
meta_close_dialog_is_visible (window->close_dialog))
|
||||
meta_close_dialog_hide (window->close_dialog);
|
||||
g_clear_object (&window->close_dialog);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,12 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
/* FIXME handle this error */
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* Ensure focus is restored after the unmap/map events triggered
|
||||
* by XReparentWindow().
|
||||
*/
|
||||
if (meta_window_has_focus (window))
|
||||
window->restore_focus_on_map = TRUE;
|
||||
|
||||
/* stick frame to the window */
|
||||
window->frame = frame;
|
||||
|
||||
@@ -194,6 +200,12 @@ meta_window_destroy_frame (MetaWindow *window)
|
||||
|
||||
meta_ui_frame_unmanage (frame->ui_frame);
|
||||
|
||||
/* Ensure focus is restored after the unmap/map events triggered
|
||||
* by XReparentWindow().
|
||||
*/
|
||||
if (meta_window_has_focus (window))
|
||||
window->restore_focus_on_map = TRUE;
|
||||
|
||||
meta_display_unregister_x_window (window->display,
|
||||
frame->xwindow);
|
||||
|
||||
|
||||
@@ -1394,7 +1394,9 @@ meta_screen_update_cursor (MetaScreen *screen)
|
||||
|
||||
XDefineCursor (display->xdisplay, screen->xroot, xcursor);
|
||||
XFlush (display->xdisplay);
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
|
||||
if (xcursor)
|
||||
XFreeCursor (display->xdisplay, xcursor);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -82,6 +82,7 @@ typedef enum
|
||||
META_MOVE_RESIZE_UNMAXIMIZE = 1 << 6,
|
||||
META_MOVE_RESIZE_FORCE_MOVE = 1 << 7,
|
||||
META_MOVE_RESIZE_WAYLAND_STATE_CHANGED = 1 << 8,
|
||||
META_MOVE_RESIZE_FORCE_UPDATE_MONITOR = 1 << 9,
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
typedef enum
|
||||
@@ -121,6 +122,13 @@ typedef enum
|
||||
META_PLACEMENT_CONSTRAINT_ADJUSTMENT_RESIZE_Y = 1 << 5,
|
||||
} MetaPlacementConstraintAdjustment;
|
||||
|
||||
typedef enum _MetaWindowUpdateMonitorFlags
|
||||
{
|
||||
META_WINDOW_UPDATE_MONITOR_FLAGS_NONE = 0,
|
||||
META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP = 1 << 0,
|
||||
META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE = 1 << 1,
|
||||
} MetaWindowUpdateMonitorFlags;
|
||||
|
||||
typedef struct _MetaPlacementRule
|
||||
{
|
||||
MetaRectangle anchor_rect;
|
||||
@@ -409,6 +417,9 @@ struct _MetaWindow
|
||||
/* whether or not the window is from a program running on another machine */
|
||||
guint is_remote : 1;
|
||||
|
||||
/* whether focus should be restored on map */
|
||||
guint restore_focus_on_map : 1;
|
||||
|
||||
/* if non-NULL, the bounds of the window frame */
|
||||
cairo_region_t *frame_bounds;
|
||||
|
||||
@@ -549,8 +560,8 @@ struct _MetaWindowClass
|
||||
cairo_surface_t **icon,
|
||||
cairo_surface_t **mini_icon);
|
||||
uint32_t (*get_client_pid) (MetaWindow *window);
|
||||
void (*update_main_monitor) (MetaWindow *window,
|
||||
gboolean user_op);
|
||||
void (*update_main_monitor) (MetaWindow *window,
|
||||
MetaWindowUpdateMonitorFlags flags);
|
||||
void (*main_monitor_changed) (MetaWindow *window,
|
||||
const MetaLogicalMonitor *old);
|
||||
void (*force_restore_shortcuts) (MetaWindow *window,
|
||||
@@ -768,8 +779,8 @@ void meta_window_activate_full (MetaWindow *window,
|
||||
MetaLogicalMonitor * meta_window_calculate_main_logical_monitor (MetaWindow *window);
|
||||
|
||||
MetaLogicalMonitor * meta_window_get_main_logical_monitor (MetaWindow *window);
|
||||
void meta_window_update_monitor (MetaWindow *window,
|
||||
gboolean user_op);
|
||||
void meta_window_update_monitor (MetaWindow *window,
|
||||
MetaWindowUpdateMonitorFlags flags);
|
||||
|
||||
void meta_window_set_urgent (MetaWindow *window,
|
||||
gboolean urgent);
|
||||
|
||||
@@ -119,6 +119,7 @@ static gboolean queue_calc_showing_func (MetaWindow *window,
|
||||
void *data);
|
||||
|
||||
static void meta_window_move_between_rects (MetaWindow *window,
|
||||
MetaMoveResizeFlags move_resize_flags,
|
||||
const MetaRectangle *old_area,
|
||||
const MetaRectangle *new_area);
|
||||
|
||||
@@ -1469,7 +1470,9 @@ meta_window_unmanage (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing default window since we're unmanaging %s\n",
|
||||
window->desc);
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace, NULL, timestamp);
|
||||
meta_workspace_focus_default_window (window->screen->active_workspace,
|
||||
window,
|
||||
timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3750,11 +3753,15 @@ maybe_move_attached_dialog (MetaWindow *window,
|
||||
*
|
||||
* Gets index of the monitor that this window is on.
|
||||
*
|
||||
* Return Value: The index of the monitor in the screens monitor list
|
||||
* Return Value: The index of the monitor in the screens monitor list, or -1
|
||||
* if the window has been recently unmanaged and does not have a monitor.
|
||||
*/
|
||||
int
|
||||
meta_window_get_monitor (MetaWindow *window)
|
||||
{
|
||||
if (!window->monitor)
|
||||
return -1;
|
||||
|
||||
return window->monitor->number;
|
||||
}
|
||||
|
||||
@@ -3802,7 +3809,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
|
||||
if (window->override_redirect || window->type == META_WINDOW_DESKTOP)
|
||||
{
|
||||
meta_window_update_monitor (window, FALSE);
|
||||
meta_window_update_monitor (window,
|
||||
META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3832,23 +3840,25 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
|
||||
* monitors changed and the same index could be refereing
|
||||
* to a different monitor. */
|
||||
meta_window_move_between_rects (window,
|
||||
META_MOVE_RESIZE_FORCE_UPDATE_MONITOR,
|
||||
&old->rect,
|
||||
&new->rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_update_monitor (window, FALSE);
|
||||
meta_window_update_monitor (window,
|
||||
META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_update_monitor (MetaWindow *window,
|
||||
gboolean user_op)
|
||||
meta_window_update_monitor (MetaWindow *window,
|
||||
MetaWindowUpdateMonitorFlags flags)
|
||||
{
|
||||
const MetaLogicalMonitor *old;
|
||||
|
||||
old = window->monitor;
|
||||
META_WINDOW_GET_CLASS (window)->update_main_monitor (window, user_op);
|
||||
META_WINDOW_GET_CLASS (window)->update_main_monitor (window, flags);
|
||||
if (old != window->monitor)
|
||||
{
|
||||
meta_window_on_all_workspaces_changed (window);
|
||||
@@ -3862,7 +3872,8 @@ meta_window_update_monitor (MetaWindow *window,
|
||||
* That should be handled by explicitly moving the window before changing the
|
||||
* workspace.
|
||||
*/
|
||||
if (meta_prefs_get_workspaces_only_on_primary () && user_op &&
|
||||
if (meta_prefs_get_workspaces_only_on_primary () &&
|
||||
flags & META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP &&
|
||||
meta_window_is_on_primary_monitor (window) &&
|
||||
window->screen->active_workspace != window->workspace)
|
||||
meta_window_change_workspace (window, window->screen->active_workspace);
|
||||
@@ -3905,6 +3916,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
MetaRectangle constrained_rect;
|
||||
MetaMoveResizeResultFlags result = 0;
|
||||
gboolean moved_or_resized = FALSE;
|
||||
MetaWindowUpdateMonitorFlags update_monitor_flags;
|
||||
|
||||
g_return_if_fail (!window->override_redirect);
|
||||
|
||||
@@ -4005,13 +4017,19 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
did_placement);
|
||||
}
|
||||
|
||||
update_monitor_flags = META_WINDOW_UPDATE_MONITOR_FLAGS_NONE;
|
||||
if (flags & META_MOVE_RESIZE_USER_ACTION)
|
||||
update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_USER_OP;
|
||||
if (flags & META_MOVE_RESIZE_FORCE_UPDATE_MONITOR)
|
||||
update_monitor_flags |= META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE;
|
||||
|
||||
if (window->monitor)
|
||||
{
|
||||
guint old_output_winsys_id;
|
||||
|
||||
old_output_winsys_id = window->monitor->winsys_id;
|
||||
|
||||
meta_window_update_monitor (window, flags & META_MOVE_RESIZE_USER_ACTION);
|
||||
meta_window_update_monitor (window, update_monitor_flags);
|
||||
|
||||
if (old_output_winsys_id != window->monitor->winsys_id &&
|
||||
flags & META_MOVE_RESIZE_MOVE_ACTION && flags & META_MOVE_RESIZE_USER_ACTION)
|
||||
@@ -4019,7 +4037,7 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_update_monitor (window, flags & META_MOVE_RESIZE_USER_ACTION);
|
||||
meta_window_update_monitor (window, update_monitor_flags);
|
||||
}
|
||||
|
||||
if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds)
|
||||
@@ -4063,6 +4081,7 @@ meta_window_move_frame (MetaWindow *window,
|
||||
|
||||
static void
|
||||
meta_window_move_between_rects (MetaWindow *window,
|
||||
MetaMoveResizeFlags move_resize_flags,
|
||||
const MetaRectangle *old_area,
|
||||
const MetaRectangle *new_area)
|
||||
{
|
||||
@@ -4086,7 +4105,12 @@ meta_window_move_between_rects (MetaWindow *window,
|
||||
window->saved_rect.x = window->unconstrained_rect.x;
|
||||
window->saved_rect.y = window->unconstrained_rect.y;
|
||||
|
||||
meta_window_move_resize_now (window);
|
||||
meta_window_move_resize_internal (window,
|
||||
move_resize_flags |
|
||||
META_MOVE_RESIZE_MOVE_ACTION |
|
||||
META_MOVE_RESIZE_RESIZE_ACTION,
|
||||
NorthWestGravity,
|
||||
window->unconstrained_rect);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4147,14 +4171,14 @@ meta_window_move_to_monitor (MetaWindow *window,
|
||||
window->unconstrained_rect.height == 0 ||
|
||||
!meta_rectangle_overlap (&window->unconstrained_rect, &old_area))
|
||||
{
|
||||
meta_window_move_between_rects (window, NULL, &new_area);
|
||||
meta_window_move_between_rects (window, 0, NULL, &new_area);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (monitor == window->monitor->number)
|
||||
return;
|
||||
|
||||
meta_window_move_between_rects (window, &old_area, &new_area);
|
||||
meta_window_move_between_rects (window, 0, &old_area, &new_area);
|
||||
}
|
||||
|
||||
window->preferred_output_winsys_id = window->monitor->winsys_id;
|
||||
@@ -4615,11 +4639,15 @@ meta_window_focus (MetaWindow *window,
|
||||
|
||||
g_return_if_fail (!window->override_redirect);
|
||||
|
||||
/* This is a oneshot flag */
|
||||
window->restore_focus_on_map = FALSE;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Setting input focus to window %s, input: %d take_focus: %d\n",
|
||||
window->desc, window->input, window->take_focus);
|
||||
|
||||
if (window->display->grab_window &&
|
||||
window->display->grab_window != window &&
|
||||
window->display->grab_window->all_keys_grabbed &&
|
||||
!window->display->grab_window->unmanaging)
|
||||
{
|
||||
@@ -7927,7 +7955,15 @@ meta_window_set_transient_for (MetaWindow *window,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (window->attached && parent == NULL)
|
||||
{
|
||||
guint32 timestamp;
|
||||
|
||||
timestamp =
|
||||
meta_display_get_current_time_roundtrip (window->display);
|
||||
meta_window_unmanage (window, timestamp);
|
||||
return;
|
||||
}
|
||||
/* We know this won't create a reference cycle because we check for loops */
|
||||
g_clear_object (&window->transient_for);
|
||||
window->transient_for = parent ? g_object_ref (parent) : NULL;
|
||||
|
||||
19
src/tests/stacking/closed-transient.metatest
Normal file
19
src/tests/stacking/closed-transient.metatest
Normal file
@@ -0,0 +1,19 @@
|
||||
new_client 1 wayland
|
||||
create 1/1
|
||||
show 1/1
|
||||
|
||||
new_client 2 wayland
|
||||
create 2/1
|
||||
show 2/1
|
||||
|
||||
create 1/2
|
||||
show 1/2
|
||||
set_parent 1/2 1
|
||||
|
||||
wait
|
||||
assert_stacking 1/1 2/1 1/2
|
||||
|
||||
destroy 1/2
|
||||
|
||||
wait
|
||||
assert_stacking 2/1 1/1
|
||||
@@ -47,10 +47,14 @@ meta_wayland_actor_surface_assigned (MetaWaylandSurfaceRole *surface_role)
|
||||
wl_list_init (&surface->pending_frame_callback_list);
|
||||
}
|
||||
|
||||
static void
|
||||
queue_surface_actor_frame_callbacks (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
void
|
||||
meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
MetaWaylandSurfaceRole *surface_role =
|
||||
META_WAYLAND_SURFACE_ROLE (actor_surface);
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaSurfaceActorWayland *surface_actor =
|
||||
META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
|
||||
|
||||
@@ -167,7 +171,7 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandSurface *toplevel_surface;
|
||||
|
||||
queue_surface_actor_frame_callbacks (surface, pending);
|
||||
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface, pending);
|
||||
|
||||
toplevel_surface = meta_wayland_surface_get_toplevel (surface);
|
||||
if (!toplevel_surface || !toplevel_surface->window)
|
||||
|
||||
@@ -40,4 +40,7 @@ void meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor
|
||||
|
||||
double meta_wayland_actor_surface_calculate_scale (MetaWaylandActorSurface *actor_surface);
|
||||
|
||||
void meta_wayland_actor_surface_queue_frame_callbacks (MetaWaylandActorSurface *actor_surface,
|
||||
MetaWaylandPendingState *pending);
|
||||
|
||||
#endif /* META_WAYLAND_ACTOR_SURFACE_H */
|
||||
|
||||
@@ -88,13 +88,13 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource)
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gboolean
|
||||
meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
return buffer->type != META_WAYLAND_BUFFER_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gboolean
|
||||
meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
{
|
||||
EGLint format;
|
||||
@@ -123,8 +123,17 @@ meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
|
||||
stream = meta_wayland_egl_stream_new (buffer, NULL);
|
||||
if (stream)
|
||||
{
|
||||
CoglTexture2D *texture;
|
||||
|
||||
texture = meta_wayland_egl_stream_create_texture (stream, NULL);
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
|
||||
buffer->egl_stream.stream = stream;
|
||||
buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
|
||||
buffer->texture = COGL_TEXTURE (texture);
|
||||
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -314,18 +323,6 @@ egl_stream_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
g_assert (stream);
|
||||
|
||||
if (!buffer->texture)
|
||||
{
|
||||
CoglTexture2D *texture;
|
||||
|
||||
texture = meta_wayland_egl_stream_create_texture (stream, error);
|
||||
if (!texture)
|
||||
return FALSE;
|
||||
|
||||
buffer->texture = COGL_TEXTURE (texture);
|
||||
buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);
|
||||
}
|
||||
|
||||
if (!meta_wayland_egl_stream_attach (stream, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -340,13 +337,11 @@ meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
|
||||
if (!meta_wayland_buffer_is_realized (buffer))
|
||||
{
|
||||
if (!meta_wayland_buffer_realize (buffer))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unknown buffer type");
|
||||
return FALSE;
|
||||
}
|
||||
/* The buffer should have been realized at surface commit time */
|
||||
g_set_error (error, G_IO_ERROR,
|
||||
G_IO_ERROR_FAILED,
|
||||
"Unknown buffer type");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (buffer->type)
|
||||
|
||||
@@ -68,6 +68,8 @@ G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer,
|
||||
META, WAYLAND_BUFFER, GObject);
|
||||
|
||||
MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource);
|
||||
gboolean meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_realize (MetaWaylandBuffer *buffer);
|
||||
gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer,
|
||||
GError **error);
|
||||
CoglTexture * meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer);
|
||||
|
||||
@@ -365,6 +365,7 @@ buffer_params_create_common (struct wl_client *client,
|
||||
dma_buf, NULL);
|
||||
buffer = meta_wayland_buffer_from_resource (buffer_resource);
|
||||
|
||||
meta_wayland_buffer_realize (buffer);
|
||||
if (!meta_wayland_buffer_attach (buffer, &error))
|
||||
{
|
||||
if (buffer_id == 0)
|
||||
|
||||
@@ -71,15 +71,13 @@ gtk_surface_set_dbus_properties (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = gtk_surface->surface;
|
||||
MetaWindow *window;
|
||||
|
||||
/* Broken client, let it die instead of us */
|
||||
if (!surface->window)
|
||||
{
|
||||
meta_warning ("meta-wayland-surface: set_dbus_properties called with invalid window!\n");
|
||||
return;
|
||||
}
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_set_gtk_dbus_properties (surface->window,
|
||||
meta_window_set_gtk_dbus_properties (window,
|
||||
application_id,
|
||||
unique_bus_name,
|
||||
app_menu_path,
|
||||
@@ -94,12 +92,17 @@ gtk_surface_set_modal (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = gtk_surface->surface;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (gtk_surface->is_modal)
|
||||
return;
|
||||
|
||||
gtk_surface->is_modal = TRUE;
|
||||
meta_window_set_type (surface->window, META_WINDOW_MODAL_DIALOG);
|
||||
meta_window_set_type (window, META_WINDOW_MODAL_DIALOG);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -108,12 +111,17 @@ gtk_surface_unset_modal (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = gtk_surface->surface;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!gtk_surface->is_modal)
|
||||
return;
|
||||
|
||||
gtk_surface->is_modal = FALSE;
|
||||
meta_window_set_type (surface->window, META_WINDOW_NORMAL);
|
||||
meta_window_set_type (window, META_WINDOW_NORMAL);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -123,8 +131,9 @@ gtk_surface_present (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandGtkSurface *gtk_surface = wl_resource_get_user_data (resource);
|
||||
MetaWaylandSurface *surface = gtk_surface->surface;
|
||||
MetaWindow *window = surface->window;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ unbind_resource (struct wl_resource *resource)
|
||||
}
|
||||
|
||||
static int
|
||||
create_anonymous_file (off_t size,
|
||||
create_anonymous_file (off_t size,
|
||||
GError **error)
|
||||
{
|
||||
static const char template[] = "mutter-shared-XXXXXX";
|
||||
@@ -126,35 +126,66 @@ create_anonymous_file (off_t size,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
send_keymap (MetaWaylandKeyboard *keyboard,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
||||
GError *error = NULL;
|
||||
int fd;
|
||||
char *keymap_area;
|
||||
|
||||
if (!xkb_info->keymap_string)
|
||||
return;
|
||||
|
||||
fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
||||
if (fd < 0)
|
||||
{
|
||||
g_warning ("Creating a keymap file for %lu bytes failed: %s",
|
||||
(unsigned long) xkb_info->keymap_size,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
keymap_area = mmap (NULL, xkb_info->keymap_size,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (keymap_area == MAP_FAILED)
|
||||
{
|
||||
g_warning ("Failed to mmap() %lu bytes\n",
|
||||
(unsigned long) xkb_info->keymap_size);
|
||||
close (fd);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy (keymap_area, xkb_info->keymap_string);
|
||||
|
||||
munmap (keymap_area, xkb_info->keymap_size);
|
||||
|
||||
wl_keyboard_send_keymap (resource,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
fd,
|
||||
keyboard->xkb_info.keymap_size);
|
||||
close (fd);
|
||||
}
|
||||
|
||||
static void
|
||||
inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard)
|
||||
{
|
||||
struct wl_resource *keyboard_resource;
|
||||
|
||||
wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
|
||||
{
|
||||
wl_keyboard_send_keymap (keyboard_resource,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
keyboard->xkb_info.keymap_fd,
|
||||
keyboard->xkb_info.keymap_size);
|
||||
}
|
||||
send_keymap (keyboard, keyboard_resource);
|
||||
wl_resource_for_each (keyboard_resource, &keyboard->focus_resource_list)
|
||||
{
|
||||
wl_keyboard_send_keymap (keyboard_resource,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
keyboard->xkb_info.keymap_fd,
|
||||
keyboard->xkb_info.keymap_size);
|
||||
}
|
||||
send_keymap (keyboard, keyboard_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||
struct xkb_keymap *keymap)
|
||||
{
|
||||
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
||||
GError *error = NULL;
|
||||
char *keymap_str;
|
||||
size_t previous_size;
|
||||
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
||||
|
||||
if (keymap == NULL)
|
||||
{
|
||||
@@ -162,60 +193,24 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&xkb_info->keymap_string, g_free);
|
||||
xkb_keymap_unref (xkb_info->keymap);
|
||||
xkb_info->keymap = xkb_keymap_ref (keymap);
|
||||
|
||||
meta_wayland_keyboard_update_xkb_state (keyboard);
|
||||
|
||||
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
||||
if (keymap_str == NULL)
|
||||
xkb_info->keymap_string =
|
||||
xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
|
||||
if (!xkb_info->keymap_string)
|
||||
{
|
||||
g_warning ("failed to get string version of keymap");
|
||||
g_warning ("Failed to get string version of keymap");
|
||||
return;
|
||||
}
|
||||
previous_size = xkb_info->keymap_size;
|
||||
xkb_info->keymap_size = strlen (keymap_str) + 1;
|
||||
|
||||
if (xkb_info->keymap_fd >= 0)
|
||||
close (xkb_info->keymap_fd);
|
||||
|
||||
xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
||||
if (xkb_info->keymap_fd < 0)
|
||||
{
|
||||
g_warning ("creating a keymap file for %lu bytes failed: %s",
|
||||
(unsigned long) xkb_info->keymap_size,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
goto err_keymap_str;
|
||||
}
|
||||
|
||||
if (xkb_info->keymap_area)
|
||||
munmap (xkb_info->keymap_area, previous_size);
|
||||
|
||||
xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, xkb_info->keymap_fd, 0);
|
||||
if (xkb_info->keymap_area == MAP_FAILED)
|
||||
{
|
||||
g_warning ("failed to mmap() %lu bytes\n",
|
||||
(unsigned long) xkb_info->keymap_size);
|
||||
goto err_dev_zero;
|
||||
}
|
||||
strcpy (xkb_info->keymap_area, keymap_str);
|
||||
free (keymap_str);
|
||||
xkb_info->keymap_size = strlen (xkb_info->keymap_string) + 1;
|
||||
|
||||
inform_clients_of_new_keymap (keyboard);
|
||||
|
||||
notify_modifiers (keyboard);
|
||||
|
||||
return;
|
||||
|
||||
err_dev_zero:
|
||||
close (xkb_info->keymap_fd);
|
||||
xkb_info->keymap_fd = -1;
|
||||
err_keymap_str:
|
||||
free (keymap_str);
|
||||
return;
|
||||
}
|
||||
|
||||
static xkb_mod_mask_t
|
||||
@@ -707,28 +702,12 @@ meta_wayland_keyboard_enable (MetaWaylandKeyboard *keyboard)
|
||||
maybe_restore_numlock_state (keyboard);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xkb_info_init (MetaWaylandXkbInfo *xkb_info)
|
||||
{
|
||||
xkb_info->keymap_fd = -1;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
|
||||
{
|
||||
g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref);
|
||||
g_clear_pointer (&xkb_info->state, xkb_state_unref);
|
||||
|
||||
if (xkb_info->keymap_area)
|
||||
{
|
||||
munmap (xkb_info->keymap_area, xkb_info->keymap_size);
|
||||
xkb_info->keymap_area = NULL;
|
||||
}
|
||||
if (xkb_info->keymap_fd >= 0)
|
||||
{
|
||||
close (xkb_info->keymap_fd);
|
||||
xkb_info->keymap_fd = -1;
|
||||
}
|
||||
g_clear_pointer (&xkb_info->keymap_string, g_free);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1001,10 +980,7 @@ meta_wayland_keyboard_create_new_resource (MetaWaylandKeyboard *keyboard,
|
||||
wl_resource_set_implementation (resource, &keyboard_interface,
|
||||
keyboard, unbind_resource);
|
||||
|
||||
wl_keyboard_send_keymap (resource,
|
||||
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||
keyboard->xkb_info.keymap_fd,
|
||||
keyboard->xkb_info.keymap_size);
|
||||
send_keymap (keyboard, resource);
|
||||
|
||||
notify_key_repeat_for_resource (keyboard, resource);
|
||||
|
||||
@@ -1050,8 +1026,6 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard)
|
||||
wl_list_init (&keyboard->resource_list);
|
||||
wl_list_init (&keyboard->focus_resource_list);
|
||||
|
||||
meta_wayland_xkb_info_init (&keyboard->xkb_info);
|
||||
|
||||
keyboard->default_grab.interface = &default_keyboard_grab_interface;
|
||||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
|
||||
@@ -74,9 +74,8 @@ typedef struct
|
||||
{
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
int keymap_fd;
|
||||
size_t keymap_size;
|
||||
char *keymap_area;
|
||||
char *keymap_string;
|
||||
} MetaWaylandXkbInfo;
|
||||
|
||||
struct _MetaWaylandKeyboard
|
||||
|
||||
@@ -185,6 +185,11 @@ zxdg_toplevel_v6_set_parent (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *transient_for = NULL;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (parent_resource)
|
||||
{
|
||||
@@ -194,7 +199,7 @@ zxdg_toplevel_v6_set_parent (struct wl_client *client,
|
||||
transient_for = parent_surface->window;
|
||||
}
|
||||
|
||||
meta_window_set_transient_for (surface->window, transient_for);
|
||||
meta_window_set_transient_for (window, transient_for);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -203,11 +208,16 @@ zxdg_toplevel_v6_set_title (struct wl_client *client,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!g_utf8_validate (title, -1, NULL))
|
||||
title = "";
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
meta_window_set_title (window, title);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -216,11 +226,16 @@ zxdg_toplevel_v6_set_app_id (struct wl_client *client,
|
||||
const char *app_id)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!g_utf8_validate (app_id, -1, NULL))
|
||||
app_id = "";
|
||||
|
||||
meta_window_set_wm_class (surface->window, app_id, app_id);
|
||||
meta_window_set_wm_class (window, app_id, app_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -233,15 +248,20 @@ zxdg_toplevel_v6_show_window_menu (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
int monitor_scale;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL))
|
||||
return;
|
||||
|
||||
monitor_scale = surface->window->monitor->scale;
|
||||
meta_window_show_menu (surface->window, META_WINDOW_MENU_WM,
|
||||
surface->window->buffer_rect.x + (x * monitor_scale),
|
||||
surface->window->buffer_rect.y + (y * monitor_scale));
|
||||
monitor_scale = window->monitor->scale;
|
||||
meta_window_show_menu (window, META_WINDOW_MENU_WM,
|
||||
window->buffer_rect.x + (x * monitor_scale),
|
||||
window->buffer_rect.y + (y * monitor_scale));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -252,8 +272,13 @@ zxdg_toplevel_v6_move (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
gfloat x, y;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
|
||||
return;
|
||||
|
||||
@@ -292,9 +317,14 @@ zxdg_toplevel_v6_resize (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
gfloat x, y;
|
||||
MetaGrabOp grab_op;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
|
||||
return;
|
||||
|
||||
@@ -309,6 +339,11 @@ zxdg_toplevel_v6_set_max_size (struct wl_client *client,
|
||||
int32_t height)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (width < 0 || height < 0)
|
||||
{
|
||||
@@ -331,6 +366,11 @@ zxdg_toplevel_v6_set_min_size (struct wl_client *client,
|
||||
int32_t height)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (width < 0 || height < 0)
|
||||
{
|
||||
@@ -351,9 +391,14 @@ zxdg_toplevel_v6_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_force_placement (surface->window, TRUE);
|
||||
meta_window_maximize (surface->window, META_MAXIMIZE_BOTH);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_force_placement (window, TRUE);
|
||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -361,8 +406,13 @@ zxdg_toplevel_v6_unset_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -371,15 +421,20 @@ zxdg_toplevel_v6_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *output_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (output_resource)
|
||||
{
|
||||
MetaWaylandOutput *output = wl_resource_get_user_data (output_resource);
|
||||
if (output)
|
||||
meta_window_move_to_monitor (surface->window, output->logical_monitor->number);
|
||||
meta_window_move_to_monitor (window, output->logical_monitor->number);
|
||||
}
|
||||
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
meta_window_make_fullscreen (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -387,8 +442,13 @@ zxdg_toplevel_v6_unset_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_unmake_fullscreen (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -396,8 +456,13 @@ zxdg_toplevel_v6_set_minimized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_minimize (surface->window);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_minimize (window);
|
||||
}
|
||||
|
||||
static const struct zxdg_toplevel_v6_interface meta_wayland_zxdg_toplevel_v6_interface = {
|
||||
@@ -598,11 +663,18 @@ meta_wayland_zxdg_toplevel_v6_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaWaylandSurfaceRoleClass *surface_role_class;
|
||||
MetaWaylandSurface *surface =
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWindow *window = surface->window;
|
||||
MetaWindow *window;
|
||||
MetaRectangle window_geometry;
|
||||
MetaRectangle old_geometry;
|
||||
gboolean geometry_changed;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
{
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
|
||||
return;
|
||||
}
|
||||
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
|
||||
@@ -365,12 +365,38 @@ meta_wayland_output_new (MetaWaylandCompositor *compositor,
|
||||
}
|
||||
|
||||
static void
|
||||
nullify_logical_monitor (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
make_output_resources_inert (MetaWaylandOutput *wayland_output)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = wayland_output->resources; l; l = l->next)
|
||||
{
|
||||
struct wl_resource *output_resource = l->data;
|
||||
|
||||
wl_resource_set_user_data (output_resource, NULL);
|
||||
}
|
||||
g_list_free (wayland_output->resources);
|
||||
wayland_output->resources = NULL;
|
||||
|
||||
for (l = wayland_output->xdg_output_resources; l; l = l->next)
|
||||
{
|
||||
struct wl_resource *xdg_output_resource = l->data;
|
||||
|
||||
wl_resource_set_user_data (xdg_output_resource, NULL);
|
||||
}
|
||||
g_list_free (wayland_output->xdg_output_resources);
|
||||
wayland_output->xdg_output_resources = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
make_output_inert (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWaylandOutput *wayland_output = value;
|
||||
|
||||
wayland_output->logical_monitor = NULL;
|
||||
make_output_resources_inert (wayland_output);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -420,7 +446,7 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor,
|
||||
wayland_output);
|
||||
}
|
||||
|
||||
g_hash_table_foreach (compositor->outputs, nullify_logical_monitor, NULL);
|
||||
g_hash_table_foreach (compositor->outputs, make_output_inert, NULL);
|
||||
g_timeout_add_seconds (10, delayed_destroy_outputs, compositor->outputs);
|
||||
|
||||
return new_table;
|
||||
@@ -449,23 +475,7 @@ meta_wayland_output_finalize (GObject *object)
|
||||
/* Make sure the wl_output destructor doesn't try to access MetaWaylandOutput
|
||||
* after we have freed it.
|
||||
*/
|
||||
for (l = wayland_output->resources; l; l = l->next)
|
||||
{
|
||||
struct wl_resource *output_resource = l->data;
|
||||
|
||||
wl_resource_set_user_data (output_resource, NULL);
|
||||
}
|
||||
|
||||
g_list_free (wayland_output->resources);
|
||||
|
||||
for (l = wayland_output->xdg_output_resources; l; l = l->next)
|
||||
{
|
||||
struct wl_resource *xdg_output_resource = l->data;
|
||||
|
||||
wl_resource_set_user_data (xdg_output_resource, NULL);
|
||||
}
|
||||
|
||||
g_list_free (wayland_output->xdg_output_resources);
|
||||
make_output_resources_inert (wayland_output);
|
||||
|
||||
G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object);
|
||||
}
|
||||
@@ -582,6 +592,9 @@ meta_xdg_output_manager_get_xdg_output (struct wl_client *client,
|
||||
wayland_output->xdg_output_resources =
|
||||
g_list_prepend (wayland_output->xdg_output_resources, xdg_output_resource);
|
||||
|
||||
if (!wayland_output->logical_monitor)
|
||||
return;
|
||||
|
||||
send_xdg_output_events (xdg_output_resource,
|
||||
wayland_output,
|
||||
wayland_output->logical_monitor,
|
||||
|
||||
@@ -83,7 +83,7 @@ meta_wayland_shell_surface_set_window (MetaWaylandShellSurface *shell_surface,
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
|
||||
meta_wayland_surface_set_window (surface, window);
|
||||
meta_window_update_monitor (window, FALSE);
|
||||
meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -602,6 +602,15 @@ parent_surface_state_applied (gpointer data,
|
||||
meta_wayland_subsurface_parent_state_applied (subsurface);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
{
|
||||
wl_list_insert_list (&surface->pending_frame_callback_list,
|
||||
&pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending)
|
||||
@@ -722,13 +731,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since there is no role assigned to the surface yet, keep frame
|
||||
* callbacks queued until a role is assigned and we know how
|
||||
* the surface will be drawn.
|
||||
*/
|
||||
wl_list_insert_list (&surface->pending_frame_callback_list,
|
||||
&pending->frame_callback_list);
|
||||
wl_list_init (&pending->frame_callback_list);
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
|
||||
|
||||
if (pending->newly_attached)
|
||||
{
|
||||
@@ -762,6 +765,10 @@ cleanup:
|
||||
static void
|
||||
meta_wayland_surface_commit (MetaWaylandSurface *surface)
|
||||
{
|
||||
if (surface->pending->buffer &&
|
||||
!meta_wayland_buffer_is_realized (surface->pending->buffer))
|
||||
meta_wayland_buffer_realize (surface->pending->buffer);
|
||||
|
||||
/*
|
||||
* If this is a sub-surface and it is in effective synchronous mode, only
|
||||
* cache the pending surface state until either one of the following two
|
||||
|
||||
@@ -261,6 +261,9 @@ MetaWaylandSurface *meta_wayland_surface_get_toplevel (MetaWaylandSurface *surfa
|
||||
|
||||
MetaWindow * meta_wayland_surface_get_toplevel_window (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_cache_pending_frame_callbacks (MetaWaylandSurface *surface,
|
||||
MetaWaylandPendingState *pending);
|
||||
|
||||
void meta_wayland_surface_queue_pending_frame_callbacks (MetaWaylandSurface *surface);
|
||||
|
||||
void meta_wayland_surface_queue_pending_state_frame_callbacks (MetaWaylandSurface *surface,
|
||||
|
||||
@@ -191,6 +191,11 @@ xdg_toplevel_set_parent (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *transient_for = NULL;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (parent_resource)
|
||||
{
|
||||
@@ -200,7 +205,7 @@ xdg_toplevel_set_parent (struct wl_client *client,
|
||||
transient_for = parent_surface->window;
|
||||
}
|
||||
|
||||
meta_window_set_transient_for (surface->window, transient_for);
|
||||
meta_window_set_transient_for (window, transient_for);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -209,11 +214,16 @@ xdg_toplevel_set_title (struct wl_client *client,
|
||||
const char *title)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!g_utf8_validate (title, -1, NULL))
|
||||
title = "";
|
||||
|
||||
meta_window_set_title (surface->window, title);
|
||||
meta_window_set_title (window, title);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -222,11 +232,16 @@ xdg_toplevel_set_app_id (struct wl_client *client,
|
||||
const char *app_id)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!g_utf8_validate (app_id, -1, NULL))
|
||||
app_id = "";
|
||||
|
||||
meta_window_set_wm_class (surface->window, app_id, app_id);
|
||||
meta_window_set_wm_class (window, app_id, app_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -239,15 +254,20 @@ xdg_toplevel_show_window_menu (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
int monitor_scale;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, FALSE, NULL, NULL))
|
||||
return;
|
||||
|
||||
monitor_scale = surface->window->monitor->scale;
|
||||
meta_window_show_menu (surface->window, META_WINDOW_MENU_WM,
|
||||
surface->window->buffer_rect.x + (x * monitor_scale),
|
||||
surface->window->buffer_rect.y + (y * monitor_scale));
|
||||
monitor_scale = window->monitor->scale;
|
||||
meta_window_show_menu (window, META_WINDOW_MENU_WM,
|
||||
window->buffer_rect.x + (x * monitor_scale),
|
||||
window->buffer_rect.y + (y * monitor_scale));
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -258,8 +278,13 @@ xdg_toplevel_move (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
float x, y;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
|
||||
return;
|
||||
|
||||
@@ -298,9 +323,14 @@ xdg_toplevel_resize (struct wl_client *client,
|
||||
{
|
||||
MetaWaylandSeat *seat = wl_resource_get_user_data (seat_resource);
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
gfloat x, y;
|
||||
MetaGrabOp grab_op;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (!meta_wayland_seat_get_grab_info (seat, surface, serial, TRUE, &x, &y))
|
||||
return;
|
||||
|
||||
@@ -357,7 +387,11 @@ xdg_toplevel_set_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window = surface->window;
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_force_placement (window, TRUE);
|
||||
meta_window_maximize (window, META_MAXIMIZE_BOTH);
|
||||
@@ -368,8 +402,13 @@ xdg_toplevel_unset_maximized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_unmaximize (surface->window, META_MAXIMIZE_BOTH);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_unmaximize (window, META_MAXIMIZE_BOTH);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -378,6 +417,11 @@ xdg_toplevel_set_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *output_resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
if (output_resource)
|
||||
{
|
||||
@@ -385,12 +429,12 @@ xdg_toplevel_set_fullscreen (struct wl_client *client,
|
||||
|
||||
if (output)
|
||||
{
|
||||
meta_window_move_to_monitor (surface->window,
|
||||
meta_window_move_to_monitor (window,
|
||||
output->logical_monitor->number);
|
||||
}
|
||||
}
|
||||
|
||||
meta_window_make_fullscreen (surface->window);
|
||||
meta_window_make_fullscreen (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -398,8 +442,13 @@ xdg_toplevel_unset_fullscreen (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_unmake_fullscreen (surface->window);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_unmake_fullscreen (window);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -407,8 +456,13 @@ xdg_toplevel_set_minimized (struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
|
||||
MetaWindow *window;
|
||||
|
||||
meta_window_minimize (surface->window);
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
meta_window_minimize (window);
|
||||
}
|
||||
|
||||
static const struct xdg_toplevel_interface meta_wayland_xdg_toplevel_interface = {
|
||||
@@ -624,13 +678,25 @@ meta_wayland_xdg_toplevel_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
MetaRectangle old_geometry;
|
||||
gboolean geometry_changed;
|
||||
|
||||
if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
|
||||
window = surface->window;
|
||||
if (!window)
|
||||
{
|
||||
meta_wayland_xdg_surface_reset (xdg_surface);
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
|
||||
{
|
||||
MetaWaylandActorSurface *actor_surface =
|
||||
META_WAYLAND_ACTOR_SURFACE (xdg_toplevel);
|
||||
|
||||
meta_wayland_xdg_surface_reset (xdg_surface);
|
||||
meta_wayland_actor_surface_queue_frame_callbacks (actor_surface,
|
||||
pending);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window = surface->window;
|
||||
old_geometry = xdg_surface_priv->geometry;
|
||||
|
||||
surface_role_class =
|
||||
@@ -957,6 +1023,7 @@ meta_wayland_xdg_popup_commit (MetaWaylandSurfaceRole *surface_role,
|
||||
if (!surface->buffer_ref.buffer && xdg_surface_priv->first_buffer_attached)
|
||||
{
|
||||
meta_wayland_xdg_surface_reset (xdg_surface);
|
||||
meta_wayland_surface_cache_pending_frame_callbacks (surface, pending);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -371,8 +371,8 @@ scale_rect_size (MetaRectangle *rect,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_wayland_update_main_monitor (MetaWindow *window,
|
||||
gboolean user_op)
|
||||
meta_window_wayland_update_main_monitor (MetaWindow *window,
|
||||
MetaWindowUpdateMonitorFlags flags)
|
||||
{
|
||||
MetaBackend *backend = meta_get_backend ();
|
||||
MetaMonitorManager *monitor_manager =
|
||||
@@ -392,7 +392,7 @@ meta_window_wayland_update_main_monitor (MetaWindow *window,
|
||||
toplevel_window = meta_wayland_surface_get_toplevel_window (window->surface);
|
||||
if (toplevel_window != window)
|
||||
{
|
||||
meta_window_update_monitor (toplevel_window, user_op);
|
||||
meta_window_update_monitor (toplevel_window, flags);
|
||||
window->monitor = toplevel_window->monitor;
|
||||
return;
|
||||
}
|
||||
@@ -413,6 +413,12 @@ meta_window_wayland_update_main_monitor (MetaWindow *window,
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & META_WINDOW_UPDATE_MONITOR_FLAGS_FORCE)
|
||||
{
|
||||
window->monitor = to;
|
||||
return;
|
||||
}
|
||||
|
||||
from_scale = meta_logical_monitor_get_scale (from);
|
||||
to_scale = meta_logical_monitor_get_scale (to);
|
||||
|
||||
|
||||
@@ -85,6 +85,13 @@ meta_xwayland_keyboard_grab_end (MetaXwaylandKeyboardActiveGrab *active_grab)
|
||||
{
|
||||
MetaWaylandSeat *seat = active_grab->seat;
|
||||
|
||||
if (seat->keyboard->grab->interface->key == meta_xwayland_keyboard_grab_key)
|
||||
{
|
||||
meta_wayland_keyboard_end_grab (active_grab->keyboard_grab.keyboard);
|
||||
meta_wayland_keyboard_set_focus (active_grab->keyboard_grab.keyboard, NULL);
|
||||
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||
}
|
||||
|
||||
if (!active_grab->surface)
|
||||
return;
|
||||
|
||||
@@ -104,13 +111,6 @@ meta_xwayland_keyboard_grab_end (MetaXwaylandKeyboardActiveGrab *active_grab)
|
||||
active_grab->window_associate_handler = 0;
|
||||
}
|
||||
|
||||
if (seat->keyboard->grab->interface->key == meta_xwayland_keyboard_grab_key)
|
||||
{
|
||||
meta_wayland_keyboard_end_grab (active_grab->keyboard_grab.keyboard);
|
||||
meta_wayland_keyboard_set_focus (active_grab->keyboard_grab.keyboard, NULL);
|
||||
meta_display_sync_wayland_input_focus (meta_get_display ());
|
||||
}
|
||||
|
||||
active_grab->surface = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1365,6 +1365,12 @@ handle_other_xevent (MetaDisplay *display,
|
||||
window = meta_window_x11_new (display, event->xmap.window,
|
||||
FALSE, META_COMP_EFFECT_CREATE);
|
||||
}
|
||||
else if (window && window->restore_focus_on_map)
|
||||
{
|
||||
meta_window_focus (window,
|
||||
meta_display_get_current_time_roundtrip (display));
|
||||
}
|
||||
|
||||
break;
|
||||
case MapRequest:
|
||||
if (window == NULL)
|
||||
|
||||
@@ -1483,8 +1483,8 @@ meta_window_x11_update_icon (MetaWindow *window,
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_x11_update_main_monitor (MetaWindow *window,
|
||||
gboolean user_op)
|
||||
meta_window_x11_update_main_monitor (MetaWindow *window,
|
||||
MetaWindowUpdateMonitorFlags flags)
|
||||
{
|
||||
window->monitor = meta_window_calculate_main_logical_monitor (window);
|
||||
}
|
||||
@@ -3314,7 +3314,7 @@ meta_window_x11_configure_notify (MetaWindow *window,
|
||||
priv->client_rect = window->rect;
|
||||
window->buffer_rect = window->rect;
|
||||
|
||||
meta_window_update_monitor (window, FALSE);
|
||||
meta_window_update_monitor (window, META_WINDOW_UPDATE_MONITOR_FLAGS_NONE);
|
||||
|
||||
/* Whether an override-redirect window is considered fullscreen depends
|
||||
* on its geometry.
|
||||
|
||||
Reference in New Issue
Block a user