From 5f26317c44f516d6b3210e1e6a9472edd85db93c Mon Sep 17 00:00:00 2001 From: xSmurf Date: Tue, 26 Sep 2017 04:00:55 +0000 Subject: [PATCH] Control prompt via full keyboard navigation... --- gnome-shell/firewall@subgraph.com/dialog.js | 121 ++++++++++++++++-- .../firewall@subgraph.com/extension.js | 63 ++++++++- .../schemas/com.subgraph.firewall.gschema.xml | 50 +++++++- .../schemas/gschemas.compiled | Bin 304 -> 1012 bytes 4 files changed, 223 insertions(+), 11 deletions(-) diff --git a/gnome-shell/firewall@subgraph.com/dialog.js b/gnome-shell/firewall@subgraph.com/dialog.js index 8a6f84c..0c35343 100644 --- a/gnome-shell/firewall@subgraph.com/dialog.js +++ b/gnome-shell/firewall@subgraph.com/dialog.js @@ -164,14 +164,14 @@ const OptionList = new Lang.Class({ }, addTLSOption: function(tlsGuardEnabled) { - let tlsg = new OptionListItem("Drop connection if not TLS with valid certificate",0); - tlsg.setSelected(tlsGuardEnabled); - tlsg.connect('selected', Lang.bind(this, function() { - this._toggleTLSGuard(tlsg); + this._tlsg = new OptionListItem("Drop connection if not TLS with valid certificate",0); + this._tlsg.setSelected(tlsGuardEnabled); + this._tlsg.connect('selected', Lang.bind(this, function() { + this._toggleTLSGuard(this._tlsg); })); - let emptyRow = new OptionListItem("",0); + let emptyRow = new OptionListItem("-------------------------------------------------", 0); this.actor.add_child(emptyRow.actor); - this.actor.add_child(tlsg.actor); + this.actor.add_child(this._tlsg.actor); }, _toggleTLSGuard: function(item) { @@ -251,6 +251,44 @@ const OptionList = new Lang.Class({ log("SGFW: unexpected scope value "+ scope); return 1; } + }, + + scopeNext: function() { + this.buttonGroup.next(); + }, + + scopePrevious: function() { + this.buttonGroup.previous(); + }, + + ruleNext: function() { + let idx = this.selectedIdx() + , l = this.items.length; + idx++; + if (l == 0) { + return; + } + if (idx >= l) { + idx = 0; + } + this._optionSelected(this.items[idx]); + }, + + rulePrevious: function() { + let idx = this.selectedIdx() + , l = this.items.length; + idx--; + if (l == 0) { + return; + } + if (idx < 0) { + idx = (l - 1); + } + this._optionSelected(this.items[idx]); + }, + + ruleToggleTLSGuard: function() { + this._toggleTLSGuard(this._tlsg); } }); @@ -261,7 +299,7 @@ const ButtonGroup = new Lang.Class({ _init: function() { this.actor = new St.BoxLayout({ style_class: 'fw-button-group'}); this._checked = -1; - this._buttons= []; + this._buttons = []; for(let i = 0; i < arguments.length; i++) { let idx = i; this._buttons[i] = new St.Button({ style_class: 'fw-group-button button', @@ -277,7 +315,6 @@ const ButtonGroup = new Lang.Class({ }, _setChecked: function(idx) { - if (idx == this._checked) { return; } @@ -288,6 +325,32 @@ const ButtonGroup = new Lang.Class({ this._checked = idx; }, + next: function() { + let idx = this._checked + , l = this._buttons.length; + idx++; + if (l == 0) { + return + } + if (idx >= l) { + idx = 0; + } + this._setChecked(idx); + }, + + previous: function() { + let idx = this._checked + , l = this._buttons.length; + idx--; + if (l == 0) { + return + } + if (idx < 0) { + idx = (l - 1); + } + this._setChecked(idx); + } + }); const ExpandingSection = new Lang.Class({ @@ -497,6 +560,48 @@ const PromptDialog = new Lang.Class({ ]); }, + _onPromptScopeNext: function() { + if (this.details.isOpen) { + this.optionList.scopeNext(); + } + }, + + _onPromptScopePrevious: function() { + if (this.details.isOpen) { + this.optionList.scopePrevious(); + } + }, + + _onPromptRuleAllow: function() { + this.onAllow(); + }, + + _onPromptRuleDeny: function() { + this.onDeny(); + }, + + _onPromptRuleNext: function() { + if (this.details.isOpen) { + this.optionList.ruleNext(); + } + }, + + _onPromptRulePrevious: function() { + if (this.details.isOpen) { + this.optionList.rulePrevious(); + } + }, + + _onPromptToggleDetails: function() { + this.details.activate(); + }, + + _onPromptToggleTlsguard: function() { + if (this.details.isOpen) { + this.optionList.ruleToggleTLSGuard(); + } + }, + onAllow: function() { if (this.cbClose !== undefined && this.cbClose !== null) { this.cbClose(); diff --git a/gnome-shell/firewall@subgraph.com/extension.js b/gnome-shell/firewall@subgraph.com/extension.js index 9fa65ca..a9c74a7 100644 --- a/gnome-shell/firewall@subgraph.com/extension.js +++ b/gnome-shell/firewall@subgraph.com/extension.js @@ -1,12 +1,17 @@ const Lang = imports.lang; +const Main = imports.ui.main; +const Meta = imports.gi.Meta; +const Shell = imports.gi.Shell; + const Gio = imports.gi.Gio; const Extension = imports.misc.extensionUtils.getCurrentExtension(); +const Convenience = Extension.imports.convenience; + const Dialog = Extension.imports.dialog; const Menu = Extension.imports.menu; //const ConnectionMonitor = Extension.imports.cmonitor; - function init() { return new FirewallSupport(); } @@ -75,18 +80,70 @@ const FirewallPromptHandler = new Lang.Class({ Name: 'FirewallPromptHandler', _init: function() { + this._settings = Convenience.getSettings(); this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(FirewallPromptInterface, this); this._dbusImpl.export(Gio.DBus.system, '/com/subgraph/FirewallPrompt'); Gio.bus_own_name_on_connection(Gio.DBus.system, 'com.subgraph.FirewallPrompt', Gio.BusNameOwnerFlags.REPLACE, null, null); this._dialogs = new Array(); + this._initKeybindings(); }, destroy: function() { + log("SGFW: Exited"); this._closeDialogs(); this._dbusImpl.unexport(); + this._destroyKeybindings(); + }, + + _initKeybindings: function() { + this._keyBindings = new Array( + "prompt-scope-previous" + , "prompt-scope-next" + , "prompt-rule-next" + , "prompt-rule-previous" + , "prompt-rule-allow" + , "prompt-rule-deny" + , "prompt-toggle-details" + , "prompt-toggle-tlsguard" + ); + for (var i = 0 , ii = this._keyBindings.length; i < ii; i++) { + Main.wm.addKeybinding(this._keyBindings[i], + this._settings, + Meta.KeyBindingFlags.NONE, + Shell.ActionMode.ALL, + Lang.bind(this, this._handleKeybinding, this._keyBindings[i])); + } + }, + + _handleKeybinding: function(a, b, c, d, binding) { + if (this._dialogs.length <= 0) { + return false; + } + + let fname = binding.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); + let fname = "_on"+ fname[0].toUpperCase() + fname.substr(1); + if (!( fname in this._dialogs[0] )) { + log("SGFW: Invalid key binding (1)... " + fname); + return true; + } + let fn = this._dialogs[0][fname]; + if (typeof fn !== "function") { + log("SGFW: Invalid key binding (2)... " + fname + " " + (typeof fn)); + return true; + } + + Lang.bind(this._dialogs[0], fn)(); + return true; + }, + + _destroyKeybindings: function() { + for (var i = 0 , ii = keyBindings.length; i < ii; i++) { + Main.wm.removeKeybinding(this._keyBindings[i]); + } }, _closeDialogs: function() { + log("SGFW: Closing all dialogs"); if (this._dialogs.length > 0) { dialog = this._dialogs.shift(); dialog.close(); @@ -108,17 +165,21 @@ const FirewallPromptHandler = new Lang.Class({ }, onCloseDialog: function() { + log("SGFW: Closed dialog"); this._dialogs.shift(); if (this._dialogs.length > 0) { + log("SGFW: Opening next dialogs (remaining: " + this._dialogs.length + ")"); this._dialogs[0].open(); } }, CloseAsync: function(params, invocation) { + log("SGFW: Close Async Requested"); this._closeDialogs(); }, TestPrompt: function(params, invocation) { + log("SGFW: Test Prompt Requested"); this.RequestPromptAsync(["Firefox", "firefox", "/usr/bin/firefox-esr", "242.12.111.18", "443", "linux", "2342", "TCP", true, true], nil); } }); diff --git a/gnome-shell/firewall@subgraph.com/schemas/com.subgraph.firewall.gschema.xml b/gnome-shell/firewall@subgraph.com/schemas/com.subgraph.firewall.gschema.xml index 559b079..2efc43f 100644 --- a/gnome-shell/firewall@subgraph.com/schemas/com.subgraph.firewall.gschema.xml +++ b/gnome-shell/firewall@subgraph.com/schemas/com.subgraph.firewall.gschema.xml @@ -1,9 +1,55 @@ - + + + ']]]> + Show prompt dialog shortcuts + + + + left']]]> + Select previous scope + + + + right']]]> + Select next scope + + + + up']]]> + Select previous rule + + + + down']]]> + Select next rule + + + + a']]]> + Accept rule + + + + d']]]> + Deny rule + + + + space']]]> + Toggle details view + + + + s']]]> + Toggle TLS Guard mode + - \ No newline at end of file + diff --git a/gnome-shell/firewall@subgraph.com/schemas/gschemas.compiled b/gnome-shell/firewall@subgraph.com/schemas/gschemas.compiled index 5a7e9d75585469b75fffe285a482ee96f839eb12..238e1ad4f2410b04b005c63a1e2781f09727ce04 100644 GIT binary patch literal 1012 zcmZ`&ziSjh82$VaHKtMU;$aT4Jd3++EtZ2|5d{k|AQm>`?cVOfW@nh4%_(RK)7VSE zABDAWe}a(fZ3Go;6fAATB1N##_cn8S!FA#7`*{0(^S$|IXYIDKnJS$4rwzVy5OOoo-;+HyL7}m^u-`e^lqvWN(BAp*o;u?e^nGd&W}X<+6FCIFy?T0{ z65}(-zX^80&)pZAI^(m@pMYNj+4q$Wb;ewO3jPXQ-<~|A&Ul%9!5wa5Yx0sh;|}yI z;Jd)|(bf`Y#CQRE3VsZHy7Y08`Hb238Tbvb-+5m9WK5s$z?`eGdc(M$t@5~MY`mH2 zstngF6Wc*}RTs|cd=ReYZcrI%OIMYbeMLFc=5Gl)Vg^lhc|3A*p|0fo(Xu`R<{t+z zUicT`8S%X4{X}u`08;b1;d+{l+#r&R|GFyT`~3MD{n#u?ovh3kIh`cfeiS>E<>i0s zN~4BxW1Y*(q*69&?&p1$hkg2%Wva(LysR5m?$6wVraAihzELjaQ1Aq}5W(z11hWef jh?MhF#2wM&I=^uq-k&<`ul^tW7@PMM>2cxDm5cud4VnRw delta 192 zcmeyuzJY0ijno+i1_oA928RDYpv4H}F!(U&0BHlpiD7aP%pd_M07)LGt>Xr%1nXib zW4Hkn`vk-=6F_W`315KZ4IHxtkS&vAnAPkU7?^;<`30$Yy2<%@ yd8x@InfZCTx%qjSCHX}RHqQBZB}Mr;b~cVVC3eLHiOH!9A`BXd#hO4(KmY)wJ1-gl