[gnome-shell] Add an OSD monitor labeler exposed on DBus



commit 19004688463efe2d2e6bd942f60ce7307edf5168
Author: Rui Matos <tiagomatos gmail com>
Date:   Mon Jan 26 15:52:10 2015 +0100

    Add an OSD monitor labeler exposed on DBus
    
    This DBus API is intended to be used by gnome-control-center's
    displays panel to show monitor labels.
    
    Each output (i.e. hardware monitor) identified by its
    org.gnome.Mutter.DisplayConfig API ID has at most one label. On
    mirrored setups, all the labels for outputs corresponding to the same
    logical monitor (i.e. showing the same contents in the same mode) are
    shown together.
    
    At most, only one DBus client at a time is allowed to show labels.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=743744

 data/theme/gnome-shell.css    |    7 ++
 js/js-resources.gresource.xml |    1 +
 js/ui/main.js                 |    3 +
 js/ui/osdMonitorLabeler.js    |  141 +++++++++++++++++++++++++++++++++++++++++
 js/ui/shellDBus.js            |   15 +++++
 5 files changed, 167 insertions(+), 0 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 7beede3..dc9a006 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -1812,6 +1812,9 @@ StScrollBar StButton#vhandle:active {
     text-align: center;
     font-weight: bold;
     spacing: 1em;
+    margin: 32px;
+    min-width: 64px;
+    min-height: 64px;
 }
 
 .osd-window .level {
@@ -1820,6 +1823,10 @@ StScrollBar StButton#vhandle:active {
     background-color: rgba(190,190,190,0.2);
 }
 
