mirror of
https://github.com/brl/mutter.git
synced 2024-12-26 04:42:14 +00:00
clutter: Remove stage fullscreening
Another unneeded feature related to clutter originally being an application library that we have no use for when we're only ever a compositor. https://gitlab.gnome.org/GNOME/mutter/merge_requests/616
This commit is contained in:
parent
4064d9a7a7
commit
a61d525111
@ -974,7 +974,6 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
|
||||
|
||||
/**
|
||||
* ClutterStageState:
|
||||
* @CLUTTER_STAGE_STATE_FULLSCREEN: Fullscreen mask
|
||||
* @CLUTTER_STAGE_STATE_OFFSCREEN: Offscreen mask (deprecated)
|
||||
* @CLUTTER_STAGE_STATE_ACTIVATED: Activated mask
|
||||
*
|
||||
@ -984,7 +983,6 @@ typedef enum /*< prefix=CLUTTER_SCROLL >*/
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_STAGE_STATE_FULLSCREEN = (1 << 1),
|
||||
CLUTTER_STAGE_STATE_OFFSCREEN = (1 << 2),
|
||||
CLUTTER_STAGE_STATE_ACTIVATED = (1 << 3)
|
||||
} ClutterStageState;
|
||||
|
@ -2552,7 +2552,7 @@ _clutter_process_event_details (ClutterActor *stage,
|
||||
break;
|
||||
|
||||
case CLUTTER_STAGE_STATE:
|
||||
/* fullscreen / focus - forward to stage */
|
||||
/* focus - forward to stage */
|
||||
event->any.source = stage;
|
||||
if (!_clutter_event_process_filters (event))
|
||||
clutter_stage_event (CLUTTER_STAGE (stage), event);
|
||||
|
@ -117,7 +117,6 @@ void _clutter_stage_remove_touch_drag_actor (ClutterStage *st
|
||||
|
||||
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);
|
||||
|
@ -62,16 +62,6 @@ _clutter_stage_window_set_title (ClutterStageWindow *window,
|
||||
iface->set_title (window, title);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_set_fullscreen (ClutterStageWindow *window,
|
||||
gboolean is_fullscreen)
|
||||
{
|
||||
ClutterStageWindowInterface *iface = CLUTTER_STAGE_WINDOW_GET_IFACE (window);
|
||||
|
||||
if (iface->set_fullscreen)
|
||||
iface->set_fullscreen (window, is_fullscreen);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
|
||||
gboolean is_visible)
|
||||
|
@ -30,8 +30,6 @@ struct _ClutterStageWindowInterface
|
||||
|
||||
void (* set_title) (ClutterStageWindow *stage_window,
|
||||
const gchar *title);
|
||||
void (* set_fullscreen) (ClutterStageWindow *stage_window,
|
||||
gboolean is_fullscreen);
|
||||
void (* set_cursor_visible) (ClutterStageWindow *stage_window,
|
||||
gboolean cursor_visible);
|
||||
|
||||
@ -81,8 +79,6 @@ ClutterActor * _clutter_stage_window_get_wrapper (ClutterStageWindow *
|
||||
|
||||
void _clutter_stage_window_set_title (ClutterStageWindow *window,
|
||||
const gchar *title);
|
||||
void _clutter_stage_window_set_fullscreen (ClutterStageWindow *window,
|
||||
gboolean is_fullscreen);
|
||||
void _clutter_stage_window_set_cursor_visible (ClutterStageWindow *window,
|
||||
gboolean is_visible);
|
||||
|
||||
|
@ -152,7 +152,6 @@ struct _ClutterStagePrivate
|
||||
|
||||
guint relayout_pending : 1;
|
||||
guint redraw_pending : 1;
|
||||
guint is_fullscreen : 1;
|
||||
guint is_cursor_visible : 1;
|
||||
guint use_fog : 1;
|
||||
guint throttle_motion_events : 1;
|
||||
@ -169,7 +168,6 @@ enum
|
||||
PROP_0,
|
||||
|
||||
PROP_COLOR,
|
||||
PROP_FULLSCREEN_SET,
|
||||
PROP_OFFSCREEN,
|
||||
PROP_CURSOR_VISIBLE,
|
||||
PROP_PERSPECTIVE,
|
||||
@ -184,8 +182,6 @@ enum
|
||||
|
||||
enum
|
||||
{
|
||||
FULLSCREEN,
|
||||
UNFULLSCREEN,
|
||||
ACTIVATE,
|
||||
DEACTIVATE,
|
||||
DELETE_EVENT,
|
||||
@ -402,40 +398,37 @@ clutter_stage_allocate (ClutterActor *self,
|
||||
flags | CLUTTER_DELEGATE_LAYOUT);
|
||||
|
||||
/* Ensure the window is sized correctly */
|
||||
if (!priv->is_fullscreen)
|
||||
if (priv->min_size_changed)
|
||||
{
|
||||
if (priv->min_size_changed)
|
||||
{
|
||||
gfloat min_width, min_height;
|
||||
gboolean min_width_set, min_height_set;
|
||||
gfloat min_width, min_height;
|
||||
gboolean min_width_set, min_height_set;
|
||||
|
||||
g_object_get (G_OBJECT (self),
|
||||
"min-width", &min_width,
|
||||
"min-width-set", &min_width_set,
|
||||
"min-height", &min_height,
|
||||
"min-height-set", &min_height_set,
|
||||
NULL);
|
||||
g_object_get (G_OBJECT (self),
|
||||
"min-width", &min_width,
|
||||
"min-width-set", &min_width_set,
|
||||
"min-height", &min_height,
|
||||
"min-height-set", &min_height_set,
|
||||
NULL);
|
||||
|
||||
if (!min_width_set)
|
||||
min_width = 1;
|
||||
if (!min_height_set)
|
||||
min_height = 1;
|
||||
if (!min_width_set)
|
||||
min_width = 1;
|
||||
if (!min_height_set)
|
||||
min_height = 1;
|
||||
|
||||
if (width < min_width)
|
||||
width = min_width;
|
||||
if (height < min_height)
|
||||
height = min_height;
|
||||
if (width < min_width)
|
||||
width = min_width;
|
||||
if (height < min_height)
|
||||
height = min_height;
|
||||
|
||||
priv->min_size_changed = FALSE;
|
||||
}
|
||||
priv->min_size_changed = FALSE;
|
||||
}
|
||||
|
||||
if (window_size.width != CLUTTER_NEARBYINT (width) ||
|
||||
window_size.height != CLUTTER_NEARBYINT (height))
|
||||
{
|
||||
_clutter_stage_window_resize (priv->impl,
|
||||
CLUTTER_NEARBYINT (width),
|
||||
CLUTTER_NEARBYINT (height));
|
||||
}
|
||||
if (window_size.width != CLUTTER_NEARBYINT (width) ||
|
||||
window_size.height != CLUTTER_NEARBYINT (height))
|
||||
{
|
||||
_clutter_stage_window_resize (priv->impl,
|
||||
CLUTTER_NEARBYINT (width),
|
||||
CLUTTER_NEARBYINT (height));
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -845,40 +838,6 @@ clutter_stage_real_deactivate (ClutterStage *stage)
|
||||
clutter_stage_emit_key_focus_event (stage, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_real_fullscreen (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
cairo_rectangle_int_t geom;
|
||||
ClutterActorBox box;
|
||||
|
||||
/* we need to force an allocation here because the size
|
||||
* of the stage might have been changed by the backend
|
||||
*
|
||||
* this is a really bad solution to the issues caused by
|
||||
* the fact that fullscreening the stage on the X11 backends
|
||||
* is really an asynchronous operation
|
||||
*/
|
||||
_clutter_stage_window_get_geometry (priv->impl, &geom);
|
||||
|
||||
box.x1 = 0;
|
||||
box.y1 = 0;
|
||||
box.x2 = geom.width;
|
||||
box.y2 = geom.height;
|
||||
|
||||
/* we need to blow the caching on the Stage size, given that
|
||||
* we're about to force an allocation, because if anything
|
||||
* ends up querying the size of the stage during the allocate()
|
||||
* call, like constraints or signal handlers, we'll get into an
|
||||
* inconsistent state: the stage will report the old cached size,
|
||||
* but the allocation will be updated anyway.
|
||||
*/
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (stage), -1.0, -1.0);
|
||||
clutter_actor_allocate (CLUTTER_ACTOR (stage),
|
||||
&box,
|
||||
CLUTTER_ALLOCATION_NONE);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_queue_event (ClutterStage *stage,
|
||||
ClutterEvent *event,
|
||||
@ -1790,10 +1749,6 @@ clutter_stage_get_property (GObject *gobject,
|
||||
g_value_set_boolean (value, FALSE);
|
||||
break;
|
||||
|
||||
case PROP_FULLSCREEN_SET:
|
||||
g_value_set_boolean (value, priv->is_fullscreen);
|
||||
break;
|
||||
|
||||
case PROP_CURSOR_VISIBLE:
|
||||
g_value_set_boolean (value, priv->is_cursor_visible);
|
||||
break;
|
||||
@ -1929,27 +1884,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
actor_class->queue_redraw = clutter_stage_real_queue_redraw;
|
||||
actor_class->apply_transform = clutter_stage_real_apply_transform;
|
||||
|
||||
/**
|
||||
* ClutterStage:fullscreen:
|
||||
*
|
||||
* Whether the stage should be fullscreen or not.
|
||||
*
|
||||
* This property is set by calling clutter_stage_set_fullscreen()
|
||||
* but since the actual implementation is delegated to the backend
|
||||
* you should connect to the notify::fullscreen-set signal in order
|
||||
* to get notification if the fullscreen state has been successfully
|
||||
* achieved.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("fullscreen-set",
|
||||
P_("Fullscreen Set"),
|
||||
P_("Whether the main stage is fullscreen"),
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READABLE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FULLSCREEN_SET,
|
||||
pspec);
|
||||
/**
|
||||
* ClutterStage:offscreen:
|
||||
*
|
||||
@ -2125,39 +2059,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_ACCEPT_FOCUS, pspec);
|
||||
|
||||
/**
|
||||
* ClutterStage::fullscreen:
|
||||
* @stage: the stage which was fullscreened
|
||||
*
|
||||
* The ::fullscreen signal is emitted when the stage is made fullscreen.
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
stage_signals[FULLSCREEN] =
|
||||
g_signal_new (I_("fullscreen"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (ClutterStageClass, fullscreen),
|
||||
NULL, NULL,
|
||||
_clutter_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
/**
|
||||
* ClutterStage::unfullscreen:
|
||||
* @stage: the stage which has left a fullscreen state.
|
||||
*
|
||||
* The ::unfullscreen signal is emitted when the stage leaves a fullscreen
|
||||
* state.
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
stage_signals[UNFULLSCREEN] =
|
||||
g_signal_new (I_("unfullscreen"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterStageClass, unfullscreen),
|
||||
NULL, NULL,
|
||||
_clutter_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
/**
|
||||
* ClutterStage::activate:
|
||||
* @stage: the stage which was activated
|
||||
@ -2258,7 +2159,6 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
G_TYPE_NONE, 2,
|
||||
G_TYPE_INT, G_TYPE_POINTER);
|
||||
|
||||
klass->fullscreen = clutter_stage_real_fullscreen;
|
||||
klass->activate = clutter_stage_real_activate;
|
||||
klass->deactivate = clutter_stage_real_deactivate;
|
||||
klass->delete_event = clutter_stage_real_delete_event;
|
||||
@ -2309,7 +2209,6 @@ clutter_stage_init (ClutterStage *self)
|
||||
|
||||
priv->event_queue = g_queue_new ();
|
||||
|
||||
priv->is_fullscreen = FALSE;
|
||||
priv->is_cursor_visible = TRUE;
|
||||
priv->use_fog = FALSE;
|
||||
priv->throttle_motion_events = TRUE;
|
||||
@ -2705,80 +2604,6 @@ _clutter_stage_get_viewport (ClutterStage *stage,
|
||||
*height = priv->viewport[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_set_fullscreen:
|
||||
* @stage: a #ClutterStage
|
||||
* @fullscreen: %TRUE to to set the stage fullscreen
|
||||
*
|
||||
* Asks to place the stage window in the fullscreen or unfullscreen
|
||||
* states.
|
||||
*
|
||||
( Note that you shouldn't assume the window is definitely full screen
|
||||
* afterward, because other entities (e.g. the user or window manager)
|
||||
* could unfullscreen it again, and not all window managers honor
|
||||
* requests to fullscreen windows.
|
||||
*
|
||||
* If you want to receive notification of the fullscreen state you
|
||||
* should either use the #ClutterStage::fullscreen and
|
||||
* #ClutterStage::unfullscreen signals, or use the notify signal
|
||||
* for the #ClutterStage:fullscreen-set property
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_stage_set_fullscreen (ClutterStage *stage,
|
||||
gboolean fullscreen)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
priv = stage->priv;
|
||||
|
||||
if (priv->is_fullscreen != fullscreen)
|
||||
{
|
||||
ClutterStageWindow *impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
ClutterStageWindowInterface *iface;
|
||||
|
||||
iface = CLUTTER_STAGE_WINDOW_GET_IFACE (impl);
|
||||
|
||||
/* Only set if backend implements.
|
||||
*
|
||||
* Also see clutter_stage_event() for setting priv->is_fullscreen
|
||||
* on state change event.
|
||||
*/
|
||||
if (iface->set_fullscreen)
|
||||
iface->set_fullscreen (impl, fullscreen);
|
||||
}
|
||||
|
||||
/* If the backend did fullscreen the stage window then we need to resize
|
||||
* the stage and update its viewport so we queue a relayout. Note: if the
|
||||
* fullscreen request is handled asynchronously we can't rely on this
|
||||
* queue_relayout to update the viewport, but for example the X backend
|
||||
* will recieve a ConfigureNotify after a successful resize which is how
|
||||
* we ensure the viewport is updated on X.
|
||||
*/
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_get_fullscreen:
|
||||
* @stage: a #ClutterStage
|
||||
*
|
||||
* Retrieves whether the stage is full screen or not
|
||||
*
|
||||
* Return value: %TRUE if the stage is full screen
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gboolean
|
||||
clutter_stage_get_fullscreen (ClutterStage *stage)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
||||
|
||||
return stage->priv->is_fullscreen;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_show_cursor:
|
||||
* @stage: a #ClutterStage
|
||||
@ -2990,13 +2815,9 @@ gboolean
|
||||
clutter_stage_event (ClutterStage *stage,
|
||||
ClutterEvent *event)
|
||||
{
|
||||
ClutterStagePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
|
||||
g_return_val_if_fail (event != NULL, FALSE);
|
||||
|
||||
priv = stage->priv;
|
||||
|
||||
if (event->type == CLUTTER_DELETE)
|
||||
{
|
||||
gboolean retval = FALSE;
|
||||
@ -3016,24 +2837,6 @@ clutter_stage_event (ClutterStage *stage,
|
||||
if (clutter_actor_event (CLUTTER_ACTOR (stage), event, FALSE))
|
||||
return TRUE;
|
||||
|
||||
if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_FULLSCREEN)
|
||||
{
|
||||
if (event->stage_state.new_state & CLUTTER_STAGE_STATE_FULLSCREEN)
|
||||
{
|
||||
priv->is_fullscreen = TRUE;
|
||||
g_signal_emit (stage, stage_signals[FULLSCREEN], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "fullscreen-set");
|
||||
}
|
||||
else
|
||||
{
|
||||
priv->is_fullscreen = FALSE;
|
||||
g_signal_emit (stage, stage_signals[UNFULLSCREEN], 0);
|
||||
|
||||
g_object_notify (G_OBJECT (stage), "fullscreen-set");
|
||||
}
|
||||
}
|
||||
|
||||
if (event->stage_state.changed_mask & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||
{
|
||||
if (event->stage_state.new_state & CLUTTER_STAGE_STATE_ACTIVATED)
|
||||
@ -3888,8 +3691,6 @@ clutter_stage_get_use_alpha (ClutterStage *stage)
|
||||
* If the current size of @stage is smaller than the minimum size, the
|
||||
* @stage will be resized to the new @width and @height
|
||||
*
|
||||
* This function has no effect if @stage is fullscreen
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
@ -4576,20 +4377,6 @@ _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
|
||||
|
@ -61,8 +61,6 @@ struct _ClutterStage
|
||||
};
|
||||
/**
|
||||
* ClutterStageClass:
|
||||
* @fullscreen: handler for the #ClutterStage::fullscreen signal
|
||||
* @unfullscreen: handler for the #ClutterStage::unfullscreen signal
|
||||
* @activate: handler for the #ClutterStage::activate signal
|
||||
* @deactivate: handler for the #ClutterStage::deactivate signal
|
||||
* @delete_event: handler for the #ClutterStage::delete-event signal
|
||||
@ -79,8 +77,6 @@ struct _ClutterStageClass
|
||||
|
||||
/*< public >*/
|
||||
/* signals */
|
||||
void (* fullscreen) (ClutterStage *stage);
|
||||
void (* unfullscreen) (ClutterStage *stage);
|
||||
void (* activate) (ClutterStage *stage);
|
||||
void (* deactivate) (ClutterStage *stage);
|
||||
|
||||
@ -168,11 +164,6 @@ CLUTTER_EXPORT
|
||||
void clutter_stage_get_perspective (ClutterStage *stage,
|
||||
ClutterPerspective *perspective);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_set_fullscreen (ClutterStage *stage,
|
||||
gboolean fullscreen);
|
||||
CLUTTER_EXPORT
|
||||
gboolean clutter_stage_get_fullscreen (ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_show_cursor (ClutterStage *stage);
|
||||
CLUTTER_EXPORT
|
||||
void clutter_stage_hide_cursor (ClutterStage *stage);
|
||||
|
@ -89,7 +89,6 @@ static const gchar *atom_names[] = {
|
||||
"_NET_WM_PID",
|
||||
"_NET_WM_PING",
|
||||
"_NET_WM_STATE",
|
||||
"_NET_WM_STATE_FULLSCREEN",
|
||||
"_NET_WM_USER_TIME",
|
||||
"WM_PROTOCOLS",
|
||||
"WM_DELETE_WINDOW",
|
||||
@ -441,14 +440,13 @@ clutter_backend_x11_post_parse (ClutterBackend *backend,
|
||||
backend_x11->atom_NET_WM_PID = atoms[0];
|
||||
backend_x11->atom_NET_WM_PING = atoms[1];
|
||||
backend_x11->atom_NET_WM_STATE = atoms[2];
|
||||
backend_x11->atom_NET_WM_STATE_FULLSCREEN = atoms[3];
|
||||
backend_x11->atom_NET_WM_USER_TIME = atoms[4];
|
||||
backend_x11->atom_WM_PROTOCOLS = atoms[5];
|
||||
backend_x11->atom_WM_DELETE_WINDOW = atoms[6];
|
||||
backend_x11->atom_XEMBED = atoms[7];
|
||||
backend_x11->atom_XEMBED_INFO = atoms[8];
|
||||
backend_x11->atom_NET_WM_NAME = atoms[9];
|
||||
backend_x11->atom_UTF8_STRING = atoms[10];
|
||||
backend_x11->atom_NET_WM_USER_TIME = atoms[3];
|
||||
backend_x11->atom_WM_PROTOCOLS = atoms[4];
|
||||
backend_x11->atom_WM_DELETE_WINDOW = atoms[5];
|
||||
backend_x11->atom_XEMBED = atoms[6];
|
||||
backend_x11->atom_XEMBED_INFO = atoms[7];
|
||||
backend_x11->atom_NET_WM_NAME = atoms[8];
|
||||
backend_x11->atom_UTF8_STRING = atoms[9];
|
||||
|
||||
g_free (clutter_display_name);
|
||||
|
||||
|
@ -89,7 +89,6 @@ struct _ClutterBackendX11
|
||||
Atom atom_NET_WM_PID;
|
||||
Atom atom_NET_WM_PING;
|
||||
Atom atom_NET_WM_STATE;
|
||||
Atom atom_NET_WM_STATE_FULLSCREEN;
|
||||
Atom atom_NET_WM_USER_TIME;
|
||||
Atom atom_WM_PROTOCOLS;
|
||||
Atom atom_WM_DELETE_WINDOW;
|
||||
|
@ -87,60 +87,6 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageX11,
|
||||
ButtonReleaseMask | \
|
||||
PointerMotionMask
|
||||
|
||||
static void
|
||||
send_wmspec_change_state (ClutterBackendX11 *backend_x11,
|
||||
Window window,
|
||||
Atom state,
|
||||
gboolean add)
|
||||
{
|
||||
XClientMessageEvent xclient;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "%s NET_WM state", add ? "adding" : "removing");
|
||||
|
||||
memset (&xclient, 0, sizeof (xclient));
|
||||
|
||||
xclient.type = ClientMessage;
|
||||
xclient.window = window;
|
||||
xclient.message_type = backend_x11->atom_NET_WM_STATE;
|
||||
xclient.format = 32;
|
||||
|
||||
xclient.data.l[0] = add ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE;
|
||||
xclient.data.l[1] = state;
|
||||
xclient.data.l[2] = 0;
|
||||
xclient.data.l[3] = 0;
|
||||
xclient.data.l[4] = 0;
|
||||
|
||||
XSendEvent (backend_x11->xdpy,
|
||||
DefaultRootWindow (backend_x11->xdpy),
|
||||
False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
(XEvent *)&xclient);
|
||||
}
|
||||
|
||||
static void
|
||||
update_state (ClutterStageX11 *stage_x11,
|
||||
ClutterBackendX11 *backend_x11,
|
||||
Atom *state,
|
||||
gboolean add)
|
||||
{
|
||||
if (add)
|
||||
{
|
||||
/* FIXME: This wont work if we support more states */
|
||||
XChangeProperty (backend_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_STATE, XA_ATOM, 32,
|
||||
PropModeReplace,
|
||||
(unsigned char *) state, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: This wont work if we support more states */
|
||||
XDeleteProperty (backend_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
|
||||
gint new_width,
|
||||
@ -166,18 +112,11 @@ clutter_stage_x11_fix_window_size (ClutterStageX11 *stage_x11,
|
||||
if (new_height <= 0)
|
||||
new_height = min_height;
|
||||
|
||||
size_hints->flags = 0;
|
||||
|
||||
/* If we are going fullscreen then we don't want any
|
||||
restrictions on the window size */
|
||||
if (!stage_x11->fullscreening)
|
||||
{
|
||||
size_hints->min_width = new_width;
|
||||
size_hints->min_height = new_height;
|
||||
size_hints->max_width = new_width;
|
||||
size_hints->max_height = new_height;
|
||||
size_hints->flags = PMinSize | PMaxSize;
|
||||
}
|
||||
size_hints->min_width = new_width;
|
||||
size_hints->min_height = new_height;
|
||||
size_hints->max_width = new_width;
|
||||
size_hints->max_height = new_height;
|
||||
size_hints->flags = PMinSize | PMaxSize;
|
||||
|
||||
XSetWMNormalHints (backend_x11->xdpy, stage_x11->xwin, size_hints);
|
||||
|
||||
@ -204,28 +143,8 @@ clutter_stage_x11_get_geometry (ClutterStageWindow *stage_window,
|
||||
cairo_rectangle_int_t *geometry)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
|
||||
|
||||
geometry->x = geometry->y = 0;
|
||||
|
||||
/* If we're fullscreen, return the size of the display.
|
||||
*
|
||||
* FIXME - this is utterly broken for anything that is not a single
|
||||
* head set up; the window manager will give us the right size in a
|
||||
* ConfigureNotify, but between the fullscreen signal emission on the
|
||||
* stage and the following frame, the size returned by the stage will
|
||||
* be wrong.
|
||||
*/
|
||||
if (_clutter_stage_is_fullscreen (stage_cogl->wrapper) &&
|
||||
stage_x11->fullscreening)
|
||||
{
|
||||
geometry->width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num);
|
||||
geometry->height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
geometry->width = stage_x11->xwin_width;
|
||||
geometry->height = stage_x11->xwin_height;
|
||||
}
|
||||
@ -251,10 +170,6 @@ clutter_stage_x11_resize (ClutterStageWindow *stage_window,
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we're going fullscreen, don't mess with the size */
|
||||
if (stage_x11->fullscreening)
|
||||
return;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
/* Should not happen, if this turns up we need to debug it and
|
||||
@ -448,117 +363,6 @@ _clutter_stage_x11_update_foreign_event_mask (CoglOnscreen *onscreen,
|
||||
&attrs);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_x11_set_fullscreen (ClutterStageWindow *stage_window,
|
||||
gboolean is_fullscreen)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
|
||||
ClutterStageCogl *stage_cogl = CLUTTER_STAGE_COGL (stage_x11);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (stage_cogl->backend);
|
||||
ClutterStage *stage = stage_cogl->wrapper;
|
||||
gboolean was_fullscreen;
|
||||
|
||||
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
|
||||
return;
|
||||
|
||||
was_fullscreen = _clutter_stage_is_fullscreen (stage);
|
||||
is_fullscreen = !!is_fullscreen;
|
||||
|
||||
if (was_fullscreen == is_fullscreen)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "%ssetting fullscreen", is_fullscreen ? "" : "un");
|
||||
|
||||
if (is_fullscreen)
|
||||
{
|
||||
#if 0
|
||||
int width, height;
|
||||
|
||||
/* FIXME: this will do the wrong thing for dual-headed
|
||||
displays. This will return the size of the combined display
|
||||
but Metacity (at least) will fullscreen to only one of the
|
||||
displays. This will cause the actor to report the wrong size
|
||||
until the ConfigureNotify for the correct size is received */
|
||||
width = DisplayWidth (backend_x11->xdpy, backend_x11->xscreen_num);
|
||||
height = DisplayHeight (backend_x11->xdpy, backend_x11->xscreen_num);
|
||||
#endif
|
||||
|
||||
/* Set the fullscreen hint so we can retain the old size of the window. */
|
||||
stage_x11->fullscreening = TRUE;
|
||||
|
||||
if (stage_x11->xwin != None)
|
||||
{
|
||||
/* if the actor is not mapped we resize the stage window to match
|
||||
* the size of the screen; this is useful for e.g. EGLX to avoid
|
||||
* a resize when calling clutter_stage_fullscreen() before showing
|
||||
* the stage
|
||||
*/
|
||||
if (!STAGE_X11_IS_MAPPED (stage_x11))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Fullscreening unmapped stage");
|
||||
|
||||
update_state (stage_x11, backend_x11,
|
||||
&backend_x11->atom_NET_WM_STATE_FULLSCREEN,
|
||||
TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Fullscreening mapped stage");
|
||||
|
||||
/* We need to fix the window size so that it will remove
|
||||
the maximum and minimum window hints. Otherwise
|
||||
metacity will honour the restrictions and not
|
||||
fullscreen correctly. */
|
||||
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
|
||||
|
||||
send_wmspec_change_state (backend_x11, stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_STATE_FULLSCREEN,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
stage_x11->fullscreen_on_realize = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
stage_x11->fullscreening = FALSE;
|
||||
|
||||
if (stage_x11->xwin != None)
|
||||
{
|
||||
if (!STAGE_X11_IS_MAPPED (stage_x11))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Un-fullscreening unmapped stage");
|
||||
|
||||
update_state (stage_x11, backend_x11,
|
||||
&backend_x11->atom_NET_WM_STATE_FULLSCREEN,
|
||||
FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Un-fullscreening mapped stage");
|
||||
|
||||
send_wmspec_change_state (backend_x11,
|
||||
stage_x11->xwin,
|
||||
backend_x11->atom_NET_WM_STATE_FULLSCREEN,
|
||||
FALSE);
|
||||
|
||||
/* Fix the window size to restore the minimum/maximum
|
||||
restriction */
|
||||
clutter_stage_x11_fix_window_size (stage_x11,
|
||||
stage_x11->xwin_width,
|
||||
stage_x11->xwin_height);
|
||||
}
|
||||
}
|
||||
else
|
||||
stage_x11->fullscreen_on_realize = FALSE;
|
||||
}
|
||||
|
||||
/* XXX: Note we rely on the ConfigureNotify mechanism as the common
|
||||
* mechanism to handle notifications of new X window sizes from the
|
||||
* X server so we don't actively change the stage viewport here or
|
||||
* queue a relayout etc. */
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_x11_events_device_changed (ClutterStageX11 *stage_x11,
|
||||
ClutterInputDevice *device,
|
||||
@ -710,13 +514,6 @@ clutter_stage_x11_realize (ClutterStageWindow *stage_window)
|
||||
stage_x11->xwin_height);
|
||||
clutter_stage_x11_set_wm_protocols (stage_x11);
|
||||
|
||||
if (stage_x11->fullscreen_on_realize)
|
||||
{
|
||||
stage_x11->fullscreen_on_realize = FALSE;
|
||||
|
||||
clutter_stage_x11_set_fullscreen (stage_window, TRUE);
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Successfully realized stage");
|
||||
|
||||
return TRUE;
|
||||
@ -817,11 +614,6 @@ clutter_stage_x11_show (ClutterStageWindow *stage_window,
|
||||
set_stage_x11_state (stage_x11, STAGE_X11_WITHDRAWN, 0);
|
||||
|
||||
update_wm_hints (stage_x11);
|
||||
|
||||
if (stage_x11->fullscreening)
|
||||
clutter_stage_x11_set_fullscreen (stage_window, TRUE);
|
||||
else
|
||||
clutter_stage_x11_set_fullscreen (stage_window, FALSE);
|
||||
}
|
||||
|
||||
g_assert (STAGE_X11_IS_MAPPED (stage_x11));
|
||||
@ -943,7 +735,6 @@ clutter_stage_x11_init (ClutterStageX11 *stage)
|
||||
stage->wm_state = STAGE_X11_WITHDRAWN;
|
||||
|
||||
stage->is_foreign_xwin = FALSE;
|
||||
stage->fullscreening = FALSE;
|
||||
stage->is_cursor_visible = TRUE;
|
||||
stage->accept_focus = TRUE;
|
||||
|
||||
@ -956,7 +747,6 @@ clutter_stage_window_iface_init (ClutterStageWindowInterface *iface)
|
||||
clutter_stage_window_parent_iface = g_type_interface_peek_parent (iface);
|
||||
|
||||
iface->set_title = clutter_stage_x11_set_title;
|
||||
iface->set_fullscreen = clutter_stage_x11_set_fullscreen;
|
||||
iface->set_cursor_visible = clutter_stage_x11_set_cursor_visible;
|
||||
iface->set_accept_focus = clutter_stage_x11_set_accept_focus;
|
||||
iface->show = clutter_stage_x11_show;
|
||||
@ -1077,13 +867,8 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
|
||||
xevent->xconfigure.width,
|
||||
xevent->xconfigure.height);
|
||||
|
||||
/* When fullscreen, we'll keep the xwin_width/height
|
||||
variables to track the old size of the window and we'll
|
||||
assume all ConfigureNotifies constitute a size change */
|
||||
if (_clutter_stage_is_fullscreen (stage))
|
||||
size_changed = TRUE;
|
||||
else if ((stage_x11->xwin_width != xevent->xconfigure.width) ||
|
||||
(stage_x11->xwin_height != xevent->xconfigure.height))
|
||||
if ((stage_x11->xwin_width != xevent->xconfigure.width) ||
|
||||
(stage_x11->xwin_height != xevent->xconfigure.height))
|
||||
{
|
||||
size_changed = TRUE;
|
||||
stage_x11->xwin_width = xevent->xconfigure.width;
|
||||
@ -1173,57 +958,6 @@ clutter_stage_x11_translate_event (ClutterEventTranslator *translator,
|
||||
}
|
||||
break;
|
||||
|
||||
case PropertyNotify:
|
||||
if (xevent->xproperty.atom == backend_x11->atom_NET_WM_STATE &&
|
||||
xevent->xproperty.window == stage_xwindow &&
|
||||
!stage_x11->is_foreign_xwin)
|
||||
{
|
||||
Atom type;
|
||||
gint format;
|
||||
gulong n_items, bytes_after;
|
||||
guchar *data = NULL;
|
||||
gboolean fullscreen_set = FALSE;
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
XGetWindowProperty (backend_x11->xdpy, stage_xwindow,
|
||||
backend_x11->atom_NET_WM_STATE,
|
||||
0, G_MAXLONG,
|
||||
False, XA_ATOM,
|
||||
&type, &format, &n_items,
|
||||
&bytes_after, &data);
|
||||
clutter_x11_untrap_x_errors ();
|
||||
|
||||
if (type != None && data != NULL)
|
||||
{
|
||||
gboolean is_fullscreen = FALSE;
|
||||
Atom *atoms = (Atom *) data;
|
||||
gulong i;
|
||||
|
||||
for (i = 0; i < n_items; i++)
|
||||
{
|
||||
if (atoms[i] == backend_x11->atom_NET_WM_STATE_FULLSCREEN)
|
||||
fullscreen_set = TRUE;
|
||||
}
|
||||
|
||||
is_fullscreen = _clutter_stage_is_fullscreen (stage_cogl->wrapper);
|
||||
|
||||
if (fullscreen_set != is_fullscreen)
|
||||
{
|
||||
if (fullscreen_set)
|
||||
_clutter_stage_update_state (stage_cogl->wrapper,
|
||||
0,
|
||||
CLUTTER_STAGE_STATE_FULLSCREEN);
|
||||
else
|
||||
_clutter_stage_update_state (stage_cogl->wrapper,
|
||||
CLUTTER_STAGE_STATE_FULLSCREEN,
|
||||
0);
|
||||
}
|
||||
|
||||
XFree (data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
if (!_clutter_stage_is_activated (stage_cogl->wrapper))
|
||||
{
|
||||
|
@ -70,11 +70,9 @@ struct _ClutterStageX11
|
||||
ClutterStageX11State wm_state;
|
||||
|
||||
guint is_foreign_xwin : 1;
|
||||
guint fullscreening : 1;
|
||||
guint is_cursor_visible : 1;
|
||||
guint viewport_initialized : 1;
|
||||
guint accept_focus : 1;
|
||||
guint fullscreen_on_realize : 1;
|
||||
};
|
||||
|
||||
struct _ClutterStageX11Class
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <clutter/clutter.h>
|
||||
#include <string.h>
|
||||
|
||||
gboolean IsFullScreen = FALSE, IsMotion = TRUE;
|
||||
gboolean IsMotion = TRUE;
|
||||
|
||||
int
|
||||
test_events_main (int argc, char *argv[]);
|
||||
@ -114,28 +114,6 @@ stage_state_cb (ClutterStage *stage,
|
||||
printf("[stage signal] %s\n", detail);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
blue_button_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = clutter_actor_get_stage (actor);
|
||||
|
||||
if (IsFullScreen)
|
||||
IsFullScreen = FALSE;
|
||||
else
|
||||
IsFullScreen = TRUE;
|
||||
|
||||
clutter_stage_set_fullscreen (CLUTTER_STAGE (stage), IsFullScreen);
|
||||
|
||||
g_print ("*** Fullscreen %s ***\n",
|
||||
IsFullScreen ? "enabled" : "disabled");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
red_button_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
@ -429,10 +407,6 @@ test_events_main (int argc, char *argv[])
|
||||
clutter_actor_set_name (stage, "Stage");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "event", G_CALLBACK (input_cb), (char *) "stage");
|
||||
g_signal_connect (stage, "fullscreen",
|
||||
G_CALLBACK (stage_state_cb), (char *) "fullscreen");
|
||||
g_signal_connect (stage, "unfullscreen",
|
||||
G_CALLBACK (stage_state_cb), (char *) "unfullscreen");
|
||||
g_signal_connect (stage, "activate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "activate");
|
||||
g_signal_connect (stage, "deactivate",
|
||||
@ -468,19 +442,6 @@ test_events_main (int argc, char *argv[])
|
||||
focus_box);
|
||||
g_signal_connect (actor, "captured-event", G_CALLBACK (capture_cb), NULL);
|
||||
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Blue);
|
||||
clutter_actor_set_name (actor, "Blue Box");
|
||||
clutter_actor_set_size (actor, 100, 100);
|
||||
clutter_actor_set_position (actor, 400, 100);
|
||||
clutter_actor_set_reactive (actor, TRUE);
|
||||
clutter_container_add (CLUTTER_CONTAINER(stage), actor, NULL);
|
||||
g_signal_connect (actor, "event", G_CALLBACK (input_cb), (char *) "blue box");
|
||||
g_signal_connect (actor, "key-focus-in", G_CALLBACK (key_focus_in_cb),
|
||||
focus_box);
|
||||
/* Fullscreen */
|
||||
g_signal_connect (actor, "button-press-event",
|
||||
G_CALLBACK (blue_button_cb), NULL);
|
||||
|
||||
/* non reactive */
|
||||
actor = clutter_rectangle_new_with_color (CLUTTER_COLOR_Black);
|
||||
clutter_actor_set_name (actor, "Black Box");
|
||||
|
@ -218,10 +218,6 @@ test_grab_main (int argc, char *argv[])
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect (stage, "event",
|
||||
G_CALLBACK (debug_event_cb), (char *) "stage");
|
||||
g_signal_connect (stage, "fullscreen",
|
||||
G_CALLBACK (stage_state_cb), (char *) "fullscreen");
|
||||
g_signal_connect (stage, "unfullscreen",
|
||||
G_CALLBACK (stage_state_cb), (char *) "unfullscreen");
|
||||
g_signal_connect (stage, "activate",
|
||||
G_CALLBACK (stage_state_cb), (char *) "activate");
|
||||
g_signal_connect (stage, "deactivate",
|
||||
|
@ -8,13 +8,6 @@ test_stage_sizing_main (int argc, char *argv[]);
|
||||
const char *
|
||||
test_stage_sizing_describe (void);
|
||||
|
||||
static gboolean
|
||||
fullscreen_clicked_cb (ClutterStage *stage)
|
||||
{
|
||||
clutter_stage_set_fullscreen (stage, !clutter_stage_get_fullscreen (stage));
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
shrink_clicked_cb (ClutterActor *stage)
|
||||
{
|
||||
@ -33,22 +26,6 @@ expand_clicked_cb (ClutterActor *stage)
|
||||
return CLUTTER_EVENT_STOP;
|
||||
}
|
||||
|
||||
static void
|
||||
on_fullscreen (ClutterStage *stage)
|
||||
{
|
||||
float width, height;
|
||||
gboolean is_fullscreen;
|
||||
|
||||
is_fullscreen = clutter_stage_get_fullscreen (stage);
|
||||
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height);
|
||||
|
||||
g_print ("Stage size [%s]: %d x %d\n",
|
||||
is_fullscreen ? "fullscreen" : "not fullscreen",
|
||||
(int) width,
|
||||
(int) height);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_stage_sizing_main (int argc, char *argv[])
|
||||
{
|
||||
@ -61,27 +38,12 @@ test_stage_sizing_main (int argc, char *argv[])
|
||||
stage = clutter_stage_new ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Stage Sizing");
|
||||
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
||||
g_signal_connect_after (stage, "notify::fullscreen-set", G_CALLBACK (on_fullscreen), NULL);
|
||||
|
||||
box = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (box, clutter_box_layout_new ());
|
||||
clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
|
||||
clutter_actor_add_child (stage, box);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (rect,
|
||||
clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER));
|
||||
clutter_actor_set_background_color (rect, CLUTTER_COLOR_LightScarletRed);
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
g_signal_connect_swapped (rect, "button-press-event",
|
||||
G_CALLBACK (fullscreen_clicked_cb),
|
||||
stage);
|
||||
label = clutter_text_new_with_text ("Sans 16", "Toggle fullscreen");
|
||||
clutter_actor_set_margin (label, &margin);
|
||||
clutter_actor_add_child (rect, label);
|
||||
clutter_actor_add_child (box, rect);
|
||||
|
||||
rect = clutter_actor_new ();
|
||||
clutter_actor_set_layout_manager (rect,
|
||||
clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
|
Loading…
Reference in New Issue
Block a user