Merge pull request #63 from franglais125/number_overlay

Implement overlay numbers for the hotkeys
This commit is contained in:
Jason DeRose
2017-02-16 12:18:52 -05:00
committed by GitHub
5 changed files with 624 additions and 6 deletions

View File

@@ -8,6 +8,273 @@
<property name="step_increment">0.01</property>
<property name="page_increment">0.10000000000000001</property>
</object>
<object class="GtkAdjustment" id="shortcut_time_adjustment">
<property name="upper">10000</property>
<property name="step_increment">250</property>
<property name="page_increment">1000</property>
</object>
<object class="GtkBox" id="box_overlay_shortcut">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkFrame" id="frame_overlay_show_dock">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkListBox" id="listbox_overlay_shortcut">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="selection_mode">none</property>
<child>
<object class="GtkListBoxRow" id="listboxrow_hotkey_prefix">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_hotkey_prefix">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkComboBoxText" id="hotkey_prefix_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">center</property>
<items>
<item id="Super" translatable="yes">Super</item>
<item id="SuperAlt" translatable="yes">Super + Alt</item>
</items>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="hotkey_prefix_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Hotkeys prefix</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="hotkey_prefix_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="max-width-chars">40</property>
<property name="label" translatable="yes">Hotkeys will either be Super+Number or Super+Alt+Num</property>
<property name="wrap">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_overlay_shortcut">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_overlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkSwitch" id="overlay_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="height">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="overlay_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Number overlay</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="overlay_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Temporarily show the application numbers over the icons when using the hotkeys.</property>
<property name="wrap">True</property>
<property name="max-width-chars">40</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_timeout">
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_timeout">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="hexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkSpinButton" id="timeout_spinbutton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="adjustment">shortcut_time_adjustment</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="shortcut_timeout_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Hide timeout (ms)</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkListBoxRow" id="listboxrow_extra_shortcut">
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
<object class="GtkGrid" id="grid_shortcut">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="column_spacing">32</property>
<child>
<object class="GtkEntry" id="shortcut_entry">
<property name="width-chars">12</property>
<property name="valign">center</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="shortcut_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">Shortcut to show the overlay for 2 seconds</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="shortcut_description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="xalign">0</property>
<property name="max-width-chars">40</property>
<property name="label" translatable="yes">Syntax: &lt;Shift&gt;, &lt;Ctrl&gt;, &lt;Alt&gt;, &lt;Super&gt;</property>
<property name="wrap">True</property>
<style>
<class name="dim-label"/>
</style>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child type="label_item">
<placeholder/>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<object class="GtkBox" id="box_middle_click_options">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -1233,11 +1500,43 @@
</packing>
</child>
<child>
<object class="GtkSwitch" id="hot_keys_switch">
<object class="GtkBox" id="overlay_box">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<child>
<object class="GtkButton" id="overlay_button">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="xalign">0.46000000834465027</property>
<child>
<object class="GtkImage" id="image_overlay">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">emblem-system-symbolic</property>
</object>
</child>
<style>
<class name="circular"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSwitch" id="hot_keys_switch">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="halign">end</property>
<property name="valign">center</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>

View File

