diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss index ae30dfc..9e0751c 100644 --- a/data/theme/gnome-shell-sass/_common.scss +++ b/data/theme/gnome-shell-sass/_common.scss @@ -688,7 +688,8 @@ StScrollBar { 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; background-color: $selected_bg_color; color: $selected_fg_color; diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js index b9f5fef..dfe1b44 100644 --- a/js/ui/windowManager.js +++ b/js/ui/windowManager.js @@ -2145,6 +2145,8 @@ var WindowManager = class { let [action,,,target] = binding.get_name().split('-'); let newWs; let direction; + let vertical = workspaceManager.layout_rows == -1; + let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL; if (action == 'move') { // "Moving" a window to another workspace doesn't make sense when @@ -2157,7 +2159,12 @@ var WindowManager = class { } 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 = workspaceManager.get_workspace_by_index(workspaceManager.n_workspaces - 1); } else if (isNaN(target)) { // Prepend a new workspace dynamically @@ -2173,16 +2180,33 @@ var WindowManager = class { target--; newWs = workspaceManager.get_workspace_by_index(target); - if (workspaceManager.get_active_workspace().index() > target) - direction = Meta.MotionDirection.UP; - else - direction = Meta.MotionDirection.DOWN; + if (workspaceManager.get_active_workspace().index() > target) { + if (vertical) + direction = Meta.MotionDirection.UP; + 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 (workspaceManager.layout_rows == -1 && + direction != Meta.MotionDirection.UP && direction != Meta.MotionDirection.DOWN) return; + if (workspaceManager.layout_columns == -1 && + direction != Meta.MotionDirection.LEFT && + direction != Meta.MotionDirection.RIGHT) + return; + if (action == 'switch') this.actionMoveWorkspace(newWs); else diff --git a/js/ui/workspaceSwitcherPopup.js b/js/ui/workspaceSwitcherPopup.js index 26404ea..d21c5de 100644 --- a/js/ui/workspaceSwitcherPopup.js +++ b/js/ui/workspaceSwitcherPopup.js @@ -17,41 +17,75 @@ class WorkspaceSwitcherPopupList extends St.Widget { this._itemSpacing = 0; this._childHeight = 0; this._childWidth = 0; + this._orientation = global.workspace_manager.layout_rows == -1 + ? Clutter.Orientation.VERTICAL + : Clutter.Orientation.HORIZONTAL; this.connect('style-changed', () => { this._itemSpacing = this.get_theme_node().get_length('spacing'); }); } - vfunc_get_preferred_height(forWidth) { + _getPreferredSizeForOrientation(forSize) { let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); let themeNode = this.get_theme_node(); - let availHeight = workArea.height; - availHeight -= themeNode.get_vertical_padding(); + let availSize; + if (this._orientation == Clutter.Orientation.HORIZONTAL) + availSize = workArea.width - themeNode.get_horizontal_padding(); + else + availSize = workArea.height - themeNode.get_vertical_padding(); - let height = 0; + let size = 0; for (let child of this.get_children()) { let [childMinHeight, childNaturalHeight] = child.get_preferred_height(-1); - let [childMinWidth, childNaturalWidth] = child.get_preferred_width(childNaturalHeight); - height += childNaturalHeight * workArea.width / workArea.height; + let height = childNaturalHeight * workArea.width / workArea.height; + + if (this._orientation == Clutter.Orientation.HORIZONTAL) { + size += height * workArea.width / workArea.height; + } else { + size += height; + } } let workspaceManager = global.workspace_manager; let spacing = this._itemSpacing * (workspaceManager.n_workspaces - 1); - height += spacing; - height = Math.min(height, availHeight); + size += spacing; + size = Math.min(size, availSize); + + if (this._orientation == Clutter.Orientation.HORIZONTAL) { + this._childWidth = (size - spacing) / workspaceManager.n_workspaces; + return themeNode.adjust_preferred_width(size, size); + } else { + this._childHeight = (size - spacing) / workspaceManager.n_workspaces; + return themeNode.adjust_preferred_height(size, size); + } + } + + _getSizeForOppositeOrientation() { + let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); - this._childHeight = (height - spacing) / workspaceManager.n_workspaces; + 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]; + } + } - return themeNode.adjust_preferred_height(height, height); + vfunc_get_preferred_height(forWidth) { + if (this._orientation == Clutter.Orientation.HORIZONTAL) + return this._getSizeForOppositeOrientation(); + else + return this._getPreferredSizeForOrientation(forWidth); } vfunc_get_preferred_width(forHeight) { - let workArea = Main.layoutManager.getWorkAreaForMonitor(Main.layoutManager.primaryIndex); - this._childWidth = Math.round(this._childHeight * workArea.width / workArea.height); - - return [this._childWidth, this._childWidth]; + if (this._orientation == Clutter.Orientation.HORIZONTAL) + return this._getPreferredSizeForOrientation(forHeight); + else + return this._getSizeForOppositeOrientation(); } vfunc_allocate(box, flags) { @@ -62,15 +96,23 @@ class WorkspaceSwitcherPopupList extends St.Widget { 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 prevChildBoxY2 = box.y1 - this._itemSpacing; for (let child of this.get_children()) { - childBox.x1 = box.x1; - childBox.x2 = box.x1 + this._childWidth; - childBox.y1 = prevChildBoxY2 + this._itemSpacing; + childBox.x1 = Math.round(x); + childBox.x2 = Math.round(x + this._childWidth); + childBox.y1 = Math.round(y); 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; + } child.allocate(childBox, flags); } } @@ -123,6 +165,10 @@ class WorkspaceSwitcherPopup extends St.Widget { indicator = new St.Bin({ style_class: 'ws-switcher-active-up' }); else if(i == this._activeWorkspaceIndex && this._direction == Meta.MotionDirection.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 indicator = new St.Bin({ style_class: 'ws-switcher-box' }); diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js index fe06d9d..069937d 100644 --- a/js/ui/workspacesView.js +++ b/js/ui/workspacesView.js @@ -181,26 +181,32 @@ var WorkspacesView = class extends WorkspacesViewBase { Tweener.removeTweens(workspace.actor); - let y = (w - active) * this._fullGeometry.height; + let params = {}; + if (workspaceManager.layout_rows == -1) + params.y = (w - active) * this._fullGeometry.height; + else if (this.actor.text_direction == Clutter.TextDirection.RTL) + params.x = (active - w) * this._fullGeometry.width; + else + params.x = (w - active) * this._fullGeometry.width; if (showAnimation) { - let params = { y: y, - time: WORKSPACE_SWITCH_TIME, - transition: 'easeOutQuad' - }; + let tweenParams = Object.assign(params, { + time: WORKSPACE_SWITCH_TIME, + transition: 'easeOutQuad' + }); // we have to call _updateVisibility() once before the // animation and once afterwards - it does not really // matter which tween we use, so we pick the first one ... if (w == 0) { this._updateVisibility(); - params.onComplete = () => { + tweenParams.onComplete = () => { this._animating = false; this._updateVisibility(); }; } - Tweener.addTween(workspace.actor, params); + Tweener.addTween(workspace.actor, tweenParams); } else { - workspace.actor.set_position(0, y); + workspace.actor.set(params); if (w == 0) this._updateVisibility(); } @@ -338,22 +344,39 @@ var WorkspacesView = class extends WorkspacesViewBase { metaWorkspace.activate(global.get_current_time()); } - let last = this._workspaces.length - 1; - let firstWorkspaceY = this._workspaces[0].actor.y; - let lastWorkspaceY = this._workspaces[last].actor.y; - let workspacesHeight = lastWorkspaceY - firstWorkspaceY; - if (adj.upper == 1) return; - let currentY = firstWorkspaceY; - let newY = - adj.value / (adj.upper - 1) * workspacesHeight; + let last = this._workspaces.length - 1; + + if (workspaceManager.layout_rows == -1) { + let firstWorkspaceY = this._workspaces[0].actor.y; + let lastWorkspaceY = this._workspaces[last].actor.y; + let workspacesHeight = lastWorkspaceY - firstWorkspaceY; + + let currentY = firstWorkspaceY; + let newY = -adj.value / (adj.upper - 1) * workspacesHeight; - let dy = newY - currentY; + let dy = newY - currentY; + + for (let i = 0; i < this._workspaces.length; i++) { + this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; + this._workspaces[i].actor.y += dy; + } + } else { + let firstWorkspaceX = this._workspaces[0].actor.x; + let lastWorkspaceX = this._workspaces[last].actor.x; + let workspacesWidth = lastWorkspaceX - firstWorkspaceX; - for (let i = 0; i < this._workspaces.length; i++) { - this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; - this._workspaces[i].actor.y += dy; + let currentX = firstWorkspaceX; + let newX = -adj.value / (adj.upper - 1) * workspacesWidth; + + let dx = newX - currentX; + + for (let i = 0; i < this._workspaces.length; i++) { + this._workspaces[i].actor.visible = Math.abs(i - adj.value) <= 1; + this._workspaces[i].actor.x += dx; + } } } }; @@ -504,7 +527,12 @@ var WorkspacesDisplay = class { _onPan(action) { let [dist, dx, dy] = action.get_motion_delta(0); let adjustment = this._scrollAdjustment; - adjustment.value -= (dy / this.actor.height) * adjustment.page_size; + if (global.workspace_manager.layout_rows == -1) + adjustment.value -= (dy / this.actor.height) * adjustment.page_size; + else if (this.actor.text_direction == Clutter.TextDirection.RTL) + adjustment.value += (dx / this.actor.width) * adjustment.page_size; + else + adjustment.value -= (dx / this.actor.width) * adjustment.page_size; return false; } @@ -536,7 +564,12 @@ var WorkspacesDisplay = class { let workspaceManager = global.workspace_manager; let active = workspaceManager.get_active_workspace_index(); let adjustment = this._scrollAdjustment; - adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size; + if (workspaceManager.layout_rows == -1) + adjustment.value = (active - yRel / this.actor.height) * adjustment.page_size; + else if (this.actor.text_direction == Clutter.TextDirection.RTL) + adjustment.value = (active + xRel / this.actor.width) * adjustment.page_size; + else + adjustment.value = (active - xRel / this.actor.width) * adjustment.page_size; } _onSwitchWorkspaceActivated(action, direction) { @@ -755,6 +788,12 @@ var WorkspacesDisplay = class { case Clutter.ScrollDirection.DOWN: ws = activeWs.get_neighbor(Meta.MotionDirection.DOWN); break; + case Clutter.ScrollDirection.LEFT: + ws = activeWs.get_neighbor(Meta.MotionDirection.LEFT); + break; + case Clutter.ScrollDirection.RIGHT: + ws = activeWs.get_neighbor(Meta.MotionDirection.RIGHT); + break; default: return Clutter.EVENT_PROPAGATE; }