diff options
Diffstat (limited to '')
-rw-r--r-- | src/shell-workspace-background.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/shell-workspace-background.c b/src/shell-workspace-background.c new file mode 100644 index 0000000..1c0bbc3 --- /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 <meta/meta-workspace-manager.h> + +#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); +} |