+.osd-monitor-label {
+    font-size: 3em;
+}
+
 /* App Switcher */
 .switcher-popup {
     padding: 8px;
diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml
index 02d2dd0..439c0aa 100644
--- a/js/js-resources.gresource.xml
+++ b/js/js-resources.gresource.xml
@@ -64,6 +64,7 @@
     <file>ui/modalDialog.js</file>
     <file>ui/notificationDaemon.js</file>
     <file>ui/osdWindow.js</file>
+    <file>ui/osdMonitorLabeler.js</file>
     <file>ui/overview.js</file>
     <file>ui/overviewControls.js</file>
     <file>ui/panel.js</file>
diff --git a/js/ui/main.js b/js/ui/main.js
index 32c8644..aecf5fb 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -21,6 +21,7 @@ const Keyboard = imports.ui.keyboard;
 const MessageTray = imports.ui.messageTray;
 const ModalDialog = imports.ui.modalDialog;
 const OsdWindow = imports.ui.osdWindow;
+const OsdMonitorLabeler = imports.ui.osdMonitorLabeler;
 const Overview = imports.ui.overview;
 const Panel = imports.ui.panel;
 const Params = imports.misc.params;
@@ -57,6 +58,7 @@ let notificationDaemon = null;
 let windowAttentionHandler = null;
 let ctrlAltTabManager = null;
 let osdWindowManager = null;
+let osdMonitorLabeler = null;
 let sessionMode = null;
 let shellDBusService = null;
 let shellMountOpDBusService = null;
@@ -150,6 +152,7 @@ function _initializeUI() {
     xdndHandler = new XdndHandler.XdndHandler();
     ctrlAltTabManager = new CtrlAltTab.CtrlAltTabManager();
     osdWindowManager = new OsdWindow.OsdWindowManager();
+    osdMonitorLabeler = new OsdMonitorLabeler.OsdMonitorLabeler();
     overview = new Overview.Overview();
     wm = new WindowManager.WindowManager();
     magnifier = new Magnifier.Magnifier();
diff --git a/js/ui/osdMonitorLabeler.js b/js/ui/osdMonitorLabeler.js
new file mode 100644
index 0000000..9d519f5
--- /dev/null
+++ b/js/ui/osdMonitorLabeler.js
@@ -0,0 +1,141 @@
+// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
+
+const Clutter = imports.gi.Clutter;
+const Gio = imports.gi.Gio;
+const St = imports.gi.St;
+
+const Lang = imports.lang;
+const Main = imports.ui.main;
+const Tweener = imports.ui.tweener;
+const Meta = imports.gi.Meta;
+
+const FADE_TIME = 0.1;
+
+const OsdMonitorLabel = new Lang.Class({
+    Name: 'OsdMonitorLabel',
+
+    _init: function(monitor, label) {
+        this._actor = new St.Widget({ opacity: 0,
+                                      x_expand: true,
+                                      y_expand: true });
+
+        this._monitor = monitor;
+
+        this._box = new St.BoxLayout({ style_class: 'osd-window',
+                                       vertical: true });
+        this._actor.add_actor(this._box);
+
+        this._label = new St.Label({ style_class: 'osd-monitor-label',
+                                     text: label });
+        this._box.add(this._label);
+
+        Main.uiGroup.add_child(this._actor);
+        Main.uiGroup.set_child_above_sibling(this._actor, null);
+        this._position();
+
+        Meta.disable_unredirect_for_screen(global.screen);
+        Tweener.addTween(this._actor,
+                         { opacity: 255,
+                           time: FADE_TIME,
+                           transition: 'easeOutQuad' });
+    },
+
+    _position: function() {
+        let workArea = Main.layoutManager.getWorkAreaForMonitor(this._monitor);
+
+        if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL)
+            this._box.x = workArea.x + (workArea.width - this._box.width);
+        else
+            this._box.x = workArea.x;
+
+        this._box.y = workArea.y;
+    },
+
+    destroy: function() {
+        Tweener.addTween(this._actor,
+                         { opacity: 0,
+                           time: FADE_TIME,
+                           transition: 'easeOutQuad',
+                           onComplete: Lang.bind(this, function() {
+                               this._actor.destroy();
+                               Meta.enable_unredirect_for_screen(global.screen);
+                           })
+                         });
+    }
+});
+
+const OsdMonitorLabeler = new Lang.Class({
+    Name: 'OsdMonitorLabeler',
+
+    _init: function() {
+        this._monitorManager = Meta.MonitorManager.get();
+        this._client = null;
+        this._clientWatchId = 0;
+        this._osdLabels = [];
+        this._monitorLabels = null;
+        Main.layoutManager.connect('monitors-changed',
+                                    Lang.bind(this, this._reset));
+        this._reset();
+    },
+
+    _reset: function() {
+        for (let i in this._osdLabels)
+            this._osdLabels[i].destroy();
+        this._osdLabels = [];
+        this._monitorLabels = new Map();
+        let monitors = Main.layoutManager.monitors;
+        for (let i in monitors)
+            this._monitorLabels.set(monitors[i].index, []);
+    },
+
+    _trackClient: function(client) {
+        if (this._client)
+            return (this._client == client);
+
+        this._client = client;
+        this._clientWatchId = Gio.bus_watch_name(Gio.BusType.SESSION, client, 0, null,
+                                                 Lang.bind(this, function(c, name) {
+                                                     this.hide(name);
+                                                 }));
+        return true;
+    },
+
+    _untrackClient: function(client) {
+        if (!this._client || this._client != client)
+            return false;
+
+        Gio.bus_unwatch_name(this._clientWatchId);
+        this._clientWatchId = 0;
+        this._client = null;
+        return true;
+    },
+
+    show: function(client, params) {
+        if (!this._trackClient(client))
+            return;
+
+        this._reset();
+
+        for (let id in params) {
+            let monitor = this._monitorManager.get_monitor_for_output(id);
+            if (monitor == -1)
+                continue;
+            this._monitorLabels.get(monitor).push(params[id].deep_unpack());
+        }
+
+        // In mirrored display setups, more than one physical outputs
+        // might be showing the same logical monitor. In that case, we
+        // join each output's labels on the same OSD widget.
+        for (let [monitor, labels] of this._monitorLabels.entries()) {
+            labels.sort();
+            this._osdLabels.push(new OsdMonitorLabel(monitor, labels.join(' ')));
+        }
+    },
+
+    hide: function(client) {
+        if (!this._untrackClient(client))
+            return;
+
+        this._reset();
+    }
+});
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 7e45d84..14dba72 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -25,6 +25,10 @@ const GnomeShellIface = '<node> \
 <method name="ShowOSD"> \
     <arg type="a{sv}" direction="in" name="params"/> \
 </method> \
+<method name="ShowMonitorLabels"> \
+    <arg type="a{uv}" direction="in" name="params" /> \
+</method> \
+<method name="HideMonitorLabels" /> \
 <method name="FocusApp"> \
     <arg type="s" direction="in" name="id"/> \
 </method> \
@@ -240,6 +244,17 @@ const GnomeShell = new Lang.Class({
         this._grabbers.delete(name);
     },
 
+    ShowMonitorLabelsAsync: function(params, invocation) {
+        let sender = invocation.get_sender();
+        let [dict] = params;
+        Main.osdMonitorLabeler.show(sender, dict);
+    },
+
+    HideMonitorLabelsAsync: function(params, invocation) {
+        let sender = invocation.get_sender();
+        Main.osdMonitorLabeler.hide(sender);
+    },
+
 
     Mode: global.session_mode,
 


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