[gnome-shell] quickSettings: Add menu support to items
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] quickSettings: Add menu support to items
- Date: Wed, 3 Aug 2022 12:43:41 +0000 (UTC)
commit e0c61f53f1dd91541d0e4e6271f9627dd13c088b
Author: Florian Müllner <fmuellner gnome org>
Date: Fri Jul 29 15:22:37 2022 +0200
quickSettings: Add menu support to items
Now that the QuickSettingsMenu supports child menus, it is time
to add menu support to quick toggles.
Do that by introducing a QuickSettingsItem parent class with a
construct-only :has-menu property, as that will allow including
menus in items that aren't following the standard icon+label
pattern of QuickToggle (yes, we'll have some of those).
A common parent class also allows us to control the type of
menu that is created. That's important, as we need another
custom menu type to
- constrain the menu's y position to place it underneath
the source actor
- use open/close animations taylored for this use case
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2393>
.../gnome-shell-sass/widgets/_quick-settings.scss | 9 ++
js/ui/quickSettings.js | 118 ++++++++++++++++++++-
2 files changed, 125 insertions(+), 2 deletions(-)
---
diff --git a/data/theme/gnome-shell-sass/widgets/_quick-settings.scss
b/data/theme/gnome-shell-sass/widgets/_quick-settings.scss
index 8dc5ff8508..05d8495144 100644
--- a/data/theme/gnome-shell-sass/widgets/_quick-settings.scss
+++ b/data/theme/gnome-shell-sass/widgets/_quick-settings.scss
@@ -20,3 +20,12 @@
.quick-toggle-label { font-weight: bold; }
.quick-toggle-icon { icon-size: $base_icon_size; }
}
+
+.quick-toggle-menu {
+ @include card();
+ padding: 1.5 * $base_padding;
+}
+
+.quick-toggle-menu-container {
+ padding: 2 * $base_padding $base_padding 0;
+ }
diff --git a/js/ui/quickSettings.js b/js/ui/quickSettings.js
index 0e1b83cef1..ae097ca646 100644
--- a/js/ui/quickSettings.js
+++ b/js/ui/quickSettings.js
@@ -4,8 +4,32 @@ const {Atk, Clutter, Gio, GLib, GObject, Graphene, Pango, St} = imports.gi;
const Main = imports.ui.main;
const PopupMenu = imports.ui.popupMenu;
-const {POPUP_ANIMATION_TIME} = imports.ui.boxpointer;
+const {PopupAnimation} = imports.ui.boxpointer;
+
const DIM_BRIGHTNESS = -0.4;
+const POPUP_ANIMATION_TIME = 400;
+
+var QuickSettingsItem = GObject.registerClass({
+ Properties: {
+ 'has-menu': GObject.ParamSpec.boolean(
+ 'has-menu', 'has-menu', 'has-menu',
+ GObject.ParamFlags.READWRITE |
+ GObject.ParamFlags.CONSTRUCT_ONLY,
+ false),
+ },
+}, class QuickSettingsItem extends St.Button {
+ _init(params) {
+ super._init(params);
+
+ if (this.hasMenu) {
+ this.menu = new QuickToggleMenu(this);
+ this.menu.actor.hide();
+
+ this._menuManager = new PopupMenu.PopupMenuManager(this);
+ this._menuManager.addMenu(this.menu);
+ }
+ }
+});
var QuickToggle = GObject.registerClass({
Properties: {
@@ -17,7 +41,7 @@ var QuickToggle = GObject.registerClass({
GObject.ParamFlags.READWRITE,
''),
},
-}, class QuickToggle extends St.Button {
+}, class QuickToggle extends QuickSettingsItem {
_init(params) {
super._init({
style_class: 'quick-toggle button',
@@ -70,6 +94,96 @@ var QuickToggle = GObject.registerClass({
}
});
+class QuickToggleMenu extends PopupMenu.PopupMenuBase {
+ constructor(sourceActor) {
+ super(sourceActor, 'quick-toggle-menu');
+
+ const constraints = new Clutter.BindConstraint({
+ coordinate: Clutter.BindCoordinate.Y,
+ source: sourceActor,
+ });
+ sourceActor.bind_property('height',
+ constraints, 'offset',
+ GObject.BindingFlags.DEFAULT);
+
+ this.actor = new St.Widget({
+ layout_manager: new Clutter.BinLayout(),
+ style_class: 'quick-toggle-menu-container',
+ reactive: true,
+ x_expand: true,
+ y_expand: false,
+ constraints,
+ });
+ this.actor._delegate = this;
+ this.actor.add_child(this.box);
+
+ global.focus_manager.add_group(this.actor);
+ }
+
+ open(animate) {
+ if (this.isOpen)
+ return;
+
+ this.actor.show();
+ this.isOpen = true;
+
+ this.actor.height = -1;
+ const [targetHeight] = this.actor.get_preferred_height(-1);
+
+ const duration = animate !== PopupAnimation.NONE
+ ? POPUP_ANIMATION_TIME / 2
+ : 0;
+
+ this.actor.height = 0;
+ this.box.opacity = 0;
+ this.actor.ease({
+ duration,
+ height: targetHeight,
+ onComplete: () => {
+ this.box.ease({
+ duration,
+ opacity: 255,
+ });
+ this.actor.height = -1;
+ },
+ });
+ this.emit('open-state-changed', true);
+ }
+
+ close(animate) {
+ if (!this.isOpen)
+ return;
+
+ const duration = animate !== PopupAnimation.NONE
+ ? POPUP_ANIMATION_TIME / 2
+ : 0;
+
+ this.box.ease({
+ duration,
+ opacity: 0,
+ onComplete: () => {
+ this.actor.ease({
+ duration,
+ height: 0,
+ onComplete: () => {
+ this.actor.hide();
+ this.emit('menu-closed');
+ },
+ });
+ },
+ });
+
+ this.isOpen = false;
+ this.emit('open-state-changed', false);
+ }
+
+ // expected on toplevel menus
+ _setOpenedSubMenu(submenu) {
+ this._openedSubMenu?.close(true);
+ this._openedSubMenu = submenu;
+ }
+}
+
const QuickSettingsLayoutMeta = GObject.registerClass({
Properties: {
'column-span': GObject.ParamSpec.int(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]