mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
ae83a61e67
With the introduction of the shallow relayout mechanism another small but severe regression sneaked into our layout machinery: We might allocate an actor twice during the same allocation cycle, with one allocation happening using the wrong parent. This issue happens when reparenting an actor from a NO_LAYOUT parent to a non-NO_LAYOUT parent, in particular it triggered a bug in gnome-shell when DND reparents a child from the NO_LAYOUT uiGroup to the overviews Workspace actor after a drag ended. The reason the issue happens is the following chain of events: 1. child of a NO_LAYOUT parent queues a relayout, this child is added to the priv->pending_relayouts list maintained by ClutterStage 2. child is reparented to a different parent which doesn't have the NO_LAYOUT flag set, another relayout is queued, this time a different actor is added to the priv->pending_relayouts list 3. the relayout happens and we go through the pending_relayouts list backwards, that means the correct relayout queued during 2. happens first, then the old one happens and we simply call clutter_actor_allocate_preferred_size() on the actor, that allocation overrides the other, correct one. So fix that issue by adding a method to ClutterStage which removes actors from the pending_relayouts list again and call this method as soon as an actor with a NO_LAYOUT parent is detached from the stage. With that in place, we can also remove the check whether an actor is still on stage while looping through pending_relayouts. In case something else is going wrong and the actor is not on stage, clutter_actor_allocate() will warn anyway. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1356
155 lines
8.5 KiB
C
155 lines
8.5 KiB
C
/*
|
|
* Clutter.
|
|
*
|
|
* An OpenGL based 'interactive canvas' library.
|
|
*
|
|
* Copyright (C) 2010 Intel Corporation.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __CLUTTER_STAGE_PRIVATE_H__
|
|
#define __CLUTTER_STAGE_PRIVATE_H__
|
|
|
|
#include <clutter/clutter-stage-window.h>
|
|
#include <clutter/clutter-stage.h>
|
|
#include <clutter/clutter-input-device.h>
|
|
#include <clutter/clutter-private.h>
|
|
|
|
#include <cogl/cogl.h>
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
typedef struct _ClutterStageQueueRedrawEntry ClutterStageQueueRedrawEntry;
|
|
|
|
/* stage */
|
|
ClutterStageWindow *_clutter_stage_get_default_window (void);
|
|
|
|
void clutter_stage_paint_view (ClutterStage *stage,
|
|
ClutterStageView *view,
|
|
const cairo_region_t *redraw_clip);
|
|
|
|
void clutter_stage_emit_before_update (ClutterStage *stage,
|
|
ClutterStageView *view);
|
|
void clutter_stage_emit_before_paint (ClutterStage *stage,
|
|
ClutterStageView *view);
|
|
void clutter_stage_emit_after_paint (ClutterStage *stage,
|
|
ClutterStageView *view);
|
|
void clutter_stage_emit_after_update (ClutterStage *stage,
|
|
ClutterStageView *view);
|
|
|
|
CLUTTER_EXPORT
|
|
void _clutter_stage_set_window (ClutterStage *stage,
|
|
ClutterStageWindow *stage_window);
|
|
CLUTTER_EXPORT
|
|
ClutterStageWindow *_clutter_stage_get_window (ClutterStage *stage);
|
|
void _clutter_stage_get_projection_matrix (ClutterStage *stage,
|
|
CoglMatrix *projection);
|
|
void _clutter_stage_dirty_projection (ClutterStage *stage);
|
|
void _clutter_stage_get_viewport (ClutterStage *stage,
|
|
float *x,
|
|
float *y,
|
|
float *width,
|
|
float *height);
|
|
void _clutter_stage_dirty_viewport (ClutterStage *stage);
|
|
void _clutter_stage_maybe_setup_viewport (ClutterStage *stage,
|
|
ClutterStageView *view);
|
|
void clutter_stage_maybe_relayout (ClutterActor *stage);
|
|
void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
|
|
GSList * clutter_stage_find_updated_devices (ClutterStage *stage);
|
|
void clutter_stage_update_devices (ClutterStage *stage,
|
|
GSList *devices);
|
|
void clutter_stage_update_actor_stage_views (ClutterStage *stage);
|
|
|
|
CLUTTER_EXPORT
|
|
void _clutter_stage_queue_event (ClutterStage *stage,
|
|
ClutterEvent *event,
|
|
gboolean copy_event);
|
|
gboolean _clutter_stage_has_queued_events (ClutterStage *stage);
|
|
void _clutter_stage_process_queued_events (ClutterStage *stage);
|
|
void _clutter_stage_update_input_devices (ClutterStage *stage);
|
|
gboolean _clutter_stage_has_full_redraw_queued (ClutterStage *stage);
|
|
|
|
void clutter_stage_log_pick (ClutterStage *stage,
|
|
const graphene_point_t *vertices,
|
|
ClutterActor *actor);
|
|
|
|
void clutter_stage_push_pick_clip (ClutterStage *stage,
|
|
const graphene_point_t *vertices);
|
|
|
|
void clutter_stage_pop_pick_clip (ClutterStage *stage);
|
|
|
|
ClutterActor *_clutter_stage_do_pick (ClutterStage *stage,
|
|
float x,
|
|
float y,
|
|
ClutterPickMode mode);
|
|
|
|
ClutterPaintVolume *_clutter_stage_paint_volume_stack_allocate (ClutterStage *stage);
|
|
void _clutter_stage_paint_volume_stack_free_all (ClutterStage *stage);
|
|
|
|
const ClutterPlane *_clutter_stage_get_clip (ClutterStage *stage);
|
|
|
|
ClutterStageQueueRedrawEntry *_clutter_stage_queue_actor_redraw (ClutterStage *stage,
|
|
ClutterStageQueueRedrawEntry *entry,
|
|
ClutterActor *actor,
|
|
const ClutterPaintVolume *clip);
|
|
void _clutter_stage_queue_redraw_entry_invalidate (ClutterStageQueueRedrawEntry *entry);
|
|
|
|
void _clutter_stage_add_pointer_drag_actor (ClutterStage *stage,
|
|
ClutterInputDevice *device,
|
|
ClutterActor *actor);
|
|
ClutterActor * _clutter_stage_get_pointer_drag_actor (ClutterStage *stage,
|
|
ClutterInputDevice *device);
|
|
void _clutter_stage_remove_pointer_drag_actor (ClutterStage *stage,
|
|
ClutterInputDevice *device);
|
|
|
|
void _clutter_stage_add_touch_drag_actor (ClutterStage *stage,
|
|
ClutterEventSequence *sequence,
|
|
ClutterActor *actor);
|
|
ClutterActor * _clutter_stage_get_touch_drag_actor (ClutterStage *stage,
|
|
ClutterEventSequence *sequence);
|
|
void _clutter_stage_remove_touch_drag_actor (ClutterStage *stage,
|
|
ClutterEventSequence *sequence);
|
|
|
|
CLUTTER_EXPORT
|
|
ClutterStageState _clutter_stage_get_state (ClutterStage *stage);
|
|
CLUTTER_EXPORT
|
|
gboolean _clutter_stage_is_activated (ClutterStage *stage);
|
|
CLUTTER_EXPORT
|
|
gboolean _clutter_stage_update_state (ClutterStage *stage,
|
|
ClutterStageState unset_state,
|
|
ClutterStageState set_state);
|
|
|
|
void _clutter_stage_set_scale_factor (ClutterStage *stage,
|
|
int factor);
|
|
|
|
void clutter_stage_presented (ClutterStage *stage,
|
|
ClutterStageView *view,
|
|
ClutterFrameInfo *frame_info);
|
|
|
|
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
|
|
ClutterActor *actor);
|
|
|
|
void clutter_stage_dequeue_actor_relayout (ClutterStage *stage,
|
|
ClutterActor *actor);
|
|
|
|
GList * clutter_stage_get_views_for_rect (ClutterStage *stage,
|
|
const graphene_rect_t *rect);
|
|
|
|
void clutter_stage_set_actor_needs_immediate_relayout (ClutterStage *stage);
|
|
|
|
G_END_DECLS
|
|
|
|
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */
|