@@ -25,6 +25,9 @@ const Convenience = Me.imports.convenience;
const Lang = imports.lang;
const Main = imports.ui.main;
const Shell = imports.gi.Shell;
const Gtk = imports.gi.Gtk;
const Gdk = imports.gi.Gdk;
const Mainloop = imports.mainloop;
const Meta = imports.gi.Meta;
@@ -56,6 +59,7 @@ const dtpOverview = new Lang.Class({
this._optionalWorkspaceIsolation();
this._optionalHotKeys();
this._optionalNumberOverlay();
this._bindSettingsChanges();
},
@@ -70,6 +74,7 @@ const dtpOverview = new Lang.Class({
// Remove key bindings
this._disableHotKeys();
this._disableExtraShortcut();
},
_bindSettingsChanges: function() {
@@ -172,12 +177,54 @@ const dtpOverview = new Lang.Class({
else
Lang.bind(this, this._disableHotKeys)();
})
],[
this._dtpSettings,
'changed::hotkey-prefix-text',
Lang.bind(this, this._checkHotkeyPrefix)
]);
},
_checkHotkeyPrefix: function() {
let hotkeyPrefix = this._dtpSettings.get_string('hotkey-prefix-text');
if (hotkeyPrefix == 'Super')
hotkeyPrefix = '<Super>';
else if (hotkeyPrefix == 'SuperAlt')
hotkeyPrefix = '<Super><Alt>';
let [key, mods] = Gtk.accelerator_parse(hotkeyPrefix);
for (let i = 1; i <= this._numHotkeys; i++) {
let number = i;
if (number == 10)
number = 0;
key = Gdk.keyval_from_name(number.toString());
if (Gtk.accelerator_valid(key, mods)) {
let shortcut = Gtk.accelerator_name(key, mods);
// Setup shortcut strings
let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-', // Regular numbers
'app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-']; // Key-pad numbers
keys.forEach( function(key) {
this._dtpSettings.set_strv(key + i, [shortcut]);
}, this);
}
else {
// Reset default settings for the relevant keys if the
// accelerators are invalid
let keys = ['app-hotkey-' + i, 'app-shift-hotkey-' + i, 'app-ctrl-hotkey-' + i, // Regular numbers
'app-hotkey-kp-' + i, 'app-shift-hotkey-kp-' + i, 'app-ctrl-hotkey-kp-' + i]; // Key-pad numbers
keys.forEach(function(val) {
this._dtpSettings.set_value(val, this._dtpSettings.get_default_value(val));
}, this);
}
}
},
_enableHotKeys: function() {
if (this._hotKeysEnabled)
return;
this._checkHotkeyPrefix();
// Setup keyboard bindings for taskbar elements
let keys = ['app-hotkey-', 'app-shift-hotkey-', 'app-ctrl-hotkey-', // Regular numbers
'app-hotkey-kp-', 'app-shift-hotkey-kp-', 'app-ctrl-hotkey-kp-']; // Key-pad numbers
@@ -187,7 +234,10 @@ const dtpOverview = new Lang.Class({
Main.wm.addKeybinding(key + (i + 1), this._dtpSettings,
Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
Lang.bind(this, function() {this._activateApp(appNum);}));
Lang.bind(this, function() {
this._activateApp(appNum);
this._showOverlay();
}));
}
}, this);
@@ -206,5 +256,93 @@ const dtpOverview = new Lang.Class({
}, this);
this._hotKeysEnabled = false;
}
},
_optionalNumberOverlay: function() {
this._shortcutIsSet = false;
// Enable extra shortcut
if (this._dtpSettings.get_boolean('hot-keys'))
this._enableExtraShortcut();
this._signalsHandler.add([
this._dtpSettings,
'changed::hot-keys',
Lang.bind(this, this._checkHotkeysOptions)
], [
this._dtpSettings,
'changed::hotkeys-overlay',
Lang.bind(this, this._checkHotkeysOptions)
], [
this._dtpSettings,
'changed::shortcut-text',
Lang.bind(this, this._checkHotkeysOptions)
]);
},
_checkHotkeysOptions: function() {
if (this._dtpSettings.get_boolean('hot-keys'))
this._enableExtraShortcut();
else
this._disableExtraShortcut();
},
_enableExtraShortcut: function() {
let shortcut_is_valid = this._setShortcut();
if (shortcut_is_valid && !this._shortcutIsSet) {
Main.wm.addKeybinding('shortcut', this._dtpSettings,
Meta.KeyBindingFlags.NONE,
Shell.ActionMode.NORMAL | Shell.ActionMode.OVERVIEW,
Lang.bind(this, function() {
this._overlayFromShortcut = true;
this._showOverlay();
}));
this._shortcutIsSet = true;
}
},
_setShortcut: function() {
let shortcut_text = this._dtpSettings.get_string('shortcut-text');
let [key, mods] = Gtk.accelerator_parse(shortcut_text);
if (Gtk.accelerator_valid(key, mods)) {
let shortcut = Gtk.accelerator_name(key, mods);
this._dtpSettings.set_strv('shortcut', [shortcut]);
return true;
}
else {
this._dtpSettings.set_strv('shortcut', []);
return false;
}
},
_disableExtraShortcut: function() {
if (this._shortcutIsSet) {
Main.wm.removeKeybinding('shortcut');
this._shortcutIsSet = false;
}
},
_showOverlay: function() {
if (this._dtpSettings.get_boolean('hotkeys-overlay') || this._overlayFromShortcut)
this.taskbar.toggleNumberOverlay(true);
// Restart the counting if the shortcut is pressed again
if (this._numberOverlayTimeoutId) {
Mainloop.source_remove(this._numberOverlayTimeoutId);
this._numberOverlayTimeoutId = 0;
}
let timeout = this._dtpSettings.get_int('overlay-timeout');
if (this._overlayFromShortcut) {
timeout = this._dtpSettings.get_int('shortcut-timeout');
this._overlayFromShortcut = false;
}
// Hide the overlay/dock after the timeout
this._numberOverlayTimeoutId = Mainloop.timeout_add(timeout, Lang.bind(this, function() {
this._numberOverlayTimeoutId = 0;
this.taskbar.toggleNumberOverlay(false);
}));
}
});

