[gnome-shell/T29763: 26/249] endlessButton: Add the Endless button to the bottom panel



commit 6c078a478d759920c98fc808acaa8dc20452d770
Author: Mario Sanchez Prada <mario endlessm com>
Date:   Thu Sep 14 15:26:44 2017 +0100

    endlessButton: Add the Endless button to the bottom panel
    
    It acts as the Super key, toggling between the apps view
    and the last opened window if there is at least one running
    application, otherwise it shows a "No apps are open" message.
    
     * 2020-03-13: Code style cleanups
    
    https://phabricator.endlessm.com/T17227
    https://phabricator.endlessm.com/T17435
    https://phabricator.endlessm.com/T17506
    https://phabricator.endlessm.com/T17520
    https://phabricator.endlessm.com/T18327
    https://phabricator.endlessm.com/T18565
    https://phabricator.endlessm.com/T20325

 data/gnome-shell-theme.gresource.xml      |   1 +
 data/theme/endless-button-symbolic.svg    |  96 ++++++++++++++++++++++
 data/theme/gnome-shell-sass/_endless.scss |  32 ++++++++
 js/js-resources.gresource.xml             |   1 +
 js/ui/endlessButton.js                    | 129 ++++++++++++++++++++++++++++++
 js/ui/panel.js                            |   1 +
 js/ui/sessionMode.js                      |   2 +-
 po/POTFILES.in                            |   1 +
 8 files changed, 262 insertions(+), 1 deletion(-)
---
diff --git a/data/gnome-shell-theme.gresource.xml b/data/gnome-shell-theme.gresource.xml
index 4c6eed7965..e4ab761cd3 100644
--- a/data/gnome-shell-theme.gresource.xml
+++ b/data/gnome-shell-theme.gresource.xml
@@ -34,6 +34,7 @@
 
     <!-- Endless-specific resources beyond this point -->
 
+    <file>endless-button-symbolic.svg</file>
     <file>mini-icon-active-indicator.png</file>
   </gresource>
 </gresources>
diff --git a/data/theme/endless-button-symbolic.svg b/data/theme/endless-button-symbolic.svg
new file mode 100644
index 0000000000..38616ec204
--- /dev/null
+++ b/data/theme/endless-button-symbolic.svg
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   viewBox="0 0 39.999999 40"
+   height="40"
+   width="40"
+   xml:space="preserve"
+   id="svg2"
+   version="1.1"
+   sodipodi:docname="endless-button-symbolic.svg"
+   inkscape:version="0.92.1 r"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1136"
+     id="namedview26"
+     showgrid="false"
+     inkscape:zoom="22.625"
+     inkscape:cx="20"
+     inkscape:cy="20"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg2"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" /><metadata
+     id="metadata8"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; 
/><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+     id="defs6"><clipPath
+       id="clipPath22"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path20"
+         d="M 0,0 H 842 V 370 H 0 Z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath34"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path32"
+         d="M 0,0 H 842 V 370 H 0 Z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath46"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path44"
+         d="M 0,0 H 842 V 370 H 0 Z"
+         inkscape:connector-curvature="0" /></clipPath></defs><g
+     transform="matrix(0.03851744,0,0,-0.03851744,3.7866422,27.120379)"
+     id="g10"
+     style=""><g
+       id="g12"
+       style=""><g
+         transform="translate(0,-0.279053)"
+         id="g14"
+         style=""><g
+           id="g16"
+           style=""><g
+             clip-path="url(#clipPath22)"
+             id="g18"
+             style=""><g
+               id="g24"
+               style=""><g
+                 id="g26"
+                 style=""><g
+                   id="g28"
+                   style=""><g
+                     clip-path="url(#clipPath34)"
+                     id="g30"
+                     style=""><g
+                       id="g36"
+                       style=""><g
+                         id="g38"
+                         style=""><g
+                           id="g40"
+                           style=""><g
+                             clip-path="url(#clipPath46)"
+                             id="g42"
+                             style=""><g
+                               id="g48"
+                               style=""><path
+                                 id="path50"
+                                 style="fill-opacity:1;fill-rule:nonzero;"
+                                 d="m 737.449,259.547 c -68.324,0 -162.289,-38.004 -249.566,-82.977 l 
-84.555,42.922 c 69.09,38.477 129.34,77.633 162.465,99.922 l 15.125,10.176 c 6.363,4.472 7.52,13.836 
2.586,20.805 l -8.586,12.156 c -4.93,6.98 -13.465,9.511 -18.984,5.629 l -3.34,-2.168 C 526.133,347.973 
463.277,306.184 389.91,264.746 377.23,257.582 364.82,250.758 352.695,244.27 238.098,292.867 154.598,317.5 
104.441,317.5 55.816,317.5 0,305.93 0,215.852 0,167.578 18.121,110.035 104.441,110.035 c 68.317,0 162.27,38 
249.551,82.977 L 438.547,150.09 C 373.215,113.695 315.859,76.75 281.809,54 h -0.016 C 263.352,41.664 
262.109,40.812 262.109,40.812 255.137,35.895 253.438,26.164 258.363,19.18 l 8.594,-12.157 c 4.926,-6.964 
14.395,-8.851 21.051,-4.164 0,0 0.058,0.032 12.25,8.161 L 300.285,11 c 30.629,20.582 87.078,57.34 
151.676,93.836 12.699,7.172 25.086,13.996 37.219,20.476 114.597,-48.585 198.093,-73.218 248.269,-73.218 
48.617,0 104.422,11.551 104.422,101.636 0,48.282 -18.121,105.817 -104
 .422,105.817 M 104.441,155.984 c -48.925,0 -58.496,21.95 -58.496,59.868 0,47.281 15.332,55.691 58.496,55.691 
