workspacesView: Add minimap on secondary monitors
The workspace minimap is much less prominent than the old workspace switcher, and serves primarily as an indicator. That means that duplicating it on secondary monitors (if workspaces on non-primaries are enabled) is harder to mistake for per-monitor workspaces, so make some people happy by including the minimap on every monitor. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1735>
This commit is contained in:
parent
082eedd968
commit
260f5b0b8d
@ -1,6 +1,6 @@
|
|||||||
/* OVERVIEW */
|
/* OVERVIEW */
|
||||||
|
|
||||||
.controls-manager {
|
.controls-manager, .secondary-monitor-workspaces {
|
||||||
spacing: 24px;
|
spacing: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ const OverviewControls = imports.ui.overviewControls;
|
|||||||
const SwipeTracker = imports.ui.swipeTracker;
|
const SwipeTracker = imports.ui.swipeTracker;
|
||||||
const Util = imports.misc.util;
|
const Util = imports.misc.util;
|
||||||
const Workspace = imports.ui.workspace;
|
const Workspace = imports.ui.workspace;
|
||||||
|
const { ThumbnailsBox, MAX_THUMBNAIL_SCALE } = imports.ui.workspaceThumbnail;
|
||||||
|
|
||||||
var WORKSPACE_SWITCH_TIME = 250;
|
var WORKSPACE_SWITCH_TIME = 250;
|
||||||
|
|
||||||
@ -604,6 +605,7 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
this._overviewAdjustment = overviewAdjustment;
|
this._overviewAdjustment = overviewAdjustment;
|
||||||
|
|
||||||
super._init({
|
super._init({
|
||||||
|
style_class: 'secondary-monitor-workspaces',
|
||||||
constraints: new Layout.MonitorConstraint({
|
constraints: new Layout.MonitorConstraint({
|
||||||
index: this._monitorIndex,
|
index: this._monitorIndex,
|
||||||
work_area: true,
|
work_area: true,
|
||||||
@ -612,13 +614,58 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
|
|
||||||
this.connect('destroy', () => this._onDestroy());
|
this.connect('destroy', () => this._onDestroy());
|
||||||
|
|
||||||
|
this._thumbnails = new ThumbnailsBox(
|
||||||
|
this._scrollAdjustment, monitorIndex);
|
||||||
|
this.add_child(this._thumbnails);
|
||||||
|
|
||||||
|
this._thumbnails.connect('notify::should-show',
|
||||||
|
() => this._updateThumbnailVisibility());
|
||||||
|
|
||||||
|
this._stateChangedId = this._overviewAdjustment.connect('notify::value',
|
||||||
|
() => this._updateThumbnailParams());
|
||||||
|
|
||||||
this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
|
this._settings = new Gio.Settings({ schema_id: MUTTER_SCHEMA });
|
||||||
this._settings.connect('changed::workspaces-only-on-primary',
|
this._settings.connect('changed::workspaces-only-on-primary',
|
||||||
() => this._updateWorkspacesView());
|
() => this._workspacesOnPrimaryChanged());
|
||||||
this._updateWorkspacesView();
|
this._workspacesOnPrimaryChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
_getWorkspacesBoxForState(state, box, padding) {
|
_getThumbnailParamsForState(state) {
|
||||||
|
const { ControlsState } = OverviewControls;
|
||||||
|
|
||||||
|
let opacity, scale;
|
||||||
|
switch (state) {
|
||||||
|
case ControlsState.HIDDEN:
|
||||||
|
case ControlsState.WINDOW_PICKER:
|
||||||
|
opacity = 255;
|
||||||
|
scale = 1;
|
||||||
|
break;
|
||||||
|
case ControlsState.APP_GRID:
|
||||||
|
opacity = 0;
|
||||||
|
scale = 0.5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opacity = 255;
|
||||||
|
scale = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { opacity, scale };
|
||||||
|
}
|
||||||
|
|
||||||
|
_getThumbnailsHeight(box) {
|
||||||
|
if (!this._thumbnails.visible)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const [width, height] = box.get_size();
|
||||||
|
const { expandFraction } = this._thumbnails;
|
||||||
|
const [thumbnailsHeight] = this._thumbnails.get_preferred_height(width);
|
||||||
|
return Math.min(
|
||||||
|
thumbnailsHeight * expandFraction,
|
||||||
|
height * MAX_THUMBNAIL_SCALE);
|
||||||
|
}
|
||||||
|
|
||||||
|
_getWorkspacesBoxForState(state, box, padding, thumbnailsHeight, spacing) {
|
||||||
const { ControlsState } = OverviewControls;
|
const { ControlsState } = OverviewControls;
|
||||||
const workspaceBox = box.copy();
|
const workspaceBox = box.copy();
|
||||||
const [width, height] = workspaceBox.get_size();
|
const [width, height] = workspaceBox.get_size();
|
||||||
@ -627,6 +674,11 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
case ControlsState.HIDDEN:
|
case ControlsState.HIDDEN:
|
||||||
break;
|
break;
|
||||||
case ControlsState.WINDOW_PICKER:
|
case ControlsState.WINDOW_PICKER:
|
||||||
|
workspaceBox.set_origin(0, padding + thumbnailsHeight + spacing);
|
||||||
|
workspaceBox.set_size(
|
||||||
|
width,
|
||||||
|
height - 2 * padding - thumbnailsHeight - spacing);
|
||||||
|
break;
|
||||||
case ControlsState.APP_GRID:
|
case ControlsState.APP_GRID:
|
||||||
workspaceBox.set_origin(0, padding);
|
workspaceBox.set_origin(0, padding);
|
||||||
workspaceBox.set_size(
|
workspaceBox.set_size(
|
||||||
@ -643,16 +695,27 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
|
|
||||||
const themeNode = this.get_theme_node();
|
const themeNode = this.get_theme_node();
|
||||||
const contentBox = themeNode.get_content_box(box);
|
const contentBox = themeNode.get_content_box(box);
|
||||||
const [, height] = contentBox.get_size();
|
const [width, height] = contentBox.get_size();
|
||||||
|
const { expandFraction } = this._thumbnails;
|
||||||
|
const spacing = themeNode.get_length('spacing') * expandFraction;
|
||||||
const padding =
|
const padding =
|
||||||
Math.round((1 - SECONDARY_WORKSPACE_SCALE) * height / 2);
|
Math.round((1 - SECONDARY_WORKSPACE_SCALE) * height / 2);
|
||||||
|
|
||||||
|
const thumbnailsHeight = this._getThumbnailsHeight(contentBox);
|
||||||
|
|
||||||
|
if (this._thumbnails.visible) {
|
||||||
|
const childBox = new Clutter.ActorBox();
|
||||||
|
childBox.set_origin(0, padding);
|
||||||
|
childBox.set_size(width, thumbnailsHeight);
|
||||||
|
this._thumbnails.allocate(childBox);
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
currentState, initialState, finalState, transitioning, progress,
|
currentState, initialState, finalState, transitioning, progress,
|
||||||
} = this._overviewAdjustment.getStateTransitionParams();
|
} = this._overviewAdjustment.getStateTransitionParams();
|
||||||
|
|
||||||
let workspacesBox;
|
let workspacesBox;
|
||||||
const workspaceParams = [contentBox, padding];
|
const workspaceParams = [contentBox, padding, thumbnailsHeight, spacing];
|
||||||
if (!transitioning) {
|
if (!transitioning) {
|
||||||
workspacesBox =
|
workspacesBox =
|
||||||
this._getWorkspacesBoxForState(currentState, ...workspaceParams);
|
this._getWorkspacesBoxForState(currentState, ...workspaceParams);
|
||||||
@ -670,6 +733,15 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
if (this._settings)
|
if (this._settings)
|
||||||
this._settings.run_dispose();
|
this._settings.run_dispose();
|
||||||
this._settings = null;
|
this._settings = null;
|
||||||
|
|
||||||
|
if (this._stateChangedId)
|
||||||
|
this._overviewAdjustment.disconnect(this._stateChangedId);
|
||||||
|
this._stateChangedId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_workspacesOnPrimaryChanged() {
|
||||||
|
this._updateWorkspacesView();
|
||||||
|
this._updateThumbnailVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateWorkspacesView() {
|
_updateWorkspacesView() {
|
||||||
@ -691,6 +763,41 @@ class SecondaryMonitorDisplay extends St.Widget {
|
|||||||
this.add_child(this._workspacesView);
|
this.add_child(this._workspacesView);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_updateThumbnailVisibility() {
|
||||||
|
const visible =
|
||||||
|
this._thumbnails.should_show &&
|
||||||
|
!this._settings.get_boolean('workspaces-only-on-primary');
|
||||||
|
|
||||||
|
if (this._thumbnails.visible === visible)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this._thumbnails.show();
|
||||||
|
this._thumbnails.ease_property('expand-fraction', visible ? 1 : 0, {
|
||||||
|
duration: OverviewControls.SIDE_CONTROLS_ANIMATION_TIME,
|
||||||
|
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
|
||||||
|
onComplete: () => (this._thumbnails.visible = visible),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_updateThumbnailParams() {
|
||||||
|
const { initialState, finalState, progress } =
|
||||||
|
this._overviewAdjustment.getStateTransitionParams();
|
||||||
|
|
||||||
|
const initialParams = this._getThumbnailParamsForState(initialState);
|
||||||
|
const finalParams = this._getThumbnailParamsForState(finalState);
|
||||||
|
|
||||||
|
const opacity =
|
||||||
|
Util.lerp(initialParams.opacity, finalParams.opacity, progress);
|
||||||
|
const scale =
|
||||||
|
Util.lerp(initialParams.scale, finalParams.scale, progress);
|
||||||
|
|
||||||
|
this._thumbnails.set({
|
||||||
|
opacity,
|
||||||
|
scale_x: scale,
|
||||||
|
scale_y: scale,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getActiveWorkspace() {
|
getActiveWorkspace() {
|
||||||
return this._workspacesView.getActiveWorkspace();
|
return this._workspacesView.getActiveWorkspace();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user