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;
|
||||
struct _ShellMonitorGroupPrivate
|
||||
{
|
||||
ShellGlobal *global;
|
||||
MetaWorkspaceManager *workspace_manager;
|
||||
StThemeContext *theme_context;
|
||||
|
||||
ClutterActor *container;
|
||||
GPtrArray *workspace_groups;
|
||||
|
||||
int index, width, height;
|
||||
float base_distance;
|
||||
|
||||
gboolean is_vertical;
|
||||
gboolean is_rtl;
|
||||
};
|
||||
|
||||
enum
|
||||
|
|
@ -60,6 +68,16 @@ shell_monitor_group_dispose (GObject *object)
|
|||
ShellMonitorGroupPrivate *priv =
|
||||
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_pointer (&priv->workspace_groups, g_ptr_array_unref);
|
||||
|
||||
|
|
@ -82,11 +100,9 @@ shell_monitor_group_set_property (GObject *object,
|
|||
break;
|
||||
case PROP_MONITOR_WIDTH:
|
||||
priv->width = g_value_get_int (value);
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (object), g_value_get_int (value), priv->height);
|
||||
break;
|
||||
case PROP_MONITOR_HEIGHT:
|
||||
priv->height = g_value_get_int (value);
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (object), priv->width, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_PROGRESS:
|
||||
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
|
||||
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->set_property = shell_monitor_group_set_property;
|
||||
object_class->get_property = shell_monitor_group_get_property;
|
||||
object_class->constructed = shell_monitor_group_constructed;
|
||||
|
||||
obj_props[PROP_INDEX] =
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
shell_monitor_group_init (ShellMonitorGroup *self)
|
||||
{
|
||||
ShellMonitorGroupPrivate *priv =
|
||||
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 ();
|
||||
|
||||
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);
|
||||
clutter_actor_add_child (CLUTTER_ACTOR (self), container);
|
||||
|
||||
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
|
||||
shell_monitor_group_get_base_distance (ShellMonitorGroup *self)
|
||||
{
|
||||
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);
|
||||
|
||||
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);
|
||||
return priv->base_distance;
|
||||
}
|
||||
|
||||
spacing = WORKSPACE_SPACING * scale;
|
||||
static float
|
||||
get_progress_from_actor (ShellMonitorGroup *self,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ShellMonitorGroupPrivate *priv =
|
||||
shell_monitor_group_get_instance_private (self);
|
||||
|
||||
if (rows == -1)
|
||||
return priv->height + spacing;
|
||||
|
||||
return priv->width + spacing;
|
||||
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
|
||||
shell_monitor_group_get_progress (ShellMonitorGroup *self)
|
||||
{
|
||||
ShellMonitorGroupPrivate *priv;
|
||||
ShellGlobal *global = shell_global_get ();
|
||||
int rows;
|
||||
float base_distance;
|
||||
|
||||
g_return_val_if_fail (SHELL_IS_MONITOR_GROUP (self), 0.0);
|
||||
|
||||
priv = shell_monitor_group_get_instance_private (self);
|
||||
|
||||
/* 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 (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;
|
||||
return -get_progress_from_actor (self, priv->container);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -236,54 +333,21 @@ shell_monitor_group_set_progress (ShellMonitorGroup *self,
|
|||
float progress)
|
||||
{
|
||||
ShellMonitorGroupPrivate *priv;
|
||||
ShellGlobal *global = shell_global_get ();
|
||||
int rows;
|
||||
float base_distance;
|
||||
|
||||
g_return_if_fail (SHELL_IS_MONITOR_GROUP (self));
|
||||
|
||||
priv = shell_monitor_group_get_instance_private (self);
|
||||
|
||||
/* 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)
|
||||
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));
|
||||
if (priv->is_vertical)
|
||||
clutter_actor_set_y (priv->container, -roundf (progress * priv->base_distance));
|
||||
else if (priv->is_rtl)
|
||||
clutter_actor_set_x (priv->container, roundf (progress * priv->base_distance));
|
||||
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]);
|
||||
}
|
||||
|
||||
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
|
||||
shell_monitor_group_get_workspace_progress (ShellMonitorGroup *self,
|
||||
MetaWorkspace *workspace)
|
||||
|
|
@ -304,7 +368,8 @@ shell_monitor_group_get_workspace_progress (ShellMonitorGroup *self,
|
|||
workspace_group = g_ptr_array_index (priv->workspace_groups, i);
|
||||
|
||||
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);
|
||||
|
|
@ -334,7 +399,8 @@ shell_monitor_group_get_snap_points (ShellMonitorGroup *self,
|
|||
data = g_new0 (float, priv->workspace_groups->len + 1);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -433,7 +499,7 @@ shell_monitor_group_find_closest_workspace (ShellMonitorGroup *self,
|
|||
for (size_t i = 0; i < priv->workspace_groups->len; 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);
|
||||
|
||||
if (G_UNLIKELY (min_distance < 0))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue