workspaceSwitcherPopup: Support horizontal layout

While mutter supports a variety of different grid layouts (n columns/rows,
growing vertically or horizontally from any of the four corners), we
hardcode a fixed vertical layout of a single column.

Now that mutter exposes the actual layout to us, add support for a more
traditional horizontal layout as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575
This commit is contained in:
Florian Müllner 2019-06-04 19:22:26 +00:00 committed by Ray Strode
parent 8d3dd1a02f
commit e287e7b319
3 changed files with 105 additions and 32 deletions

View file

@ -683,7 +683,8 @@ StScrollBar {
spacing: 8px; spacing: 8px;
} }
.ws-switcher-active-up, .ws-switcher-active-down { .ws-switcher-active-up, .ws-switcher-active-down,
.ws-switcher-active-left, .ws-switcher-active-right {
height: 50px; height: 50px;
background-color: $selected_bg_color; background-color: $selected_bg_color;
color: $selected_fg_color; color: $selected_fg_color;

View file

@ -1890,6 +1890,8 @@ var WindowManager = new Lang.Class({
let [action,,,target] = binding.get_name().split('-'); let [action,,,target] = binding.get_name().split('-');
let newWs; let newWs;
let direction; let direction;
let vertical = screen.layout_rows == -1;
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
if (action == 'move') { if (action == 'move') {
// "Moving" a window to another workspace doesn't make sense when // "Moving" a window to another workspace doesn't make sense when
@ -1902,7 +1904,12 @@ var WindowManager = new Lang.Class({
} }
if (target == 'last') { if (target == 'last') {
direction = Meta.MotionDirection.DOWN; if (vertical)
direction = Meta.MotionDirection.DOWN;
else if (rtl)
direction = Meta.MotionDirection.LEFT;
else
direction = Meta.MotionDirection.RIGHT;
newWs = screen.get_workspace_by_index(screen.n_workspaces - 1); newWs = screen.get_workspace_by_index(screen.n_workspaces - 1);
} else if (isNaN(target)) { } else if (isNaN(target)) {
// Prepend a new workspace dynamically // Prepend a new workspace dynamically
@ -1918,16 +1925,33 @@ var WindowManager = new Lang.Class({
target--; target--;
newWs = screen.get_workspace_by_index(target); newWs = screen.get_workspace_by_index(target);
if (screen.get_active_workspace().index() > target) if (screen.get_active_workspace().index() > target) {
direction = Meta.MotionDirection.UP; if (vertical)
else direction = Meta.MotionDirection.UP;
direction = Meta.MotionDirection.DOWN; else if (rtl)
direction = Meta.MotionDirection.RIGHT;
else
direction = Meta.MotionDirection.LEFT;
} else {
if (vertical)
direction = Meta.MotionDirection.DOWN;
else if (rtl)
direction = Meta.MotionDirection.LEFT;
else
direction = Meta.MotionDirection.RIGHT;
}
} }
if (direction != Meta.MotionDirection.UP && if (screen.layout_rows == -1 &&
direction != Meta.MotionDirection.UP &&
direction != Meta.MotionDirection.DOWN) direction != Meta.MotionDirection.DOWN)
return; return;
if (screen.layout_columns == -1 &&
direction != Meta.MotionDirection.LEFT &&
direction != Meta.MotionDirection.RIGHT)
return;
if (action == 'switch') if (action == 'switch')
this.actionMoveWorkspace(newWs); this.actionMoveWorkspace(newWs);
else else

View file

@ -32,6 +32,10 @@ var WorkspaceSwitcherPopup = new Lang.Class({
this._childHeight = 0; this._childHeight = 0;
this._childWidth = 0; this._childWidth = 0;
this._timeoutId = 0; this._timeoutId = 0;
this._orientation = global.screen.layout_rows == -1
? Clutter.Orientation.VERTICAL
: Clutter.Orientation.HORIZONTAL;
this._list.connect('style-changed', () => { this._list.connect('style-changed', () => {
this._itemSpacing = this._list.get_theme_node().get_length('spacing'); this._itemSpacing = this._list.get_theme_node().get_length('spacing');
}); });
@ -52,53 +56,93 @@ var WorkspaceSwitcherPopup = new Lang.Class({
this._globalSignals.push(global.screen.connect('workspace-removed', this._redisplay.bind(this))); this._globalSignals.push(global.screen.connect('workspace-removed', this._redisplay.bind(this)));
}, },
_getPreferredHeight(actor, forWidth, alloc) { _getPreferredSizeForOrientation(forSize) {
let children = this._list.get_children(); let children = this._list.get_children();
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
let themeNode = this.actor.get_theme_node();
let availHeight = workArea.height; let availSize;
availHeight -= this.actor.get_theme_node().get_vertical_padding(); if (this._orientation == Clutter.Orientation.HORIZONTAL) {
availHeight -= this._container.get_theme_node().get_vertical_padding(); availSize = workArea.width - themeNode.get_horizontal_padding();
availHeight -= this._list.get_theme_node().get_vertical_padding(); availSize -= this._container.get_theme_node().get_horizontal_padding();
availSize -= this._list.get_theme_node().get_horizontal_padding();
} else {
availSize = workArea.height - themeNode.get_vertical_padding();
availSize -= this._container.get_theme_node().get_vertical_padding();
availSize -= this._list.get_theme_node().get_vertical_padding();
}
let height = 0; let size = 0;
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
let [childMinHeight, childNaturalHeight] = children[i].get_preferred_height(-1); let [childMinHeight, childNaturalHeight] = children[i].get_preferred_height(-1);
let [childMinWidth, childNaturalWidth] = children[i].get_preferred_width(childNaturalHeight); let height = childNaturalHeight * workArea.width / workArea.height;
height += childNaturalHeight * workArea.width / workArea.height;
if (this._orientation == Clutter.Orientation.HORIZONTAL)
size += height * workArea.width / workArea.height;
else
size += height;
} }
let spacing = this._itemSpacing * (global.screen.n_workspaces - 1); let spacing = this._itemSpacing * (global.screen.n_workspaces - 1);
height += spacing; size += spacing;
height = Math.min(height, availHeight); size = Math.min(size, availSize);
this._childHeight = (height - spacing) / global.screen.n_workspaces; if (this._orientation == Clutter.Orientation.HORIZONTAL) {
this._childWidth = (size - spacing) / global.screen.n_workspaces;
return themeNode.adjust_preferred_width(size, size);
} else {
this._childHeight = (size - spacing) / global.screen.n_workspaces;
return themeNode.adjust_preferred_height(size, size);
}
},
alloc.min_size = height; _getSizeForOppositeOrientation() {
alloc.natural_size = height; let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex);
if (this._orientation == Clutter.Orientation.HORIZONTAL) {
this._childHeight = Math.round(this._childWidth * workArea.height / workArea.width);
return [this._childHeight, this._childHeight];
} else {
this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height);
return [this._childWidth, this._childWidth];
}
},
_getPreferredHeight(actor, forWidth, alloc) {
if (this._orientation == Clutter.Orientation.HORIZONTAL)
[alloc.min_size, alloc.natural_size] = this._getSizeForOppositeOrientation();
else
[alloc.min_size, alloc.natural_size] = this._getPreferredSizeForOrientation(forWidth);
}, },
_getPreferredWidth(actor, forHeight, alloc) { _getPreferredWidth(actor, forHeight, alloc) {
let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); if (this._orientation == Clutter.Orientation.HORIZONTAL)
this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height); [alloc.min_size, alloc.natural_size] = this._getPreferredSizeForOrientation(forHeight);
else
alloc.min_size = this._childWidth; [alloc.min_size, alloc.natural_size] = this._getSizeForOppositeOrientation();
alloc.natural_size = this._childWidth;
}, },
_allocate(actor, box, flags) { _allocate(actor, box, flags) {
let children = this._list.get_children(); let children = this._list.get_children();
let childBox = new Clutter.ActorBox(); let childBox = new Clutter.ActorBox();
let rtl = this.text_direction == Clutter.TextDirection.RTL;
let x = rtl ? box.x2 - this._childWidth : box.x1;
let y = box.y1; let y = box.y1;
let prevChildBoxY2 = box.y1 - this._itemSpacing;
for (let i = 0; i < children.length; i++) { for (let i = 0; i < children.length; i++) {
childBox.x1 = box.x1; childBox.x1 = Math.round(x);
childBox.x2 = box.x1 + this._childWidth; childBox.x2 = Math.round(x + this._childWidth);
childBox.y1 = prevChildBoxY2 + this._itemSpacing; childBox.y1 = Math.round(y);
childBox.y2 = Math.round(y + this._childHeight); childBox.y2 = Math.round(y + this._childHeight);
y += this._childHeight + this._itemSpacing;
prevChildBoxY2 = childBox.y2; if (this._orientation == Clutter.Orientation.HORIZONTAL) {
if (rtl)
x -= this._childWidth + this._itemSpacing;
else
x += this._childWidth + this._itemSpacing;
} else {
y += this._childHeight + this._itemSpacing;
}
children[i].allocate(childBox, flags); children[i].allocate(childBox, flags);
} }
}, },
@ -111,8 +155,12 @@ var WorkspaceSwitcherPopup = new Lang.Class({
if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP) if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.UP)
indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-up' });
else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN) else if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.DOWN)
indicator = new St.Bin({ style_class: 'ws-switcher-active-down' }); indicator = new St.Bin({ style_class: 'ws-switcher-active-down' });
else if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.LEFT)
indicator = new St.Bin({ style_class: 'ws-switcher-active-left' });
else if (i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.RIGHT)
indicator = new St.Bin({ style_class: 'ws-switcher-active-right' });
else else
indicator = new St.Bin({ style_class: 'ws-switcher-box' }); indicator = new St.Bin({ style_class: 'ws-switcher-box' });