[gnome-shell] shellDBus: Add methods to handle key grabs



commit 81e01b6f88ce55bee8d55e83adaa5522d7c08c87
Author: Florian Müllner <fmuellner gnome org>
Date:   Sat Aug 11 23:11:37 2012 +0200

    shellDBus: Add methods to handle key grabs
    
    Expose Mutter's external grab API on the bus, so gnome-settings-daemon
    can refer keygrabbing to the shell.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=643111

 js/ui/shellDBus.js |  110 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 1 deletions(-)
---
diff --git a/js/ui/shellDBus.js b/js/ui/shellDBus.js
index 6aaa2f0..6657b35 100644
--- a/js/ui/shellDBus.js
+++ b/js/ui/shellDBus.js
@@ -1,14 +1,16 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
-const Lang = imports.lang;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const Lang = imports.lang;
+const Meta = imports.gi.Meta;
 const Shell = imports.gi.Shell;
 
 const Config = imports.misc.config;
 const ExtensionSystem = imports.ui.extensionSystem;
 const ExtensionDownloader = imports.ui.extensionDownloader;
 const ExtensionUtils = imports.misc.extensionUtils;
+const Hash = imports.misc.hash;
 const Main = imports.ui.main;
 const Screenshot = imports.ui.screenshot;
 
@@ -18,6 +20,23 @@ const GnomeShellIface = <interface name="org.gnome.Shell">
     <arg type="b" direction="out" name="success" />
     <arg type="s" direction="out" name="result" />
 </method>
+<method name="GrabAccelerator">
+    <arg type="s" direction="in" name="accelerator"/>
+    <arg type="u" direction="in" name="flags"/>
+    <arg type="u" direction="out" name="action"/>
+</method>
+<method name="GrabAccelerators">
+    <arg type="a(su)" direction="in" name="accelerators"/>
+    <arg type="au" direction="out" name="actions"/>
+</method>
+<method name="UngrabAccelerator">
+    <arg type="u" direction="in" name="action"/>
+    <arg type="b" direction="out" name="success"/>
+</method>
+<signal name="AcceleratorActivated">
+    <arg name="action" type="u" />
+    <arg name="deviceid" type="u" />
+</signal>
 <property name="Mode" type="s" access="read" />
 <property name="OverviewActive" type="b" access="readwrite" />
 <property name="ShellVersion" type="s" access="read" />
@@ -49,6 +68,14 @@ const GnomeShell = new Lang.Class({
 
         this._extensionsService = new GnomeShellExtensions();
         this._screenshotService = new Screenshot.ScreenshotService();
+
+        this._grabbedAccelerators = new Hash.Map();
+        this._grabbers = new Hash.Map();
+
+        global.display.connect('accelerator-activated', Lang.bind(this,
+            function(display, action, deviceid) {
+                this._emitAcceleratorActivated(action, deviceid);
+            }));
     },
 
     /**
@@ -84,6 +111,87 @@ const GnomeShell = new Lang.Class({
         return [success, returnValue];
     },
 
+    GrabAcceleratorAsync: function(params, invocation) {
+        let [accel, flags] = params;
+        let sender = invocation.get_sender();
+        let bindingAction = this._grabAcceleratorForSender(accel, flags, sender);
+        return invocation.return_value(GLib.Variant.new('(u)', [bindingAction]));
+    },
+
+    GrabAcceleratorsAsync: function(params, invocation) {
+        let [accels] = params;
+        let sender = invocation.get_sender();
+        let bindingActions = [];
+        for (let i = 0; i < accels.length; i++) {
+            let [accel, flags] = accels[i];
+            bindingActions.push(this._grabAcceleratorForSender(accel, flags, sender));
+        }
+        return invocation.return_value(GLib.Variant.new('(au)', [bindingActions]));
+    },
+
+    UngrabAcceleratorAsync: function(params, invocation) {
+        let [action] = params;
+        let grabbedBy = this._grabbedAccelerators.get(action);
+        if (invocation.get_sender() != grabbedBy)
+            return invocation.return_value(GLib.Variant.new('(b)', [false]));
+
+        let ungrabSucceeded = global.display.ungrab_accelerator(action);
+        if (ungrabSucceeded)
+            this._grabbedAccelerators.delete(action);
+        return invocation.return_value(GLib.Variant.new('(b)', [ungrabSucceeded]));
+    },
+
+    _emitAcceleratorActivated: function(action, deviceid) {
+        let destination = this._grabbedAccelerators.get(action);
+        if (!destination)
+            return;
+
+        let connection = this._dbusImpl.get_connection();
+        let info = this._dbusImpl.get_info();
+        connection.emit_signal(destination,
+                               this._dbusImpl.get_object_path(),
+                               info ? info.name : null,
+                               'AcceleratorActivated',
+                               GLib.Variant.new('(uu)', [action, deviceid]));
+    },
+
+    _grabAcceleratorForSender: function(accelerator, flags, sender) {
+        let bindingAction = global.display.grab_accelerator(accelerator);
+        if (bindingAction == Meta.KeyBindingAction.NONE)
+            return Meta.KeyBindingAction.NONE;
+
+        let bindingName = Meta.external_binding_name_for_action(bindingAction);
+        Main.wm.allowKeybinding(bindingName, flags);
+
+        this._grabbedAccelerators.set(bindingAction, sender);
+
+        if (!this._grabbers.has(sender)) {
+            let id = Gio.bus_watch_name(Gio.BusType.SESSION, sender, 0, null,
+                                        Lang.bind(this, this._onGrabberBusNameVanished));
+            this._grabbers.set(sender, id);
+        }
+
+        return bindingAction;
+    },
+
+    _ungrabAccelerator: function(action) {
+        let ungrabSucceeded = global.display.ungrab_accelerator(action);
+        if (ungrabSucceeded)
+            this._grabbedAccelerators.delete(action);
+    },
+
+    _onGrabberBusNameVanished: function(connection, name) {
+        let grabs = this._grabbedAccelerators.items();
+        for (let i = 0; i < grabs.length; i++) {
+            let [action, sender] = grabs[i];
+            if (sender == name)
+                this._ungrabAccelerator(action);
+        }
+        Gio.bus_unwatch_name(this._grabbers.get(name));
+        this._grabbers.delete(name);
+    },
+
+
     Mode: global.session_mode,
 
     get OverviewActive() {


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