38.411,0 105.094,-18.813 194.399,-54.711 C 215.957,176.82 149.695,155.984 104.441,155.984 M 737.449,98.031 c 
-38.41,0 -105.113,18.828 -194.398,54.731 82.863,39.996 149.133,60.847 194.398,60.847 48.906,0 58.469,-21.961 
58.469,-59.879 0,-47.277 -15.305,-55.699 -58.469,-55.699"
+                                 inkscape:connector-curvature="0" 
/></g></g></g></g></g></g></g></g></g></g></g></g></g></g></svg>
\ No newline at end of file
diff --git a/data/theme/gnome-shell-sass/_endless.scss b/data/theme/gnome-shell-sass/_endless.scss
index 61f273b10c..d2c0f48b78 100644
--- a/data/theme/gnome-shell-sass/_endless.scss
+++ b/data/theme/gnome-shell-sass/_endless.scss
@@ -214,3 +214,35 @@
         }
     }
 }
+
+// Endless Button
+
+%endless-button-hover {
+    color: #f15a22;
+    background-gradient-start: rgba(255, 255, 255, 0.12);
+    transition: 300ms;
+}
+
+%endless-button-clicked {
+    @extend %endless-button-hover;
+    color: white;
+    box-shadow: none;
+}
+
+.endless-button {
+    color: rgba(255, 255, 255, 0.8);
+    background-gradient-start: rgba(255, 255, 255, 0.08);
+    background-gradient-end: transparent;
+    background-gradient-direction: radial;
+    background-gradient-position: 0 20px;
+    background-gradient-radius: 65px;
+    background-gradient-stop: 63px;
+    height: 40px;
+    width: 65px;
+    padding: 0px;
+
+    .single-icon-button { icon-size: 34px; }
+
+    &:hover { @extend %endless-button-hover; }
+    &:clicked { @extend %endless-button-clicked; }
+}
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index f0ed005e7c..4efd4b95e8 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -143,6 +143,7 @@
 
     <file>ui/appActivation.js</file>
     <file>ui/appIconBar.js</file>
+    <file>ui/endlessButton.js</file>
     <file>ui/forceAppExitDialog.js</file>
     <file>ui/workspaceMonitor.js</file>
   </gresource>
