mirror of
https://github.com/edu4rdshl/gnome-shell.git
synced 2026-07-17 23:24:51 +00:00
shell/monitor-group: Avoid doing extra work
A lot of our calculations only change based on (unlikely) external events, simply cache those parts and only update when the underlying properties actually change. Notable is base_direction, which was previously being calculated repeatedly per workspace per monitor on every interpolate — now it's simply a private int. This seriously cuts down the number of calls, vs just maths, we need to do at each step including eliminating a repeated `g_object_get` in favour of a gboolean flag.
This commit is contained in:
parent
fbce396f4a
commit
8271fda6e3
1 changed files with 142 additions and 76 deletions
|
|
@ -31,10 +31,18 @@
|
||||||
typedef struct _ShellMonitorGroupPrivate ShellMonitorGroupPrivate;
|
typedef struct _ShellMonitorGroupPrivate ShellMonitorGroupPrivate;
|
||||||
struct _ShellMonitorGroupPrivate
|
struct _ShellMonitorGroupPrivate
|
||||||
{
|
{
|
||||||
|
ShellGlobal *global;
|
||||||
|
MetaWorkspaceManager *workspace_manager;
|
||||||
|
StThemeContext *theme_context;
|
||||||
|
|
||||||
ClutterActor *container;
|
ClutterActor *container;
|
||||||
GPtrArray *workspace_groups;
|
GPtrArray *workspace_groups;
|
||||||
|
|
||||||
int index, width, height;
|
int index, width, height;
|
||||||
|
float base_distance;
|
||||||
|
|
||||||
|
gboolean is_vertical;
|
||||||
|
gboolean is_rtl;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
@ -60,6 +68,16 @@ shell_monitor_group_dispose (GObject *object)
|
||||||
ShellMonitorGroupPrivate *priv =
|
ShellMonitorGroupPrivate *priv =
|
||||||
shell_monitor_group_get_instance_private (SHELL_MONITOR_GROUP (object));
|
shell_monitor_group_get_instance_private (SHELL_MONITOR_GROUP (object));
|
||||||
|
|
||||||
|
g_clear_weak_pointer (&priv->global);
|
||||||
|
|
||||||
|
if (priv->workspace_manager)
|
||||||
|
g_signal_handlers_disconnect_by_data (priv->workspace_manager, object);
|
||||||
|
g_clear_weak_pointer (&priv->workspace_manager);
|
||||||
|
|
||||||
|
if (priv->theme_context)
|
||||||
|
g_signal_handlers_disconnect_by_data (priv->theme_context, object);
|
||||||
|
g_clear_weak_pointer (&priv->theme_context);
|
||||||
|
|
||||||
g_clear_weak_pointer (&priv->container);
|
g_clear_weak_pointer (&priv->container);
|
||||||
g_clear_pointer (&priv->workspace_groups, g_ptr_array_unref);
|
g_clear_pointer (&priv->workspace_groups, g_ptr_array_unref);
|
||||||
|
|
||||||
|
|
@ -82,11 +100,9 @@ shell_monitor_group_set_property (GObject *object,
|
||||||
break;
|
break;
|
||||||
case PROP_MONITOR_WIDTH:
|
case PROP_MONITOR_WIDTH:
|
||||||
priv->width = g_value_get_int (value);
|
priv->width = g_value_get_int (value);
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (object), g_value_get_int (value), priv->height);
|
|
||||||
break;
|
break;
|
||||||
case PROP_MONITOR_HEIGHT:
|
case PROP_MONITOR_HEIGHT:
|
||||||
priv->height = g_value_get_int (value);
|
priv->height = g_value_get_int (value);
|
||||||
clutter_actor_set_size (CLUTTER_ACTOR (object), priv->width, g_value_get_int (value));
|
|
||||||
break;
|
break;
|
||||||
case PROP_PROGRESS:
|
case PROP_PROGRESS:
|
||||||
shell_monitor_group_set_progress (SHELL_MONITOR_GROUP (object),
|
shell_monitor_group_set_progress (SHELL_MONITOR_GROUP (object),
|
||||||
|
|
@ -131,6 +147,35 @@ shell_monitor_group_get_property (GObject *object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_base_distance (ShellMonitorGroup *self)
|
||||||
|
{
|
||||||
|
ShellMonitorGroupPrivate *priv =
|
||||||
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
int spacing =
|
||||||
|
WORKSPACE_SPACING * st_theme_context_get_scale_factor (priv->theme_context);
|
||||||
|
|
||||||
|
if (priv->is_vertical)
|
||||||
|
priv->base_distance = priv->height + spacing;
|
||||||
|
else
|
||||||
|
priv->base_distance = priv->width + spacing;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_BASE_DISTANCE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
shell_monitor_group_constructed (GObject *object)
|
||||||
|
{
|
||||||
|
ShellMonitorGroup *self = SHELL_MONITOR_GROUP (object);
|
||||||
|
ShellMonitorGroupPrivate *priv =
|
||||||
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (shell_monitor_group_parent_class)->constructed (object);
|
||||||
|
|
||||||
|
clutter_actor_set_size (CLUTTER_ACTOR (object), priv->width, priv->height);
|
||||||
|
update_base_distance (self);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_monitor_group_class_init (ShellMonitorGroupClass *klass)
|
shell_monitor_group_class_init (ShellMonitorGroupClass *klass)
|
||||||
{
|
{
|
||||||
|
|
@ -139,6 +184,7 @@ shell_monitor_group_class_init (ShellMonitorGroupClass *klass)
|
||||||
object_class->dispose = shell_monitor_group_dispose;
|
object_class->dispose = shell_monitor_group_dispose;
|
||||||
object_class->set_property = shell_monitor_group_set_property;
|
object_class->set_property = shell_monitor_group_set_property;
|
||||||
object_class->get_property = shell_monitor_group_get_property;
|
object_class->get_property = shell_monitor_group_get_property;
|
||||||
|
object_class->constructed = shell_monitor_group_constructed;
|
||||||
|
|
||||||
obj_props[PROP_INDEX] =
|
obj_props[PROP_INDEX] =
|
||||||
g_param_spec_int ("index", NULL, NULL,
|
g_param_spec_int ("index", NULL, NULL,
|
||||||
|
|
@ -164,71 +210,122 @@ shell_monitor_group_class_init (ShellMonitorGroupClass *klass)
|
||||||
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
g_object_class_install_properties (object_class, PROP_LAST, obj_props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
layout_rows_changed (ShellMonitorGroup *self)
|
||||||
|
{
|
||||||
|
ShellMonitorGroupPrivate *priv =
|
||||||
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
int rows;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3351
|
||||||
|
* priv->is_vertical =
|
||||||
|
* meta_workspace_manager_get_layout_rows (priv->workspace_manager) == -1;
|
||||||
|
*/
|
||||||
|
g_object_get (priv->workspace_manager, "layout-rows", &rows, NULL);
|
||||||
|
|
||||||
|
priv->is_vertical = rows == -1;
|
||||||
|
update_base_distance (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
scale_factor_changed (ShellMonitorGroup *self)
|
||||||
|
{
|
||||||
|
update_base_distance (self);
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
text_direction_changed (ShellMonitorGroup *self)
|
||||||
|
{
|
||||||
|
ShellMonitorGroupPrivate *priv =
|
||||||
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
|
priv->is_rtl =
|
||||||
|
clutter_actor_get_text_direction (CLUTTER_ACTOR (self)) == CLUTTER_TEXT_DIRECTION_RTL;
|
||||||
|
|
||||||
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
shell_monitor_group_init (ShellMonitorGroup *self)
|
shell_monitor_group_init (ShellMonitorGroup *self)
|
||||||
{
|
{
|
||||||
ShellMonitorGroupPrivate *priv =
|
ShellMonitorGroupPrivate *priv =
|
||||||
shell_monitor_group_get_instance_private (self);
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
ShellGlobal *global = shell_global_get ();
|
||||||
|
MetaWorkspaceManager *workspace_manager =
|
||||||
|
shell_global_get_workspace_manager (global);
|
||||||
|
StThemeContext *theme_context =
|
||||||
|
st_theme_context_get_for_stage (shell_global_get_stage (global));
|
||||||
ClutterActor *container = clutter_actor_new ();
|
ClutterActor *container = clutter_actor_new ();
|
||||||
|
|
||||||
|
g_set_weak_pointer (&priv->global, global);
|
||||||
|
g_set_weak_pointer (&priv->workspace_manager, workspace_manager);
|
||||||
|
g_set_weak_pointer (&priv->theme_context, theme_context);
|
||||||
|
|
||||||
g_set_weak_pointer (&priv->container, container);
|
g_set_weak_pointer (&priv->container, container);
|
||||||
clutter_actor_add_child (CLUTTER_ACTOR (self), container);
|
clutter_actor_add_child (CLUTTER_ACTOR (self), container);
|
||||||
|
|
||||||
priv->workspace_groups = g_ptr_array_new_with_free_func (g_object_unref);
|
priv->workspace_groups = g_ptr_array_new_with_free_func (g_object_unref);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (self));
|
||||||
|
g_signal_connect_swapped (priv->workspace_manager,
|
||||||
|
"notify::layout-rows", G_CALLBACK (layout_rows_changed),
|
||||||
|
self);
|
||||||
|
layout_rows_changed (self);
|
||||||
|
|
||||||
|
g_signal_connect_swapped (priv->theme_context,
|
||||||
|
"notify::scale-factor", G_CALLBACK (scale_factor_changed),
|
||||||
|
self);
|
||||||
|
scale_factor_changed (self);
|
||||||
|
|
||||||
|
g_signal_connect_swapped (self,
|
||||||
|
"notify::text-direction", G_CALLBACK (text_direction_changed),
|
||||||
|
self);
|
||||||
|
text_direction_changed (self);
|
||||||
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
shell_monitor_group_get_base_distance (ShellMonitorGroup *self)
|
shell_monitor_group_get_base_distance (ShellMonitorGroup *self)
|
||||||
{
|
{
|
||||||
ShellMonitorGroupPrivate *priv;
|
ShellMonitorGroupPrivate *priv;
|
||||||
ShellGlobal *global = shell_global_get ();
|
|
||||||
StThemeContext *context;
|
|
||||||
int scale, spacing, rows;
|
|
||||||
|
|
||||||
g_return_val_if_fail (SHELL_IS_MONITOR_GROUP (self), 0.0);
|
g_return_val_if_fail (SHELL_IS_MONITOR_GROUP (self), 0.0);
|
||||||
|
|
||||||
priv = shell_monitor_group_get_instance_private (self);
|
priv = shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
context = st_theme_context_get_for_stage (shell_global_get_stage (global));
|
|
||||||
scale = st_theme_context_get_scale_factor (context);
|
|
||||||
/* TODO: Add mutter API? */
|
|
||||||
g_object_get (shell_global_get_workspace_manager (global),
|
|
||||||
"layout-rows", &rows,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
spacing = WORKSPACE_SPACING * scale;
|
|
||||||
|
|
||||||
if (rows == -1)
|
|
||||||
return priv->height + spacing;
|
|
||||||
|
|
||||||
return priv->width + spacing;
|
return priv->base_distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float
|
||||||
|
get_progress_from_actor (ShellMonitorGroup *self,
|
||||||
|
ClutterActor *actor)
|
||||||
|
{
|
||||||
|
ShellMonitorGroupPrivate *priv =
|
||||||
|
shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
|
if (priv->is_vertical)
|
||||||
|
return clutter_actor_get_y (actor) / priv->base_distance;
|
||||||
|
else if (priv->is_rtl)
|
||||||
|
return -clutter_actor_get_x (actor) / priv->base_distance;
|
||||||
|
else
|
||||||
|
return clutter_actor_get_x (actor) / priv->base_distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
float
|
float
|
||||||
shell_monitor_group_get_progress (ShellMonitorGroup *self)
|
shell_monitor_group_get_progress (ShellMonitorGroup *self)
|
||||||
{
|
{
|
||||||
ShellMonitorGroupPrivate *priv;
|
ShellMonitorGroupPrivate *priv;
|
||||||
ShellGlobal *global = shell_global_get ();
|
|
||||||
int rows;
|
|
||||||
float base_distance;
|
|
||||||
|
|
||||||
g_return_val_if_fail (SHELL_IS_MONITOR_GROUP (self), 0.0);
|
g_return_val_if_fail (SHELL_IS_MONITOR_GROUP (self), 0.0);
|
||||||
|
|
||||||
priv = shell_monitor_group_get_instance_private (self);
|
priv = shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
/* TODO: Add mutter API? */
|
return -get_progress_from_actor (self, priv->container);
|
||||||
g_object_get (shell_global_get_workspace_manager (global),
|
|
||||||
"layout-rows", &rows,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
base_distance = shell_monitor_group_get_base_distance (self);
|
|
||||||
|
|
||||||
if (rows == -1)
|
|
||||||
return -clutter_actor_get_y (priv->container) / base_distance;
|
|
||||||
else if (clutter_actor_get_text_direction (CLUTTER_ACTOR (self)) == CLUTTER_TEXT_DIRECTION_RTL)
|
|
||||||
return clutter_actor_get_x (priv->container) / base_distance;
|
|
||||||
else
|
|
||||||
return -clutter_actor_get_x (priv->container) / base_distance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -236,54 +333,21 @@ shell_monitor_group_set_progress (ShellMonitorGroup *self,
|
||||||
float progress)
|
float progress)
|
||||||
{
|
{
|
||||||
ShellMonitorGroupPrivate *priv;
|
ShellMonitorGroupPrivate *priv;
|
||||||
ShellGlobal *global = shell_global_get ();
|
|
||||||
int rows;
|
|
||||||
float base_distance;
|
|
||||||
|
|
||||||
g_return_if_fail (SHELL_IS_MONITOR_GROUP (self));
|
g_return_if_fail (SHELL_IS_MONITOR_GROUP (self));
|
||||||
|
|
||||||
priv = shell_monitor_group_get_instance_private (self);
|
priv = shell_monitor_group_get_instance_private (self);
|
||||||
|
|
||||||
/* TODO: Add mutter API? */
|
if (priv->is_vertical)
|
||||||
g_object_get (shell_global_get_workspace_manager (global),
|
clutter_actor_set_y (priv->container, -roundf (progress * priv->base_distance));
|
||||||
"layout-rows", &rows,
|
else if (priv->is_rtl)
|
||||||
NULL);
|
clutter_actor_set_x (priv->container, roundf (progress * priv->base_distance));
|
||||||
|
|
||||||
base_distance = shell_monitor_group_get_base_distance (self);
|
|
||||||
|
|
||||||
if (rows == -1)
|
|
||||||
clutter_actor_set_y (priv->container, -roundf (progress * base_distance));
|
|
||||||
else if (clutter_actor_get_text_direction (CLUTTER_ACTOR (self)) == CLUTTER_TEXT_DIRECTION_RTL)
|
|
||||||
clutter_actor_set_x (priv->container, roundf (progress * base_distance));
|
|
||||||
else
|
else
|
||||||
clutter_actor_set_x (priv->container, -roundf (progress * base_distance));
|
clutter_actor_set_x (priv->container, -roundf (progress * priv->base_distance));
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PROGRESS]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float
|
|
||||||
get_workspace_group_progress (ShellMonitorGroup *self,
|
|
||||||
ShellWorkspaceGroup *group)
|
|
||||||
{
|
|
||||||
ShellGlobal *global = shell_global_get ();
|
|
||||||
int rows;
|
|
||||||
float base_distance;
|
|
||||||
|
|
||||||
/* TODO: Add mutter API? */
|
|
||||||
g_object_get (shell_global_get_workspace_manager (global),
|
|
||||||
"layout-rows", &rows,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
base_distance = shell_monitor_group_get_base_distance (self);
|
|
||||||
|
|
||||||
if (rows == -1)
|
|
||||||
return clutter_actor_get_y (CLUTTER_ACTOR (group)) / base_distance;
|
|
||||||
else if (clutter_actor_get_text_direction (CLUTTER_ACTOR (self)) == CLUTTER_TEXT_DIRECTION_RTL)
|
|
||||||
return -clutter_actor_get_x (CLUTTER_ACTOR (group)) / base_distance;
|
|
||||||
else
|
|
||||||
return clutter_actor_get_x (CLUTTER_ACTOR (group)) / base_distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
float
|
float
|
||||||
shell_monitor_group_get_workspace_progress (ShellMonitorGroup *self,
|
shell_monitor_group_get_workspace_progress (ShellMonitorGroup *self,
|
||||||
MetaWorkspace *workspace)
|
MetaWorkspace *workspace)
|
||||||
|
|
@ -304,7 +368,8 @@ shell_monitor_group_get_workspace_progress (ShellMonitorGroup *self,
|
||||||
workspace_group = g_ptr_array_index (priv->workspace_groups, i);
|
workspace_group = g_ptr_array_index (priv->workspace_groups, i);
|
||||||
|
|
||||||
if (meta_workspace_index (shell_workspace_group_get_workspace (workspace_group)) == target_index)
|
if (meta_workspace_index (shell_workspace_group_get_workspace (workspace_group)) == target_index)
|
||||||
return get_workspace_group_progress (self, workspace_group);
|
return get_progress_from_actor (self,
|
||||||
|
CLUTTER_ACTOR (workspace_group));
|
||||||
}
|
}
|
||||||
|
|
||||||
g_return_val_if_reached (0.0);
|
g_return_val_if_reached (0.0);
|
||||||
|
|
@ -334,7 +399,8 @@ shell_monitor_group_get_snap_points (ShellMonitorGroup *self,
|
||||||
data = g_new0 (float, priv->workspace_groups->len + 1);
|
data = g_new0 (float, priv->workspace_groups->len + 1);
|
||||||
|
|
||||||
for (size_t i = 0; i < priv->workspace_groups->len; i++)
|
for (size_t i = 0; i < priv->workspace_groups->len; i++)
|
||||||
data[i] = get_workspace_group_progress (self, g_ptr_array_index (priv->workspace_groups, i));
|
data[i] = get_progress_from_actor (self,
|
||||||
|
g_ptr_array_index (priv->workspace_groups, i));
|
||||||
|
|
||||||
*points = data;
|
*points = data;
|
||||||
}
|
}
|
||||||
|
|
@ -433,7 +499,7 @@ shell_monitor_group_find_closest_workspace (ShellMonitorGroup *self,
|
||||||
for (size_t i = 0; i < priv->workspace_groups->len; i++)
|
for (size_t i = 0; i < priv->workspace_groups->len; i++)
|
||||||
{
|
{
|
||||||
group = g_ptr_array_index (priv->workspace_groups, i);
|
group = g_ptr_array_index (priv->workspace_groups, i);
|
||||||
distance = get_workspace_group_progress (self, group);
|
distance = get_progress_from_actor (self, CLUTTER_ACTOR (group));
|
||||||
value = fabsf (distance - progress);
|
value = fabsf (distance - progress);
|
||||||
|
|
||||||
if (G_UNLIKELY (min_distance < 0))
|
if (G_UNLIKELY (min_distance < 0))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue