stage: Add state tracking

State changes on the Stage are currently deferred to the windowing
system backends, but the code is generally the same, and it should
be abstracted neatly inside the Stage class itself.

There's also the extra caveat for backends that state changes on a
Stage must also emit a ClutterEvent of type CLUTTER_STAGE_STATE, a
requirement that needlessly complicates the backend code.
This commit is contained in:
Emmanuele Bassi 2012-01-25 21:24:47 +00:00
parent a4d571aaf9
commit 19ff11ac93
2 changed files with 111 additions and 17 deletions

View File

@ -109,6 +109,13 @@ ClutterActor * _clutter_stage_get_drag_actor (ClutterStage *sta
void _clutter_stage_remove_drag_actor (ClutterStage *stage,
ClutterInputDevice *device);
ClutterStageState _clutter_stage_get_state (ClutterStage *stage);
gboolean _clutter_stage_is_activated (ClutterStage *stage);
gboolean _clutter_stage_is_fullscreen (ClutterStage *stage);
gboolean _clutter_stage_update_state (ClutterStage *stage,
ClutterStageState unset_state,
ClutterStageState set_state);
G_END_DECLS
#endif /* __CLUTTER_STAGE_PRIVATE_H__ */

View File

@ -121,32 +121,33 @@ struct _ClutterStagePrivate
/* the stage implementation */
ClutterStageWindow *impl;
ClutterColor color;
ClutterPerspective perspective;
CoglMatrix projection;
CoglMatrix inverse_projection;
CoglMatrix view;
float viewport[4];
ClutterFog fog;
ClutterColor color;
ClutterPerspective perspective;
CoglMatrix projection;
CoglMatrix inverse_projection;
CoglMatrix view;
float viewport[4];
gchar *title;
ClutterActor *key_focused_actor;
ClutterFog fog;
GQueue *event_queue;
gchar *title;
ClutterActor *key_focused_actor;
ClutterStageHint stage_hints;
GQueue *event_queue;
gint picks_per_frame;
ClutterStageHint stage_hints;
GArray *paint_volume_stack;
gint picks_per_frame;
ClutterPlane current_clip_planes[4];
GArray *paint_volume_stack;
GList *pending_queue_redraws;
ClutterPlane current_clip_planes[4];
ClutterPickMode pick_buffer_mode;
GList *pending_queue_redraws;
CoglFramebuffer *active_framebuffer;
ClutterPickMode pick_buffer_mode;
CoglFramebuffer *active_framebuffer;
GHashTable *devices;
@ -159,6 +160,8 @@ struct _ClutterStagePrivate
gulong redraw_count;
#endif /* CLUTTER_ENABLE_DEBUG */
ClutterStageState current_state;
guint relayout_pending : 1;
guint redraw_pending : 1;
guint is_fullscreen : 1;
@ -4397,3 +4400,87 @@ _clutter_stage_remove_drag_actor (ClutterStage *stage,
if (g_hash_table_size (drag_actors) == 0)
g_object_set_data (G_OBJECT (stage), "__clutter_stage_drag_actors", NULL);
}
/*< private >
* _clutter_stage_get_state:
* @stage: a #ClutterStage
*
* Retrieves the current #ClutterStageState flags associated to the @stage.
*
* Return value: a bitwise OR of #ClutterStageState flags
*/
ClutterStageState
_clutter_stage_get_state (ClutterStage *stage)
{
return stage->priv->current_state;
}
/*< private >
* _clutter_stage_is_activated:
* @stage: a #ClutterStage
*
* Checks whether the @stage state includes %CLUTTER_STAGE_STATE_ACTIVATED.
*
* Return value: %TRUE if the @stage is active
*/
gboolean
_clutter_stage_is_activated (ClutterStage *stage)
{
return (stage->priv->current_state & CLUTTER_STAGE_STATE_ACTIVATED) != 0;
}
/*< private >
* _clutter_stage_is_fullscreen:
* @stage: a #ClutterStage
*
* Checks whether the @stage state includes %CLUTTER_STAGE_STATE_FULLSCREEN.
*
* Return value: %TRUE if the @stage is fullscreen
*/
gboolean
_clutter_stage_is_fullscreen (ClutterStage *stage)
{
return (stage->priv->current_state & CLUTTER_STAGE_STATE_FULLSCREEN) != 0;
}
/*< private >
* _clutter_stage_update_state:
* @stage: a #ClutterStage
* @unset_flags: flags to unset
* @set_flags: flags to set
*
* Updates the state of @stage, by unsetting the @unset_flags and setting
* the @set_flags.
*
* If the stage state has been changed, this function will queue a
* #ClutterEvent of type %CLUTTER_STAGE_STATE.
*
* Return value: %TRUE if the state was updated, and %FALSE otherwise
*/
gboolean
_clutter_stage_update_state (ClutterStage *stage,
ClutterStageState unset_flags,
ClutterStageState set_flags)
{
ClutterStageState new_state;
ClutterEvent *event;
new_state = stage->priv->current_state;
new_state |= set_flags;
new_state &= ~unset_flags;
if (new_state == stage->priv->current_state)
return FALSE;
event = clutter_event_new (CLUTTER_STAGE_STATE);
clutter_event_set_stage (event, stage);
event->stage_state.new_state = new_state;
event->stage_state.changed_mask = new_state ^ stage->priv->current_state;
stage->priv->current_state = new_state;
_clutter_event_push (event, FALSE);
return TRUE;
}