diff --git a/js/ui/endlessButton.js b/js/ui/endlessButton.js
new file mode 100644
index 0000000000..cb6f9a2111
--- /dev/null
+++ b/js/ui/endlessButton.js
@@ -0,0 +1,129 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+/* exported EndlessButton */
+
+const { Clutter, Gio, GObject, St } = imports.gi;
+
+const Main = imports.ui.main;
+const PanelMenu = imports.ui.panelMenu;
+const ViewSelector = imports.ui.viewSelector;
+
+var EndlessButton = GObject.registerClass(
+class EndlessButton extends PanelMenu.SingleIconButton {
+    _init() {
+        super._init(_('Endless Button'));
+        this.add_style_class_name('endless-button');
+        this.connect('style-changed', () => {
+            this.width = this.get_theme_node().get_length('width');
+            this.height = this.get_theme_node().get_length('height');
+        });
+        this.connect('notify::hover', this._onHoverChanged.bind(this));
+        this.connect('button-press-event', this._onButtonPressEvent.bind(this));
+        this.connect('button-release-event', this._onButtonReleaseEvent.bind(this));
+
+        let iconFile = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/endless-button-symbolic.svg');
+        this.setIcon(new Gio.FileIcon({ file: iconFile }));
+
+        this._setupTooltipText();
+    }
+
+    _setupTooltipText() {
+        this._label = new St.Label({ style_class: 'app-icon-hover-label' });
+
+        this._labelOffsetX = 0;
+        this._labelOffsetY = 0;
+        this._label.connect('style-changed', () => {
+            this._labelOffsetX = this._label.get_theme_node().get_length('-label-offset-x');
+            this._labelOffsetY = this._label.get_theme_node().get_length('-label-offset-y');
+        });
+
+        let pageChangedId = Main.overview.connect('page-changed', this._onOverviewPageChanged.bind(this));
+        let showingId = Main.overview.connect('showing', this._onOverviewShowing.bind(this));
+        let hidingId = Main.overview.connect('hiding', this._onOverviewHiding.bind(this));
+
+        this.connect('destroy', () => {
+            Main.overview.disconnect(pageChangedId);
+            Main.overview.disconnect(showingId);
+            Main.overview.disconnect(hidingId);
+        });
+
+        this._setHoverLabelText(true);
+    }
+
+    _updateHoverLabel(hiding) {
+        let viewSelector = Main.overview.viewSelector;
+        let showingDesktop = true;
+
+        if (!hiding &&
+            viewSelector &&
+            viewSelector.getActivePage() === ViewSelector.ViewPage.APPS)
+            showingDesktop = false;
+
+        this._setHoverLabelText(showingDesktop);
+    }
+
+    _setHoverLabelText(desktop) {
+        if (desktop)
+            this._label.text = _('Show Desktop');
+        else
+            this._label.text = _('Show Apps');
+    }
+
+    _onOverviewPageChanged() {
+        this._updateHoverLabel(false);
+    }
+
+    _onOverviewShowing() {
+        this._updateHoverLabel(false);
+    }
+
+    _onOverviewHiding() {
+        this._updateHoverLabel(true);
+    }
+
+    // overrides default implementation from PanelMenu.Button
+    vfunc_event(event) {
+        if (this.menu &&
+            (event.type() === Clutter.EventType.TOUCH_BEGIN ||
+             event.type() === Clutter.EventType.BUTTON_PRESS))
+            Main.overview.toggleApps();
+
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _onHoverChanged() {
+        if (!this._label)
+            return;
+
+        if (this.hover) {
+            if (this._label.get_parent())
+                return;
+
+            Main.uiGroup.add_actor(this._label);
+            Main.uiGroup.set_child_above_sibling(this._label, null);
+
+            // Update the tooltip position
+            let monitor = Main.layoutManager.findMonitorForActor(this._label);
+            let iconMidpoint = this.get_transformed_position()[0] + this.width / 2;
+            this._label.translation_x = Math.floor(iconMidpoint - this._label.width / 2) + 
this._labelOffsetX;
+            this._label.translation_y = Math.floor(this.get_transformed_position()[1] - this._labelOffsetY);
+
+            // Clip left edge to be the left edge of the screen
+            this._label.translation_x = Math.max(this._label.translation_x, monitor.x + this._labelOffsetX);
+        } else if (this._label.get_parent()) {
+            // Remove the tooltip from uiGroup
+            Main.uiGroup.remove_actor(this._label);
+        }
+    }
+
+    _onButtonPressEvent() {
+        // This is the CSS active state
+        this.add_style_pseudo_class('clicked');
+        return Clutter.EVENT_PROPAGATE;
+    }
+
+    _onButtonReleaseEvent() {
+        this.remove_style_pseudo_class('clicked');
+        return Clutter.EVENT_PROPAGATE;
+    }
+});
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 1520596d2b..a390ed211b 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -815,6 +815,7 @@ class PopoverMenu extends PanelMenu.SingleIconButton {
 });
 
 const PANEL_ITEM_IMPLEMENTATIONS = {
+    'endlessButton': imports.ui.endlessButton.EndlessButton,
     'activities': ActivitiesButton,
     'aggregateMenu': AggregateMenu,
     'appIcons': imports.ui.appIconBar.AppIconBar,
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index faf2284bb5..5cc06af057 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -87,7 +87,7 @@ const _modes = {
                'keyring', 'autorunManager', 'automountManager'],
 
         panel: {
-            left: ['appIcons'],
+            left: ['endlessButton', 'appIcons'],
             center: [],
             right: ['dwellClick', 'a11y', 'keyboard', 'aggregateMenu', 'dateMenu'],
         },
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 4f073d21cc..35ccbb1a15 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -98,4 +98,5 @@ subprojects/extensions-tool/src/main.c
 subprojects/gvc/gvc-mixer-control.c
 # Endless-specific files beyond this point
 js/ui/appIconBar.js
+js/ui/endlessButton.js
 js/ui/forceAppExitDialog.js


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