[gnome-shell] Make Dash horizontal



commit 97eb4560efa2ea15d657c3f7cc057b6075862a46
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Fri Dec 11 09:47:28 2020 -0300

    Make Dash horizontal
    
    And move it to the bottom of the overview. Change the height-based calculation
    of the icon sizes to be width-based. Put the DashFader in a vertical box, and
    make all corners of the Dash equally rounded.
    
    Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1559>

 data/theme/gnome-shell-sass/widgets/_dash.scss | 10 +--
 js/ui/dash.js                                  | 91 +++++++++++++-------------
 js/ui/overviewControls.js                      | 71 ++++++++++----------
 3 files changed, 85 insertions(+), 87 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_dash.scss b/data/theme/gnome-shell-sass/widgets/_dash.scss
index c639fad6a2..22e538a617 100644
--- a/data/theme/gnome-shell-sass/widgets/_dash.scss
+++ b/data/theme/gnome-shell-sass/widgets/_dash.scss
@@ -7,14 +7,10 @@ $dash_border_radius: $modal_radius * 1.5;
 #dash {
   @extend %overview_panel;
   @include fontsize($base_font_size - 2);
+  margin: $base_margin * 4 $base_margin * 2;
   padding: ($dash_spacing / 2) 0;
 
-  border-radius: 0 $dash_border_radius $dash_border_radius 0; 
-  border-left-width: 0;
-  &:rtl {
-    border-radius: $dash_border_radius 0 0 $dash_border_radius;
-    border-right-width: 0;
-  }
+  border-radius: $dash_border_radius;
 
   .placeholder {
     // background-image: url("resource:///org/gnome/shell/theme/dash-placeholder.svg");
@@ -43,7 +39,7 @@ $dash_border_radius: $modal_radius * 1.5;
   color: $osd_fg_color;
   padding: $base_padding $base_padding + 2px;
   text-align: center;
-  -x-offset: $base_margin * 2; // distance from the dash edge
+  -y-offset: $base_margin * 3; // distance from the dash edge
 }
 
 // Show apps button
