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__ */