edd942
From 2ebc78ce92ae615d36ae80420b737b6f1583c7c8 Mon Sep 17 00:00:00 2001
edd942
From: rpm-build <rpm-build>
edd942
Date: Fri, 9 Aug 2019 14:46:44 +0200
edd942
Subject: [PATCH] Add extra-osk-keys extension
edd942
edd942
Originally improveosk by Simon Schumann,
edd942
https://extensions.gnome.org/extension/1631/improve-onscreen-keyboard/
edd942
---
edd942
 extensions/extra-osk-keys/extension.js     | 230 +++++++++++++++++++++
edd942
 extensions/extra-osk-keys/meson.build      |   5 +
edd942
 extensions/extra-osk-keys/metadata.json.in |  10 +
edd942
 extensions/extra-osk-keys/stylesheet.css   |   6 +
edd942
 meson.build                                |   1 +
edd942
 5 files changed, 252 insertions(+)
edd942
 create mode 100644 extensions/extra-osk-keys/extension.js
edd942
 create mode 100644 extensions/extra-osk-keys/meson.build
edd942
 create mode 100644 extensions/extra-osk-keys/metadata.json.in
edd942
 create mode 100644 extensions/extra-osk-keys/stylesheet.css
edd942
edd942
diff --git a/extensions/extra-osk-keys/extension.js b/extensions/extra-osk-keys/extension.js
edd942
new file mode 100644
edd942
index 0000000..23221d7
edd942
--- /dev/null
edd942
+++ b/extensions/extra-osk-keys/extension.js
edd942
@@ -0,0 +1,230 @@
edd942
+
edd942
+const St = imports.gi.St;
edd942
+const Main = imports.ui.main;
edd942
+const Keyboard = imports.ui.keyboard;
edd942
+const EdgeDragAction = imports.ui.edgeDragAction;
edd942
+const Shell = imports.gi.Shell;
edd942
+const Lang = imports.lang;
edd942
+const Clutter = imports.gi.Clutter;
edd942
+const Workspace = imports.ui.workspace
edd942
+const Tweener = imports.ui.tweener;
edd942
+const Overview = imports.ui.overview;
edd942
+const Layout = imports.ui.layout;
edd942
+
edd942
+var defaultKeyboardDelay;
edd942
+var Backup_DefaultKeysForRow;
edd942
+var Backup_contructor;
edd942
+var Backup_keyvalPress;
edd942
+var Backup_keyvalRelease;
edd942
+
edd942
+
edd942
+function init() {
edd942
+    defaultKeyboardDelay = Layout.KEYBOARD_ANIMATION_TIME;
edd942
+    Backup_DefaultKeysForRow = Keyboard.Keyboard.prototype['_getDefaultKeysForRow'];
edd942
+    Backup_contructor = Keyboard.KeyboardController.prototype['constructor'];
edd942
+    Backup_keyvalPress = Keyboard.KeyboardController.prototype['keyvalPress'];
edd942
+    Backup_keyvalRelease = Keyboard.KeyboardController.prototype['keyvalRelease'];
edd942
+}
edd942
+
edd942
+function enable() {
edd942
+    Main.layoutManager.removeChrome(Main.layoutManager.keyboardBox);
edd942
+
edd942
+    var KeyboardIsSetup = true;
edd942
+    try {
edd942
+      Main.keyboard._destroyKeyboard();
edd942
+    } catch (e) {
edd942
+        if(e instanceof TypeError) {
edd942
+            // In case the keyboard is currently disabled in accessability settings, attempting to _destroyKeyboard() yields a TypeError ("TypeError: this.actor is null")
edd942
+            // This doesn't affect functionality, so proceed as usual. The only difference is that we do not automatically _setupKeyboard at the end of this enable() (let the user enable the keyboard in accessability settings)
edd942
+            KeyboardIsSetup = false;
edd942
+        } else {
edd942
+            // Something different happened
edd942
+            throw e;
edd942
+        }
edd942
+    }
edd942
+    
edd942
+
edd942
+    Keyboard.Keyboard.prototype['_getDefaultKeysForRow'] = function(row, numRows, level) {
edd942
+        
edd942
+        let defaultKeysPreMod = [
edd942
+            [ [{ label: 'Esc', width: 1, keyval: Clutter.KEY_Escape }], [{ label: '↹', width: 1.5, keyval: Clutter.KEY_Tab }], [{ width: 1.5, level: 1, extraClassName: 'shift-key-lowercase' }], [{ label: 'Ctrl', width: 1, keyval: Clutter.KEY_Control_L, extraClassName: 'control-key' }, { label: '◆', width: 1, keyval: Clutter.KEY_Super_L, extraClassName: 'super-key' }, { label: 'Alt', width: 1, keyval: Clutter.KEY_Alt_L, extraClassName: 'alt-key' }] ],
edd942
+            [ [{ label: 'Esc', width: 1, keyval: Clutter.KEY_Escape }], [{ label: '↹', width: 1.5, keyval: Clutter.KEY_Tab }], [{ width: 1.5, level: 0, extraClassName: 'shift-key-uppercase' }], [{ label: 'Ctrl', width: 1, keyval: Clutter.KEY_Control_L, extraClassName: 'control-key' }, { label: '◆', width: 1, keyval: Clutter.KEY_Super_L, extraClassName: 'super-key' }, { label: 'Alt', width: 1, keyval: Clutter.KEY_Alt_L, extraClassName: 'alt-key' }] ],
edd942
+            [ [{ label: 'Esc', width: 1, keyval: Clutter.KEY_Escape }], [{ label: '↹', width: 1.5, keyval: Clutter.KEY_Tab }], [{ label: '=/
edd942
+            [ [{ label: 'Esc', width: 1, keyval: Clutter.KEY_Escape }], [{ label: '↹', width: 1.5, keyval: Clutter.KEY_Tab }], [{ label: '?123', width: 1.5, level: 2 }], [{ label: 'Ctrl', width: 1, keyval: Clutter.KEY_Control_L, extraClassName: 'control-key' }, { label: '◆', width: 1, keyval: Clutter.KEY_Super_L, extraClassName: 'super-key' }, { label: 'Alt', width: 1, keyval: Clutter.KEY_Alt_L, extraClassName: 'alt-key' }] ],
edd942
+        ];
edd942
+
edd942
+    
edd942
+        let defaultKeysPostMod = [
edd942
+            [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }, { label: '⌦', width: 1, keyval: Clutter.KEY_Delete }, { width: 1, action: 'hide', extraClassName: 'hide-key' }],
edd942
+              [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }, { width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }],
edd942
+              [{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }, { label: '?123', width: 1.5, level: 2 }],
edd942
+              [{ label: '←', width: 1, keyval: Clutter.KEY_Left }, { label: '↑', width: 1, keyval: Clutter.KEY_Up }, { label: '↓', width: 1, keyval: Clutter.KEY_Down }, { label: '→', width: 1, keyval: Clutter.KEY_Right }] ],
edd942
+            [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }, { label: '⌦', width: 1, keyval: Clutter.KEY_Delete }, { width: 1, action: 'hide', extraClassName: 'hide-key' }],
edd942
+              [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }, { width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }],
edd942
+              [{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }, { label: '?123', width: 1.5, level: 2 }],
edd942
+              [{ label: '←', width: 1, keyval: Clutter.KEY_Left }, { label: '↑', width: 1, keyval: Clutter.KEY_Up }, { label: '↓', width: 1, keyval: Clutter.KEY_Down }, { label: '→', width: 1, keyval: Clutter.KEY_Right }] ],
edd942
+            [ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }, { label: '⌦', width: 1, keyval: Clutter.KEY_Delete }, { width: 1, action: 'hide', extraClassName: 'hide-key' }],
edd942
+              [{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }, { width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }],
edd942
+              [{ label: '=/
edd942
+              [{ label: '←', width: 1, keyval: Clutter.KEY_Left }, { label: '↑', width: 1, keyval: Clutter.KEY_Up }, { label: '↓', width: 1, keyval: Clutter.KEY_Down }, { label: '→', width: 1, keyval: Clutter.KEY_Right }] ],
edd942
+            [ [{ label: 'F1', width: 1, keyval: Clutter.KEY_F1 }, { label: 'F2', width: 1, keyval: Clutter.KEY_F2 }, { label: 'F3', width: 1, keyval: Clutter.KEY_F3 }, { label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }, { label: '⌦', width: 1, keyval: Clutter.KEY_Delete }, { width: 1, action: 'hide', extraClassName: 'hide-key' }],
edd942
+              [{ label: 'F4', width: 1, keyval: Clutter.KEY_F4 }, { label: 'F5', width: 1, keyval: Clutter.KEY_F5 }, { label: 'F6', width: 1, keyval: Clutter.KEY_F6 }, { width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }, { width: 1.5, action: 'languageMenu', extraClassName: 'layout-key' }],
edd942
+              [{ label: 'F7', width: 1, keyval: Clutter.KEY_F7 }, { label: 'F8', width: 1, keyval: Clutter.KEY_F8 }, { label: 'F9', width: 1, keyval: Clutter.KEY_F9 }, { label: '?123', width: 3, level: 2, right: true }, { label: 'ABC', width: 1.5, level: 0 }],
edd942
+              [{ label: 'F10', width: 1, keyval: Clutter.KEY_F10 }, { label: 'F11', width: 1, keyval: Clutter.KEY_F11 }, { label: 'F12', width: 1, keyval: Clutter.KEY_F12 }, { label: '←', width: 1, keyval: Clutter.KEY_Left }, { label: '↑', width: 1, keyval: Clutter.KEY_Up }, { label: '↓', width: 1, keyval: Clutter.KEY_Down }, { label: '→', width: 1, keyval: Clutter.KEY_Right }] ],
edd942
+        ];
edd942
+
edd942
+    
edd942
+        let pre, post;
edd942
+
edd942
+        /* The first 2 rows in defaultKeysPre/Post belong together with
edd942
+         * the first 2 rows on each keymap. On keymaps that have more than
edd942
+         * 4 rows, the last 2 default key rows must be respectively
edd942
+         * assigned to the 2 last keymap ones.
edd942
+         */
edd942
+        if (row < 2) {
edd942
+            return [defaultKeysPreMod[level][row], defaultKeysPostMod[level][row]];
edd942
+        } else if (row >= numRows - 2) {
edd942
+            let defaultRow = row - (numRows - 2) + 2;
edd942
+            return [defaultKeysPreMod[level][defaultRow], defaultKeysPostMod[level][defaultRow]];
edd942
+        } else {
edd942
+            return [null, null];
edd942
+        }
edd942
+    }
edd942
+    
edd942
+    Keyboard.KeyboardController.prototype['constructor'] = function() {
edd942
+        let deviceManager = Clutter.DeviceManager.get_default();
edd942
+        this._virtualDevice = deviceManager.create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
edd942
+
edd942
+        this._inputSourceManager = InputSourceManager.getInputSourceManager();
edd942
+        this._sourceChangedId = this._inputSourceManager.connect('current-source-changed',
edd942
+                                                                 this._onSourceChanged.bind(this));
edd942
+        this._sourcesModifiedId = this._inputSourceManager.connect ('sources-changed',
edd942
+                                                                    this._onSourcesModified.bind(this));
edd942
+        this._currentSource = this._inputSourceManager.currentSource;
edd942
+        
edd942
+        this._controlActive = false;
edd942
+        this._superActive = false;
edd942
+        this._altActive = false;
edd942
+
edd942
+        Main.inputMethod.connect('notify::content-purpose',
edd942
+                                 this._onContentPurposeHintsChanged.bind(this));
edd942
+        Main.inputMethod.connect('notify::content-hints',
edd942
+                                 this._onContentPurposeHintsChanged.bind(this));
edd942
+        Main.inputMethod.connect('input-panel-state', (o, state) => {
edd942
+            this.emit('panel-state', state);
edd942
+        });
edd942
+    }
edd942
+
edd942
+    
edd942
+    Keyboard.KeyboardController.prototype['keyvalPress'] = function(keyval) {
edd942
+        if(keyval==Clutter.KEY_Control_L) {
edd942
+            this._controlActive = !this._controlActive; // This allows to revert an accidental tap on Ctrl by tapping on it again
edd942
+        }
edd942
+        if(keyval==Clutter.KEY_Super_L) {
edd942
+            this._superActive = !this._superActive;
edd942
+        }
edd942
+        if(keyval==Clutter.KEY_Alt_L) {
edd942
+            this._altActive = !this._altActive;
edd942
+        }
edd942
+        
edd942
+        if(this._controlActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Control_L, Clutter.KeyState.PRESSED);
edd942
+            Main.layoutManager.keyboardBox.add_style_class_name("control-key-latched");
edd942
+        } else {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Control_L, Clutter.KeyState.RELEASED);
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("control-key-latched");
edd942
+        }
edd942
+        if(this._superActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Super_L, Clutter.KeyState.PRESSED);
edd942
+            Main.layoutManager.keyboardBox.add_style_class_name("super-key-latched");
edd942
+        } else {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Super_L, Clutter.KeyState.RELEASED);
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("super-key-latched");
edd942
+        }
edd942
+        if(this._altActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Alt_L, Clutter.KeyState.PRESSED);
edd942
+            Main.layoutManager.keyboardBox.add_style_class_name("alt-key-latched");
edd942
+        } else {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Alt_L, Clutter.KeyState.RELEASED);
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("alt-key-latched");
edd942
+        }
edd942
+        this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                          keyval, Clutter.KeyState.PRESSED);
edd942
+    }
edd942
+
edd942
+    
edd942
+    Keyboard.KeyboardController.prototype['keyvalRelease'] = function(keyval) {
edd942
+        if(keyval==Clutter.KEY_Control_L || keyval==Clutter.KEY_Alt_L || keyval==Clutter.KEY_Super_L) {
edd942
+            return;
edd942
+        }
edd942
+        
edd942
+        this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                          keyval, Clutter.KeyState.RELEASED);
edd942
+
edd942
+        if(this._controlActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Control_L, Clutter.KeyState.RELEASED);
edd942
+            this._controlActive = false;
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("control-key-latched");
edd942
+        }
edd942
+        if(this._superActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Super_L, Clutter.KeyState.RELEASED);
edd942
+            this._superActive = false;
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("super-key-latched");
edd942
+        }
edd942
+        if(this._altActive)
edd942
+        {
edd942
+            this._virtualDevice.notify_keyval(Clutter.get_current_event_time(),
edd942
+                                              Clutter.KEY_Alt_L, Clutter.KeyState.RELEASED);
edd942
+            this._altActive = false;
edd942
+            Main.layoutManager.keyboardBox.remove_style_class_name("alt-key-latched");
edd942
+        }
edd942
+
edd942
+    }
edd942
+
edd942
+    Layout.KEYBOARD_ANIMATION_TIME = 0;
edd942
+    if(KeyboardIsSetup) {
edd942
+        Main.keyboard._setupKeyboard();
edd942
+    }
edd942
+    Main.layoutManager.addChrome(   Main.layoutManager.keyboardBox, { affectsStruts: true, trackFullscreen: false });
edd942
+}
edd942
+
edd942
+function disable() {
edd942
+    Main.layoutManager.removeChrome(Main.layoutManager.keyboardBox);
edd942
+    
edd942
+    var KeyboardIsSetup = true;
edd942
+    try {
edd942
+      Main.keyboard._destroyKeyboard();
edd942
+    } catch (e) {
edd942
+        if(e instanceof TypeError) {
edd942
+            // In case the keyboard is currently disabled in accessability settings, attempting to _destroyKeyboard() yields a TypeError ("TypeError: this.actor is null")
edd942
+            // This doesn't affect functionality, so proceed as usual. The only difference is that we do not automatically _setupKeyboard at the end of this enable() (let the user enable the keyboard in accessability settings)
edd942
+            KeyboardIsSetup = false;
edd942
+        } else {
edd942
+            // Something different happened
edd942
+            throw e;
edd942
+        }
edd942
+    }
edd942
+    
edd942
+    Keyboard.Keyboard.prototype['_getDefaultKeysForRow'] = Backup_DefaultKeysForRow;
edd942
+    Keyboard.KeyboardController.prototype['constructor'] = Backup_contructor;
edd942
+    Keyboard.KeyboardController.prototype['keyvalPress'] = Backup_keyvalPress;
edd942
+    Keyboard.KeyboardController.prototype['keyvalRelease'] = Backup_keyvalRelease;
edd942
+    Layout.KEYBOARD_ANIMATION_TIME = defaultKeyboardDelay;
edd942
+    if(KeyboardIsSetup) {
edd942
+        Main.keyboard._setupKeyboard();
edd942
+    }
edd942
+    Main.layoutManager.addChrome(   Main.layoutManager.keyboardBox);
edd942
+}
edd942
diff --git a/extensions/extra-osk-keys/meson.build b/extensions/extra-osk-keys/meson.build
edd942
new file mode 100644
edd942
index 0000000..48504f6
edd942
--- /dev/null
edd942
+++ b/extensions/extra-osk-keys/meson.build
edd942
@@ -0,0 +1,5 @@
edd942
+extension_data += configure_file(
edd942
+  input: metadata_name + '.in',
edd942
+  output: metadata_name,
edd942
+  configuration: metadata_conf
edd942
+)
edd942
diff --git a/extensions/extra-osk-keys/metadata.json.in b/extensions/extra-osk-keys/metadata.json.in
edd942
new file mode 100644
edd942
index 0000000..39dfdd3
edd942
--- /dev/null
edd942
+++ b/extensions/extra-osk-keys/metadata.json.in
edd942
@@ -0,0 +1,10 @@
edd942
+{
edd942
+"extension-id": "@extension_id@",
edd942
+"uuid": "@uuid@",
edd942
+"gettext-domain": "@gettext_domain@",
edd942
+"name": "Extra Onscreen Keyboard Keys",
edd942
+"description": "Adds extra keys to gnome-shell onscreen keyboard.",
edd942
+"original-authors": [ "simon.schumann@web.de" ],
edd942
+"shell-version": [ "@shell_current@" ],
edd942
+"url": "@url@"
edd942
+}
edd942
diff --git a/extensions/extra-osk-keys/stylesheet.css b/extensions/extra-osk-keys/stylesheet.css
edd942
new file mode 100644
edd942
index 0000000..010cfb3
edd942
--- /dev/null
edd942
+++ b/extensions/extra-osk-keys/stylesheet.css
edd942
@@ -0,0 +1,6 @@
edd942
+.control-key-latched .control-key,
edd942
+.super-key-latched .super-key,
edd942
+.alt-key-latched .alt-key {
edd942
+      background-color: #55a54c;
edd942
+}
edd942
+
edd942
diff --git a/meson.build b/meson.build
edd942
index df2be33..fa4aa9c 100644
edd942
--- a/meson.build
edd942
+++ b/meson.build
edd942
@@ -56,6 +56,7 @@ all_extensions += [
edd942
   'dash-to-dock',
edd942
   'disable-screenshield',
edd942
   'example',
edd942
+  'extra-osk-keys',
edd942
   'native-window-placement',
edd942
   'no-hot-corner',
edd942
   'panel-favorites',
edd942
-- 
edd942
2.23.0.rc1
edd942