diff --git a/js/ui/workspace.js b/js/ui/workspace.js
index 0e22af59b..0069cdd00 100644
--- a/js/ui/workspace.js
+++ b/js/ui/workspace.js
@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Workspace */
-const { Clutter, GLib, GObject, Graphene, Meta, St } = imports.gi;
+const {Clutter, GLib, GObject, Graphene, Meta, Shell, St} = imports.gi;
const Background = imports.ui.background;
const DND = imports.ui.dnd;
@@ -24,7 +24,6 @@ var LAYOUT_SCALE_WEIGHT = 1;
var LAYOUT_SPACE_WEIGHT = 0.1;
const BACKGROUND_CORNER_RADIUS_PIXELS = 30;
-const BACKGROUND_MARGIN = 12;
// Window Thumbnail Layout Algorithm
// =================================
@@ -940,13 +939,13 @@ var WorkspaceLayout = GObject.registerClass({
});
var WorkspaceBackground = GObject.registerClass(
-class WorkspaceBackground extends St.Widget {
+class WorkspaceBackground extends Shell.WorkspaceBackground {
_init(monitorIndex, stateAdjustment) {
super._init({
style_class: 'workspace-background',
- layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
+ monitor_index: monitorIndex,
});
this._monitorIndex = monitorIndex;
@@ -957,6 +956,10 @@ class WorkspaceBackground extends St.Widget {
this._updateBorderRadius();
this.queue_relayout();
}, this);
+ this._stateAdjustment.bind_property(
+ 'value', this, 'state-adjustment-value',
+ GObject.BindingFlags.SYNC_CREATE
+ );
this._bin = new Clutter.Actor({
layout_manager: new Clutter.BinLayout(),
@@ -1011,52 +1014,6 @@ class WorkspaceBackground extends St.Widget {
this._bgManager.backgroundActor.content.set_rounded_clip_bounds(rect);
}
- vfunc_allocate(box) {
- const [width, height] = box.get_size();
- const { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
- const scaledHeight = height - (BACKGROUND_MARGIN * 2 * scaleFactor);
- const scaledWidth = (scaledHeight / height) * width;
-
- const scaledBox = box.copy();
- scaledBox.set_origin(
- box.x1 + (width - scaledWidth) / 2,
- box.y1 + (height - scaledHeight) / 2);
- scaledBox.set_size(scaledWidth, scaledHeight);
-
- const progress = this._stateAdjustment.value;
-
- if (progress === 1)
- box = scaledBox;
- else if (progress !== 0)
- box = box.interpolate(scaledBox, progress);
-
- this.set_allocation(box);
-
- const themeNode = this.get_theme_node();
- const contentBox = themeNode.get_content_box(box);
-
- this._bin.allocate(contentBox);
-
- const [contentWidth, contentHeight] = contentBox.get_size();
- const monitor = Main.layoutManager.monitors[this._monitorIndex];
- const [mX1, mX2] = [monitor.x, monitor.x + monitor.width];
- const [mY1, mY2] = [monitor.y, monitor.y + monitor.height];
- const [wX1, wX2] = [this._workarea.x, this._workarea.x + this._workarea.width];
- const [wY1, wY2] = [this._workarea.y, this._workarea.y + this._workarea.height];
- const xScale = contentWidth / this._workarea.width;
- const yScale = contentHeight / this._workarea.height;
- const leftOffset = wX1 - mX1;
- const topOffset = wY1 - mY1;
- const rightOffset = mX2 - wX2;
- const bottomOffset = mY2 - wY2;
-
- contentBox.set_origin(-leftOffset * xScale, -topOffset * yScale);
- contentBox.set_size(
- contentWidth + (leftOffset + rightOffset) * xScale,
- contentHeight + (topOffset + bottomOffset) * yScale);
- this._backgroundGroup.allocate(contentBox);
- }
-
_onDestroy() {
if (this._bgManager) {
this._bgManager.destroy();
diff --git a/src/meson.build b/src/meson.build
index e784a5132..fc7f8bfcc 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -112,7 +112,8 @@ libshell_public_headers = [
'shell-window-preview.h',
'shell-window-preview-layout.h',
'shell-window-tracker.h',
- 'shell-wm.h'
+ 'shell-wm.h',
+ 'shell-workspace-background.h'
]
if have_networkmanager
@@ -157,7 +158,8 @@ libshell_sources = [
'shell-window-preview.c',
'shell-window-preview-layout.c',
'shell-window-tracker.c',
- 'shell-wm.c'
+ 'shell-wm.c',
+ 'shell-workspace-background.c'
]
if have_networkmanager
diff --git a/src/shell-workspace-background.c b/src/shell-workspace-background.c
new file mode 100644
index 000000000..1c0bbc380
--- /dev/null
+++ b/src/shell-workspace-background.c
@@ -0,0 +1,226 @@
+#include "config.h"
+
+#include "shell-workspace-background.h"
+
+#include "shell-global.h"
+#include
+
+#define BACKGROUND_MARGIN 12
+
+enum
+{
+ PROP_0,
+
+ PROP_MONITOR_INDEX,
+ PROP_STATE_ADJUSTMENT_VALUE,
+
+ PROP_LAST
+};
+
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
+
+struct _ShellWorkspaceBackground
+{
+ /*< private >*/
+ StWidget parent_instance;
+
+ int monitor_index;
+ double state_adjustment_value;
+
+ MetaRectangle work_area;
+ MetaRectangle monitor_geometry;
+};
+
+G_DEFINE_TYPE (ShellWorkspaceBackground, shell_workspace_background, ST_TYPE_WIDGET);
+
+static void
+on_workareas_changed (ShellWorkspaceBackground *self)
+{
+ ShellGlobal *global = shell_global_get ();
+ MetaDisplay *display = shell_global_get_display (global);
+ MetaWorkspaceManager *workspace_manager = shell_global_get_workspace_manager (global);
+ MetaWorkspace *workspace =
+ meta_workspace_manager_get_workspace_by_index (workspace_manager, 0);
+
+ meta_workspace_get_work_area_for_monitor (workspace,
+ self->monitor_index,
+ &self->work_area);
+
+ meta_display_get_monitor_geometry (display,
+ self->monitor_index,
+ &self->monitor_geometry);
+}
+
+static void
+shell_workspace_background_allocate (ClutterActor *actor,
+ const ClutterActorBox *box)
+{
+ ShellWorkspaceBackground *self = SHELL_WORKSPACE_BACKGROUND (actor);
+ ShellGlobal *global = shell_global_get ();
+ ClutterStage *stage = shell_global_get_stage (global);
+ StThemeContext *context = st_theme_context_get_for_stage (stage);
+ StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (actor));
+ ClutterActorBox scaled_box, my_box, content_box;
+ ClutterActor *child;
+ float content_width, content_height;
+ float scaled_width, scaled_height;
+ float x_scale, y_scale;
+ float width, height;
+ int left_offset, right_offset;
+ int top_offset, bottom_offset;
+ int scale_factor;
+
+ scale_factor = st_theme_context_get_scale_factor (context);
+
+ clutter_actor_box_get_size (box, &width, &height);
+ scaled_height = height - BACKGROUND_MARGIN * 2 * scale_factor;
+ scaled_width = (scaled_height / height) * width;
+
+ scaled_box.x1 = box->x1 + (width - scaled_width) / 2;
+ scaled_box.y1 = box->y1 + (height - scaled_height) / 2;
+ clutter_actor_box_set_size (&scaled_box, scaled_width, scaled_height);
+
+ clutter_actor_box_interpolate(box, &scaled_box,
+ self->state_adjustment_value, &my_box);
+
+ clutter_actor_set_allocation (actor, &my_box);
+
+ st_theme_node_get_content_box (theme_node, &my_box, &content_box);
+
+ child = clutter_actor_get_first_child (actor);
+ clutter_actor_allocate (child, &content_box);
+
+ clutter_actor_box_get_size (&content_box, &content_width, &content_height);
+ x_scale = content_width / self->work_area.width;
+ y_scale = content_height / self->work_area.height;
+
+ left_offset = self->work_area.x - self->monitor_geometry.x;
+ top_offset = self->work_area.y - self->monitor_geometry.y;
+ right_offset = self->monitor_geometry.width - self->work_area.width - left_offset;
+ bottom_offset = self->monitor_geometry.height - self->work_area.height - top_offset;
+
+ clutter_actor_box_set_origin (&content_box,
+ -left_offset * x_scale,
+ -top_offset * y_scale);
+ clutter_actor_box_set_size (&content_box,
+ content_width + (left_offset + right_offset) * x_scale,
+ content_height + (top_offset + bottom_offset) * y_scale);
+
+ child = clutter_actor_get_first_child (child);
+ clutter_actor_allocate (child, &content_box);
+}
+
+static void
+shell_workspace_background_constructed (GObject *object)
+{
+ G_OBJECT_CLASS (shell_workspace_background_parent_class)->constructed (object);
+
+ on_workareas_changed (SHELL_WORKSPACE_BACKGROUND (object));
+}
+
+static void
+shell_workspace_background_get_property (GObject *gobject,
+ unsigned int property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ ShellWorkspaceBackground *self = SHELL_WORKSPACE_BACKGROUND (gobject);
+
+ switch (property_id)
+ {
+ case PROP_MONITOR_INDEX:
+ g_value_set_int (value, self->monitor_index);
+ break;
+
+ case PROP_STATE_ADJUSTMENT_VALUE:
+ g_value_set_double (value, self->state_adjustment_value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
+ }
+}
+
+static void
+shell_workspace_background_set_property (GObject *gobject,
+ unsigned int property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ ShellWorkspaceBackground *self = SHELL_WORKSPACE_BACKGROUND (gobject);
+
+ switch (property_id)
+ {
+ case PROP_MONITOR_INDEX:
+ {
+ int new_value = g_value_get_int (value);
+ if (self->monitor_index != new_value)
+ {
+ self->monitor_index = new_value;
+ g_object_notify_by_pspec (gobject, obj_props[PROP_MONITOR_INDEX]);
+ }
+ }
+ break;
+
+ case PROP_STATE_ADJUSTMENT_VALUE:
+ {
+ double new_value = g_value_get_double (value);
+ if (self->state_adjustment_value != new_value)
+ {
+ self->state_adjustment_value = new_value;
+ g_object_notify_by_pspec (gobject, obj_props[PROP_STATE_ADJUSTMENT_VALUE]);
+ }
+ }
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
+ }
+}
+
+static void
+shell_workspace_background_class_init (ShellWorkspaceBackgroundClass *klass)
+{
+ ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ actor_class->allocate = shell_workspace_background_allocate;
+
+ gobject_class->constructed = shell_workspace_background_constructed;
+ gobject_class->get_property = shell_workspace_background_get_property;
+ gobject_class->set_property = shell_workspace_background_set_property;
+
+ /**
+ * ShellWorkspaceBackground:monitor-index:
+ */
+ obj_props[PROP_MONITOR_INDEX] =
+ g_param_spec_int ("monitor-index", "", "",
+ 0, G_MAXINT, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY);
+
+ /**
+ * ShellWorkspaceBackground:state-adjustment-value:
+ */
+ obj_props[PROP_STATE_ADJUSTMENT_VALUE] =
+ g_param_spec_double ("state-adjustment-value", "", "",
+ -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS |
+ G_PARAM_EXPLICIT_NOTIFY);
+
+ g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
+}
+
+static void
+shell_workspace_background_init (ShellWorkspaceBackground *self)
+{
+ ShellGlobal *global = shell_global_get ();
+ MetaDisplay *display = shell_global_get_display (global);
+
+ g_signal_connect_object (display, "workareas-changed",
+ G_CALLBACK (on_workareas_changed),
+ self, G_CONNECT_SWAPPED);
+}
diff --git a/src/shell-workspace-background.h b/src/shell-workspace-background.h
new file mode 100644
index 000000000..48b2bd68f
--- /dev/null
+++ b/src/shell-workspace-background.h
@@ -0,0 +1,14 @@
+#ifndef __SHELL_WORKSPACE_BACKGROUND_H__
+#define __SHELL_WORKSPACE_BACKGROUND_H__
+
+#include
+
+G_BEGIN_DECLS
+
+#define SHELL_TYPE_WORKSPACE_BACKGROUND (shell_workspace_background_get_type ())
+G_DECLARE_FINAL_TYPE (ShellWorkspaceBackground, shell_workspace_background,
+ SHELL, WORKSPACE_BACKGROUND, StWidget)
+
+G_END_DECLS
+
+#endif /* __SHELL_WORKSPACE_BACKGROUND_H__ */