From cbba2678c4ee9f23f9e15aef59054a3e7f40dbb3 Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Wed, 12 Jan 2011 21:06:51 +0100 Subject: [PATCH] XRandRIndicator: new extension Replace the GTK+ based indicator from gnome-settings-daemon with a native one. Allows to rotate the laptop monitor and to fast open display preferences. Depends on bug 621017. --- .gitignore | 1 + configure.ac | 7 +- extensions/Makefile.am | 2 +- extensions/alternate-tab/stylesheet.css | 9 +- extensions/xrandr-indicator/Makefile.am | 3 + extensions/xrandr-indicator/extension.js | 135 +++++++++++++++++++++ extensions/xrandr-indicator/extension.js~ | 132 ++++++++++++++++++++ extensions/xrandr-indicator/metadata.json | 6 + extensions/xrandr-indicator/stylesheet.css | 3 + 9 files changed, 288 insertions(+), 10 deletions(-) create mode 100644 extensions/xrandr-indicator/Makefile.am create mode 100644 extensions/xrandr-indicator/extension.js create mode 100644 extensions/xrandr-indicator/extension.js~ create mode 100644 extensions/xrandr-indicator/metadata.json create mode 100644 extensions/xrandr-indicator/stylesheet.css diff --git a/.gitignore b/.gitignore index 523a48ed..58b7e1be 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ autom4te.cache/ m4/ po/POTFILES po/stamp-it +staging/ diff --git a/configure.ac b/configure.ac index 73f040a2..5a012ef5 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ PKG_PROG_PKG_CONFIG([0.22]) ADDITIONAL_PACKAGES= dnl keep this in sync with extensions/Makefile.am -ALL_EXTENSIONS="example alternate-tab" +ALL_EXTENSIONS="example alternate-tab xrandr-indicator" AC_ARG_ENABLE([extensions], [AS_HELP_STRING([--enable-extensions],[Space separated list of extensions to enable. Default is that all extensions are built.])], [], @@ -28,6 +28,10 @@ AC_ARG_ENABLE([extensions], ENABLED_EXTENSIONS= for e in $enable_extensions; do case $e in + xrandr-indicator) + ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e" + ADDITIONAL_PACKAGES="gnome-desktop-3.0 >= 2.91.6" + ;; alternate-tab|example) ENABLED_EXTENSIONS="$ENABLED_EXTENSIONS $e" ;; @@ -50,6 +54,7 @@ AC_CONFIG_FILES([ extensions/Makefile extensions/example/Makefile extensions/alternate-tab/Makefile + extensions/xrandr-indicator/Makefile po/Makefile.in ]) AC_OUTPUT diff --git a/extensions/Makefile.am b/extensions/Makefile.am index a0471ec1..b42f5d7d 100644 --- a/extensions/Makefile.am +++ b/extensions/Makefile.am @@ -1,3 +1,3 @@ -DIST_SUBDIRS = example +DIST_SUBDIRS = example alternate-tab xrandr-indicator SUBDIRS = $(ENABLED_EXTENSIONS) diff --git a/extensions/alternate-tab/stylesheet.css b/extensions/alternate-tab/stylesheet.css index a8dc980f..25134b65 100644 --- a/extensions/alternate-tab/stylesheet.css +++ b/extensions/alternate-tab/stylesheet.css @@ -1,8 +1 @@ -/* Example stylesheet */ -.helloworld-label { - font-size: 36px; - font-weight: bold; - color: #ffffff; - background-color: rgba(10,10,10,0.7); - border-radius: 5px; -} +/* This extensions requires no special styling */ diff --git a/extensions/xrandr-indicator/Makefile.am b/extensions/xrandr-indicator/Makefile.am new file mode 100644 index 00000000..56abe216 --- /dev/null +++ b/extensions/xrandr-indicator/Makefile.am @@ -0,0 +1,3 @@ +EXTENSION_ID = xrandr-indicator + +include ../../extension.mk diff --git a/extensions/xrandr-indicator/extension.js b/extensions/xrandr-indicator/extension.js new file mode 100644 index 00000000..6cc0bd2c --- /dev/null +++ b/extensions/xrandr-indicator/extension.js @@ -0,0 +1,135 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +const DBus = imports.dbus; +const Gdk = imports.gi.Gdk; +const GLib = imports.gi.GLib; +const GnomeDesktop = imports.gi.GnomeDesktop; +const Lang = imports.lang; +const Shell = imports.gi.Shell; +const St = imports.gi.St; + +const Main = imports.ui.main; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const Panel = imports.ui.panel; + +const Gettext = imports.gettext.domain('gnome-shell'); +const _ = Gettext.gettext; + +const possibleRotations = [ GnomeDesktop.RRRotation.ROTATION_0, + GnomeDesktop.RRRotation.ROTATION_90, + GnomeDesktop.RRRotation.ROTATION_180, + GnomeDesktop.RRRotation.ROTATION_270 + ]; + +let rotations = [ [ GnomeDesktop.RRRotation.ROTATION_0, _("Normal") ], + [ GnomeDesktop.RRRotation.ROTATION_90, _("Left") ], + [ GnomeDesktop.RRRotation.ROTATION_270, _("Right") ], + [ GnomeDesktop.RRRotation.ROTATION_180, _("Upside-down") ] + ]; + +const XRandr2Iface = { + name: 'org.gnome.SettingsDaemon.XRANDR_2', + methods: [ + { name: 'ApplyConfiguration', inSignature: 'xx', outSignature: '' }, + ] +}; +let XRandr2 = DBus.makeProxyClass(XRandr2Iface); + +function Indicator() { + this._init.apply(this, arguments); +} + +Indicator.prototype = { + __proto__: PanelMenu.SystemStatusButton.prototype, + + _init: function() { + PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-display'); + + this._proxy = new XRandr2(DBus.session, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/XRANDR'); + + try { + this._screen = new GnomeDesktop.RRScreen({ gdk_screen: Gdk.Screen.get_default() }); + this._screen.init(null); + } catch(e) { + // an error means there is no XRandR extension + this.actor.hide(); + return; + } + + this._createMenu(); + this._screen.connect('screen-changed', Lang.bind(this, this._randrEvent)); + }, + + _randrEvent: function() { + this.menu.removeAll(); + this._createMenu(); + }, + + _createMenu: function() { + let config = GnomeDesktop.RRConfig.new_current(this._screen); + let outputs = config.get_outputs(); + for (let i = 0; i < outputs.length; i++) { + if (outputs[i].get_connected()) + this._addOutputItem(config, outputs[i]); + } + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + this.menu.addAction(_("Configure display settings..."), function() { + GLib.spawn_command_line_async('gnome-control-center display'); + }); + }, + + _addOutputItem: function(config, output) { + let item = new PopupMenu.PopupMenuItem(output.get_display_name()); + item.label.add_style_class_name('display-subtitle'); + item.actor.reactive = false; + item.actor.can_focus = false; + this.menu.addMenuItem(item); + + let allowedRotations = this._getAllowedRotations(config, output); + for (let i = 0; i < rotations.length; i++) { + let [bitmask, name] = rotations[i]; + if (bitmask & allowedRotations) { + this.menu.addAction(name, Lang.bind(this, function(event) { + /* ensure config is saved so we get a backup if anything goes wrong */ + config.save(); + + output.set_rotation(bitmask); + try { + config.save(); + this._proxy.ApplyConfigurationRemote(global.stage_xwindow, event.get_time()); + } catch (e) { + logError ('Could not save monitor configuration: ' + e); + } + })); + } + } + }, + + _getAllowedRotations: function(config, output) { + let retval = 0; + + let current = output.get_rotation(); + + for (let i = 0; i < possibleRotations.length; i++) { + output.set_rotation(possibleRotations[i]); + if (config.applicable(this._screen)) { + retval |= possibleRotations[i]; + } + } + + output.set_rotation(current); + + if (retval.lenght == 0) { + // what, no rotation? + // what's current then? + retval = current; + } + return retval; + } +} + + +function main() { + Panel.STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['display'] = Indicator; +} diff --git a/extensions/xrandr-indicator/extension.js~ b/extensions/xrandr-indicator/extension.js~ new file mode 100644 index 00000000..c52ea153 --- /dev/null +++ b/extensions/xrandr-indicator/extension.js~ @@ -0,0 +1,132 @@ +/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */ + +const DBus = imports.dbus; +const Gdk = imports.gi.Gdk; +const GLib = imports.gi.GLib; +const GnomeDesktop = imports.gi.GnomeDesktop; +const Lang = imports.lang; +const Shell = imports.gi.Shell; +const St = imports.gi.St; + +const Main = imports.ui.main; +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const Panel = imports.ui.panel; + +const Gettext = imports.gettext.domain('gnome-shell'); +const _ = Gettext.gettext; + +const possibleRotations = [ GnomeDesktop.RRRotation.ROTATION_0, + GnomeDesktop.RRRotation.ROTATION_90, + GnomeDesktop.RRRotation.ROTATION_180, + GnomeDesktop.RRRotation.ROTATION_270 + ]; + +let rotations = [ [ GnomeDesktop.RRRotation.ROTATION_0, _("Normal") ], + [ GnomeDesktop.RRRotation.ROTATION_90, _("Left") ], + [ GnomeDesktop.RRRotation.ROTATION_270, _("Right") ], + [ GnomeDesktop.RRRotation.ROTATION_180, _("Upside-down") ] + ]; + +const XRandr2Iface = { + name: 'org.gnome.SettingsDaemon.XRANDR_2', + methods: [ + { name: 'ApplyConfiguration', inSignature: 'xx', outSignature: '' }, + ] +}; +let XRandr2 = DBus.makeProxyClass(XRandr2Iface); + +function Indicator() { + this._init.apply(this, arguments); +} + +Indicator.prototype = { + __proto__: PanelMenu.SystemStatusButton.prototype, + + _init: function() { + PanelMenu.SystemStatusButton.prototype._init.call(this, 'preferences-desktop-display'); + + this._proxy = new XRandr2(DBus.session, 'org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/XRANDR'); + + try { + this._screen = new GnomeDesktop.RRScreen({ gdk_screen: Gdk.Screen.get_default() }); + this._screen.init(null); + } catch(e) { + // an error means there is no XRandR extension + this.actor.hide(); + return; + } + + this._createMenu(); + this._screen.connect('screen-changed', Lang.bind(this, this._randrEvent)); + }, + + _randrEvent: function() { + this.menu.removeAll(); + this._createMenu(); + }, + + _createMenu: function() { + let config = GnomeDesktop.RRConfig.new_current(this._screen); + let outputs = config.get_outputs(); + for (let i = 0; i < outputs.length; i++) { + if (outputs[i].get_connected()) + this._addOutputItem(config, outputs[i]); + } + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + this.menu.addAction(_("Configure display settings..."), function() { + GLib.spawn_command_line_async('gnome-control-center display'); + }); + }, + + _addOutputItem: function(config, output) { + let item = new PopupMenu.PopupMenuItem(output.get_display_name()); + item.label.add_style_class_name('display-subtitle'); + item.actor.reactive = false; + item.actor.can_focus = false; + this.menu.addMenuItem(item); + + let allowedRotations = this._getAllowedRotations(config, output); + for (let i = 0; i < rotations.length; i++) { + let [bitmask, name] = rotations[i]; + if (bitmask & allowedRotations) { + this.menu.addAction(name, Lang.bind(this, function(event) { + /* ensure config is saved so we get a backup if anything goes wrong */ + config.save(); + + output.set_rotation(bitmask); + try { + config.save(); + this._proxy.ApplyConfigurationRemote(global.stage_xwindow, event.get_time()); + } catch (e) { + logError ('Could not save monitor configuration: ' + e); + } + })); + } + } + }, + + _getAllowedRotations: function(config, output) { + let retval = 0; + + let current = output.get_rotation(); + + for (let i = 0; i < possibleRotations.length; i++) { + output.set_rotation(possibleRotations[i]); + if (config.applicable(this._screen)) { + retval |= possibleRotations[i]; + } + } + + output.set_rotation(current); + + if (retval.lenght == 0) { + // what, no rotation? + // what's current then? + retval = current; + } + return retval; + } +} + +Panel.STANDARD_TRAY_ICON_SHELL_IMPLEMENTATION['display'] = Indicator; diff --git a/extensions/xrandr-indicator/metadata.json b/extensions/xrandr-indicator/metadata.json new file mode 100644 index 00000000..1cc3c558 --- /dev/null +++ b/extensions/xrandr-indicator/metadata.json @@ -0,0 +1,6 @@ +{ +"uuid": "xrandr-indicator@gnome-shell-extensions.gnome.org", +"name": "Monitor Status Indicator", +"description": "Add a systems status menu for rotating monitors (overrides what is currently provided by gnome-settings-daemon)" +"shell-version": [ "2.91.5" ] +} diff --git a/extensions/xrandr-indicator/stylesheet.css b/extensions/xrandr-indicator/stylesheet.css new file mode 100644 index 00000000..e263d705 --- /dev/null +++ b/extensions/xrandr-indicator/stylesheet.css @@ -0,0 +1,3 @@ +.display-subtitle { + font-weight: bold; +}