View File

@@ -250,6 +250,77 @@ const Settings = new Lang.Class({
this._builder.get_object('hot_keys_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('hot-keys',
this._builder.get_object('overlay_button'),
'sensitive',
Gio.SettingsBindFlags.DEFAULT);
// Create dialog for number overlay options
this._builder.get_object('overlay_button').connect('clicked', Lang.bind(this, function() {
let dialog = new Gtk.Dialog({ title: _('Advanced hotkeys options'),
transient_for: this.widget.get_toplevel(),
use_header_bar: true,
modal: true });
// GTK+ leaves positive values for application-defined response ids.
// Use +1 for the reset action
dialog.add_button(_('Reset to defaults'), 1);
let box = this._builder.get_object('box_overlay_shortcut');
dialog.get_content_area().add(box);
this._builder.get_object('overlay_switch').set_active(this._settings.get_boolean('hotkeys-overlay'));
this._settings.bind('hotkey-prefix-text',
this._builder.get_object('hotkey_prefix_combo'),
'text',
Gio.SettingsBindFlags.DEFAULT);
this._builder.get_object('hotkey_prefix_combo').set_active_id(this._settings.get_string('hotkey-prefix-text'));
this._settings.bind('hotkey-prefix-text',
this._builder.get_object('hotkey_prefix_combo'),
'active-id',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('hotkeys-overlay',
this._builder.get_object('overlay_switch'),
'active',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('overlay-timeout',
this._builder.get_object('timeout_spinbutton'),
'value',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('hotkeys-overlay',
this._builder.get_object('timeout_spinbutton'),
'sensitive',
Gio.SettingsBindFlags.DEFAULT);
this._settings.bind('shortcut-text',
this._builder.get_object('shortcut_entry'),
'text',
Gio.SettingsBindFlags.DEFAULT);
dialog.connect('response', Lang.bind(this, function(dialog, id) {
if (id == 1) {
// restore default settings for the relevant keys
let keys = ['hotkey-prefix-text', 'shortcut-text', 'hotkeys-overlay', 'overlay-timeout'];
keys.forEach(function(val) {
this._settings.set_value(val, this._settings.get_default_value(val));
}, this);
} else {
// remove the settings box so it doesn't get destroyed;
dialog.get_content_area().remove(box);
dialog.destroy();
}
return;
}));
dialog.show_all();
}));
// setup dialog for advanced options
this._builder.get_object('button_advanced_options').connect('clicked', Lang.bind(this, function() {

View File

@@ -13,6 +13,10 @@
<value value='1' nick='STATUSLEFT'/>
<value value='2' nick='STATUSRIGHT'/>
</enum>
<enum id='org.gnome.shell.extensions.dash-to-panel.hotkeyPrefix'>
<value value='0' nick='Super'/>
<value value='1' nick='SuperAlt'/>
</enum>
<!-- this is mean to Match StSide. LEFT and RIGHT actual position in reversed in
rtl languages -->
<enum id='org.gnome.shell.extensions.dash-to-panel.panelPosition'>
@@ -147,11 +151,41 @@
<summary>Status icon padding</summary>
<description>Set the size of the aggregate (status) menu icon padding. (-1 for default)</description>
</key>
<key type="s" name="shortcut-text">
<default>"&lt;Super&gt;q"</default>
<summary>Keybinding to show the dock and the number overlay.</summary>
<description>Behavior depends on hotkeys-show-dock and hotkeys-overlay.</description>
</key>
<key type="as" name="shortcut">
<default><![CDATA[['<Super>q']]]></default>
<summary>Keybinding to show the dock and the number overlay.</summary>
<description>Behavior depends on hotkeys-show-dock and hotkeys-overlay.</description>
</key>
<key type="i" name="shortcut-timeout">
<default>2000</default>
<summary>Timeout to hide the dock, in seconds</summary>
<description>Sets the time duration before the dock is hidden again.</description>
</key>
<key type="i" name="overlay-timeout">
<default>750</default>
<summary>Timeout to hide the dock, in seconds</summary>
<description>Sets the time duration before the dock is hidden again.</description>
</key>
<key type="b" name="hotkeys-overlay">
<default>true</default>
<summary>Show the dock when using the hotkeys</summary>
<description>The dock will be quickly shown so that the number-overlay is visible and app activation is easier</description>
</key>
<key type="b" name="hot-keys">
<default>false</default>
<summary>Super Hot-Keys</summary>
<description>Launch and switch between dash items using Super+(0-9)</description>
</key>
<key name="hotkey-prefix-text" enum="org.gnome.shell.extensions.dash-to-panel.hotkeyPrefix">
<default>'Super'</default>
<summary>Prefix to use for hotkeys</summary>
<description>You can choose between Super or SuperAlt as the prefix for hotkeys.</description>
</key>
<key name="app-ctrl-hotkey-1" type="as">
<default><![CDATA[['<Ctrl><Super>1']]]></default>
<summary>Keybinding to launch 1st dash app</summary>

View File

@@ -865,6 +865,9 @@ const taskbar = new Lang.Class({
// This is required for icon reordering when the scrollview is used.
this._updateAppIconsGeometry();
// This will update the size, and the corresponding number for each icon
this._updateNumberOverlay();
},
// Reset the displayed apps icon to mantain the correct order
@@ -886,6 +889,34 @@ const taskbar = new Lang.Class({
},
_updateNumberOverlay: function() {
let appIcons = this._getAppIcons();
let counter = 1;
appIcons.forEach(function(icon) {
if (counter < 10){
icon.setNumberOverlay(counter);
counter++;
}
else if (counter == 10) {
icon.setNumberOverlay(0);
counter++;
}
else {
// No overlay after 10
icon.setNumberOverlay(-1);
}
icon.updateNumberOverlay();
});
},
toggleNumberOverlay: function(activate) {
let appIcons = this._getAppIcons();
appIcons.forEach(function(icon) {
icon.toggleNumberOverlay(activate);
});
},
_clearDragPlaceholder: function() {
if (this._dragPlaceholder) {
this._animatingPlaceholdersCount++;
@@ -1250,6 +1281,8 @@ const taskbarAppIcon = new Lang.Class({
}));
this.forcedOverview = false;
this._numberOverlay();
},
shouldShowTooltip: function() {
@@ -1561,6 +1594,49 @@ const taskbarAppIcon = new Lang.Class({
cr.fill();
cr.$dispose();
},
_numberOverlay: function() {
// Add label for a Hot-Key visual aid
this._numberOverlayLabel = new St.Label();
this._numberOverlayBin = new St.Bin({
child: this._numberOverlayLabel,
x_align: St.Align.START, y_align: St.Align.START,
x_expand: true, y_expand: true
});
this._numberOverlayStyle = 'background-color: rgba(0,0,0,0.8);'
this._numberOverlayOrder = -1;
this._numberOverlayBin.hide();
this._iconContainer.add_child(this._numberOverlayBin);
},
updateNumberOverlay: function() {
// Set the font size to something smaller than the whole icon so it is
// still visible. The border radius is large to make the shape circular
let [minWidth, natWidth] = this._iconContainer.get_preferred_width(-1);
let font_size = Math.round(Math.max(12, 0.3*natWidth));
let size = Math.round(font_size*1.2);
this._numberOverlayLabel.set_style(
this._numberOverlayStyle +
'font-size: ' + font_size + 'px;' +
'text-align: center;' +
'border-radius: ' + this.icon.iconSize + 'px;' +
'width: ' + size + 'px; height: ' + size +'px;'
);
},
setNumberOverlay: function(number) {
this._numberOverlayOrder = number;
this._numberOverlayLabel.set_text(number.toString());
},
toggleNumberOverlay: function(activate) {
if (activate && this._numberOverlayOrder > -1)
this._numberOverlayBin.show();
else
this._numberOverlayBin.hide();
}
});