diff --git a/js/ui/dash.js b/js/ui/dash.js
index 650e07c4b7..a4dc7a8fb5 100644
--- a/js/ui/dash.js
+++ b/js/ui/dash.js
@@ -105,21 +105,16 @@ class DashItemContainer extends St.Widget {
 
         let [stageX, stageY] = this.get_transformed_position();
 
-        let itemHeight = this.allocation.y2 - this.allocation.y1;
+        const itemWidth = this.allocation.get_width();
 
-        let labelHeight = this.label.get_height();
-        let yOffset = Math.floor((itemHeight - labelHeight) / 2);
-
-        let y = stageY + yOffset;
+        const labelWidth = this.label.get_width();
+        const xOffset = Math.floor((itemWidth - labelWidth) / 2);
+        const x = Math.clamp(stageX + xOffset, 0, global.stage.width - labelWidth);
 
         let node = this.label.get_theme_node();
-        let xOffset = node.get_length('-x-offset');
+        const yOffset = node.get_length('-y-offset');
 
-        let x;
-        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
-            x = stageX - this.label.get_width() - xOffset;
-        else
-            x = stageX + this.get_width() + xOffset;
+        const y = stageY - this.label.height - yOffset;
 
         this.label.set_position(x, y);
         this.label.ease({
@@ -283,51 +278,51 @@ class EmptyDropTargetItem extends DashItemContainer {
 var DashActor = GObject.registerClass(
 class DashActor extends St.Widget {
     _init() {
-        let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.VERTICAL });
+        let layout = new Clutter.BoxLayout({ orientation: Clutter.Orientation.HORIZONTAL });
         super._init({
             name: 'dash',
             layout_manager: layout,
             clip_to_allocation: true,
-            y_align: Clutter.ActorAlign.CENTER,
+            x_align: Clutter.ActorAlign.CENTER,
         });
     }
 
     vfunc_allocate(box) {
         let contentBox = this.get_theme_node().get_content_box(box);
-        let availWidth = contentBox.x2 - contentBox.x1;
+        const availHeight = contentBox.get_height();
 
         this.set_allocation(box);
 
         let [appIcons, showAppsButton] = this.get_children();
-        let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
+        const [, showAppsNatWidth] = showAppsButton.get_preferred_width(availHeight);
 
         let childBox = new Clutter.ActorBox();
         childBox.x1 = contentBox.x1;
         childBox.y1 = contentBox.y1;
-        childBox.x2 = contentBox.x2;
-        childBox.y2 = contentBox.y2 - showAppsNatHeight;
+        childBox.x2 = contentBox.x2 - showAppsNatWidth;
+        childBox.y2 = contentBox.y2;
         appIcons.allocate(childBox);
 
-        childBox.y1 = contentBox.y2 - showAppsNatHeight;
-        childBox.y2 = contentBox.y2;
+        childBox.x1 = contentBox.x2 - showAppsNatWidth;
+        childBox.x2 = contentBox.x2;
         showAppsButton.allocate(childBox);
     }
 
-    vfunc_get_preferred_height(forWidth) {
-        // We want to request the natural height of all our children
-        // as our natural height, so we chain up to StWidget (which
+    vfunc_get_preferred_width(forHeight) {
+        // We want to request the natural width of all our children
+        // as our natural width, so we chain up to StWidget (which
         // then calls BoxLayout), but we only request the showApps
         // button as the minimum size
 
-        let [, natHeight] = super.vfunc_get_preferred_height(forWidth);
+        const [, natWidth] = super.vfunc_get_preferred_width(forHeight);
 
         let themeNode = this.get_theme_node();
-        let adjustedForWidth = themeNode.adjust_for_width(forWidth);
+        const adjustedForHeight = themeNode.adjust_for_height(forHeight);
         let [, showAppsButton] = this.get_children();
-        let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth);
-        [minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight);
+        let [minWidth] = showAppsButton.get_preferred_width(adjustedForHeight);
+        [minWidth] = themeNode.adjust_preferred_width(minWidth, natWidth);
 
-        return [minHeight, natHeight];
+        return [minWidth, natWidth];
     }
 });
 
@@ -337,7 +332,7 @@ var Dash = GObject.registerClass({
     Signals: { 'icon-size-changed': {} },
 }, class Dash extends St.Bin {
     _init() {
-        this._maxHeight = -1;
+        this._maxWidth = -1;
         this.iconSize = 64;
         this._shownInitially = false;
 
@@ -349,8 +344,7 @@ var Dash = GObject.registerClass({
         this._labelShowing = false;
 
         this._container = new DashActor();
-        this._box = new St.BoxLayout({ vertical: true,
-                                       clip_to_allocation: true });
+        this._box = new St.BoxLayout({ clip_to_allocation: true });
         this._box._delegate = this;
         this._container.add_actor(this._box);
         this._container.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
@@ -365,10 +359,10 @@ var Dash = GObject.registerClass({
         this._container.add_actor(this._showAppsIcon);
 
         super._init({ child: this._container });
-        this.connect('notify::height', () => {
-            if (this._maxHeight != this.height)
+        this.connect('notify::width', () => {
+            if (this._maxWidth !== this.width)
                 this._queueRedisplay();
-            this._maxHeight = this.height;
+            this._maxWidth = this.width;
         });
 
         this._workId = Main.initializeDeferredWork(this._box, this._redisplay.bind(this));
@@ -567,15 +561,18 @@ var Dash = GObject.registerClass({
 
         iconChildren.push(this._showAppsIcon);
 
-        if (this._maxHeight == -1)
+        if (this._maxWidth === -1)
             return;
 
         let themeNode = this._container.get_theme_node();
-        let maxAllocation = new Clutter.ActorBox({ x1: 0, y1: 0,
-                                                   x2: 42 /* whatever */,
-                                                   y2: this._maxHeight });
+        const maxAllocation = new Clutter.ActorBox({
+            x1: 0,
+            y1: 0,
+            x2: this._maxWidth,
+            y2: 42, /* whatever */
+        });
         let maxContent = themeNode.get_content_box(maxAllocation);
-        let availHeight = maxContent.y2 - maxContent.y1;
+        let availWidth = maxContent.x2 - maxContent.x1;
         let spacing = themeNode.get_length('spacing');
 
         let firstButton = iconChildren[0].child;
@@ -583,14 +580,14 @@ var Dash = GObject.registerClass({
 
         // Enforce valid spacings during the size request
         firstIcon.icon.ensure_style();
-        let [, iconHeight] = firstIcon.icon.get_preferred_height(-1);
-        let [, buttonHeight] = firstButton.get_preferred_height(-1);
+        let [, iconWidth] = firstIcon.icon.get_preferred_width(-1);
+        let [, buttonWidth] = firstButton.get_preferred_width(-1);
 
-        // Subtract icon padding and box spacing from the available height
-        availHeight -= iconChildren.length * (buttonHeight - iconHeight) +
+        // Subtract icon padding and box spacing from the available width
+        availWidth -= iconChildren.length * (buttonWidth - iconWidth) +
                        (iconChildren.length - 1) * spacing;
 
-        let availSize = availHeight / iconChildren.length;
+        let availSize = availWidth / iconChildren.length;
 
         let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
         let iconSizes = baseIconSizes.map(s => s * scaleFactor);
@@ -787,7 +784,7 @@ var Dash = GObject.registerClass({
         }
     }
 
-    handleDragOver(source, actor, x, y, _time) {
+    handleDragOver(source, actor, x, _y, _time) {
         let app = getAppFromSource(source);
 
         // Don't allow favoriting of transient apps
@@ -804,19 +801,19 @@ var Dash = GObject.registerClass({
 
         let children = this._box.get_children();
         let numChildren = children.length;
-        let boxHeight = this._box.height;
+        let boxWidth = this._box.width;
 
         // Keep the placeholder out of the index calculation; assuming that
         // the remove target has the same size as "normal" items, we don't
         // need to do the same adjustment there.
         if (this._dragPlaceholder) {
-            boxHeight -= this._dragPlaceholder.height;
+            boxWidth -= this._dragPlaceholder.width;
             numChildren--;
         }
 
         let pos;
         if (!this._emptyDropTarget)
-            pos = Math.floor(y * numChildren / boxHeight);
+            pos = Math.floor(x * numChildren / boxWidth);
         else
             pos = 0; // always insert at the top when dash is empty
 
diff --git a/js/ui/overviewControls.js b/js/ui/overviewControls.js
index 05a177df0e..11f50c27c6 100644
--- a/js/ui/overviewControls.js
+++ b/js/ui/overviewControls.js
@@ -339,32 +339,35 @@ class ThumbnailsSlider extends SlidingControl {
     }
 });
 
-var DashSlider = GObject.registerClass(
-class DashSlider extends SlidingControl {
+var DashFader = GObject.registerClass(
+class DashFader extends FaderControl {
     _init(dash) {
-        super._init({ slideDirection: SlideDirection.LEFT });
+        super._init({
+            y_expand: true,
+            x_expand: true,
+            y_align: Clutter.ActorAlign.END,
+        });
 
         this._dash = dash;
+        this.add_child(this._dash);
+    }
 
-        // SlideLayout reads the actor's expand flags to decide
-        // whether to allocate the natural size to its child, or the whole
-        // available allocation
-        this._dash.x_expand = true;
+    vfunc_allocate(box) {
+        this.set_allocation(box);
 
-        this.x_expand = true;
-        this.x_align = Clutter.ActorAlign.START;
-        this.y_expand = true;
+        box = this.get_theme_node().get_content_box(box);
 
-        this.add_actor(this._dash);
+        const availWidth = Math.round(box.get_width());
+        const availHeight = Math.round(box.get_height());
+        const [, natHeight] = this._dash.get_preferred_height(availWidth);
 
-        this._dash.connect('icon-size-changed', this._updateSlide.bind(this));
-    }
+        const actorBox = new Clutter.ActorBox();
+        actorBox.x1 = box.x1;
+        actorBox.x2 = actorBox.x1 + availWidth;
+        actorBox.y1 = box.y1;
+        actorBox.y2 = actorBox.y1 + (this._dash.y_expand ? availHeight : natHeight);
 
-    _getSlide() {
-        if (this._visible || this._inDrag)
-            return 1;
-        else
-            return 0;
+        this._dash.allocate(box);
     }
 
     _onWindowDragBegin() {
@@ -412,8 +415,8 @@ class ControlsManager extends St.Widget {
         });
 
         this.dash = new Dash.Dash();
-        this._dashSlider = new DashSlider(this.dash);
-        this._dashSpacer = new DashSpacer(this._dashSlider);
+        this._dashFader = new DashFader(this.dash);
+        this._dashSpacer = new DashSpacer(this._dashFader);
 
         let workspaceManager = global.workspace_manager;
         let activeWorkspaceIndex = workspaceManager.get_active_workspace_index();
@@ -441,15 +444,25 @@ class ControlsManager extends St.Widget {
         this.viewSelector.connect('page-changed', this._setVisibility.bind(this));
         this.viewSelector.connect('page-empty', this._onPageEmpty.bind(this));
 
-        this._group = new St.BoxLayout({ name: 'overview-group',
-                                         x_expand: true, y_expand: true });
+        this._group = new St.BoxLayout({
+            name: 'overview-group',
+            vertical: true,
+            x_expand: true,
+            y_expand: true,
+        });
         this.add_actor(this._group);
 
-        this.add_actor(this._dashSlider);
+        this.add_actor(this._dashFader);
+
+        const box = new St.BoxLayout({
+            x_expand: true,
+            y_expand: true,
+        });
+        box.add_child(this.viewSelector);
+        box.add_child(this._thumbnailsSlider);
 
+        this._group.add_child(box);
         this._group.add_actor(this._dashSpacer);
-        this._group.add_child(this.viewSelector);
-        this._group.add_actor(this._thumbnailsSlider);
 
         this.connect('destroy', this._onDestroy.bind(this));
     }
@@ -481,15 +494,8 @@ class ControlsManager extends St.Widget {
             return;
 
         let activePage = this.viewSelector.getActivePage();
-        let dashVisible = activePage == ViewSelector.ViewPage.WINDOWS ||
-                           activePage == ViewSelector.ViewPage.APPS;
         let thumbnailsVisible = activePage == ViewSelector.ViewPage.WINDOWS;
 
-        if (dashVisible)
-            this._dashSlider.slideIn();
-        else
-            this._dashSlider.slideOut();
-
         if (thumbnailsVisible)
             this._thumbnailsSlider.slideIn();
         else
@@ -497,7 +503,6 @@ class ControlsManager extends St.Widget {
     }
 
     _onPageEmpty() {
-        this._dashSlider.pageEmpty();
         this._thumbnailsSlider.pageEmpty();
     }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]