Skip to content

Commit

Permalink
Detect OS and set default hold key (closes #43)
Browse files Browse the repository at this point in the history
I moved the manual hold key selection into an advanced section (closes #49) of
options.
  • Loading branch information
jchang504 committed Jul 31, 2017
1 parent 04b5243 commit f03b5ef
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 38 deletions.
31 changes: 27 additions & 4 deletions background.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ var current_tab_index = 0;
// changes (this does NOT fire the active tab change listener).
var window_to_active_tab_map = {};

// Detect and save the current OS.
function detectOs() {
chrome.runtime.getPlatformInfo(function(platform_info) {
chrome.storage.sync.set({
[OS_KEY]: platform_info.os
});
});
}

// Navigate to (make active) the specified tab (and focus its window, if the
// optional argument is provided).
function navigateToTab(tab_id, window_id) {
Expand Down Expand Up @@ -131,12 +140,24 @@ function addToTabHistory(tab_id) {
chrome.windows.onFocusChanged.addListener(function (window_id) {
// Release hold key on window change (even to WINDOW_ID_NONE) to avoid
// sticking when using native shortcuts.
LOG_INFO("Send hold release to tab_id=" + tab_history[current_tab_index]);
chrome.tabs.sendMessage(tab_history[current_tab_index],
{[HOLD_RELEASE_MSG]: null});
var current_tab_id = tab_history[current_tab_index];
if (current_tab_id != undefined) {
LOG_INFO("Send hold release to tab_id=" +
tab_history[current_tab_index]);
chrome.tabs.sendMessage(tab_history[current_tab_index],
{[HOLD_RELEASE_MSG]: null});
}
else {
LOG_WARNING("tab_history[current_tab_index] is undefined on chrome.windows.onFocusChanged event");
}
// Track last focused window; ignore when user is not on any window.
if (window_id != chrome.windows.WINDOW_ID_NONE) {
addToTabHistory(window_to_active_tab_map[window_id]);
var new_tab = window_to_active_tab_map[window_id];
if (new_tab != undefined) {
addToTabHistory(new_tab);
} else {
LOG_WARNING("window_to_active_tab_map[window_id] is undefined on chrome.windows.onFocusChanged event");
}
}
},
// Exclude 'app' and 'panel' WindowType (extension's own windows).
Expand Down Expand Up @@ -269,5 +290,7 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
}
});

// Detect and save OS to determine default hold key.
detectOs();
// Load hotkeys at background script start.
loadHotkeys();
18 changes: 17 additions & 1 deletion hotkeys.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,24 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
}
});

chrome.storage.sync.get({[HOLD_KEY_KEY]: HOLD_KEY_DEFAULT}, function(items) {
chrome.storage.sync.get({
[HOLD_KEY_KEY]: HOLD_KEY_EMPTY,
[OS_KEY]: OS_EMPTY
}, function(items) {
hold_key = items[HOLD_KEY_KEY];
if (hold_key == HOLD_KEY_EMPTY) {
// No hold key saved in storage.
var os = items[OS_KEY];
if (os == OS_EMPTY) {
// This should never happen, unless the background script somehow
// failed to save the OS.
LOG_ERROR("No OS saved in chrome.storage.sync.");
hold_key = ALT;
}
else {
hold_key = OS_TO_DEFAULT_HOLD_KEY[os];
}
}
// Only add listeners once hold_key has been updated from options.
$(window).get(0).addEventListener(KEYDOWN, keydownHandler, true);
$(window).get(0).addEventListener(KEYUP, keyupHandler, true);
Expand Down
20 changes: 17 additions & 3 deletions options.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ body {
min-width: 750px;
}

#hold_key_description {
margin-bottom: 10px;
#recommended_description, #changed_description {
display: none;
}

#hotkey_entry {
margin-bottom: 10px;
margin-bottom: 0.5em;
}

#hotkey_entry tr:first-child th {
Expand Down Expand Up @@ -41,3 +41,17 @@ td.checkbox {
.restore {
display: none;
}

#open_advanced {
margin-top: 1em;
}

#open_advanced > a {
color: grey;
text-decoration: none;
cursor: pointer;
}

#advanced {
display: none;
}
53 changes: 40 additions & 13 deletions options.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,30 @@
<body>
<h1>KeepTabs Options</h1>
<form id="options">
<h2>Set hold key</h2>
<p id="hold_key_description">The <strong>hold key</strong> is the key
you hold while typing to activate your hotkeys. If it is used for
native shortcuts in Chrome (e.g. Ctrl+f on Windows), creating an
overlapping hotkey may or may not override the native shortcut.
Operating system shortcuts, however, will not get overridden, so choose
your hold key carefully to avoid side effects.</p>
<select id="hold_key">
<!-- Values are Chrome e.key values -->
<option value="Control">Control</option>
<option value="Alt">Alt/Option (Mac)</option>
<option value="Meta">Windows key/Cmd (Mac)</option>
</select>
<h2>Hold key</h2>
<p id="hold_key_description">
The <strong>hold key</strong> is the key you hold while typing to
activate your hotkeys. For most users, it is recommended that you
stick with the default hold key for your operating system, as it
has been chosen for the least interference with system and browser
shortcuts. If you have a customized setup and would like to change
your hold key, you can do so in Advanced Options at the bottom.
</p>
<div id="recommended_description">
<p>
Your operating system was detected as
<strong><span id="detected_os"></span></strong>. The recommended
hold key for your operating system is
<strong><span class="hold_key_name"></span></strong>.
</p>
<p>
<span id="extra_suggestion"></span>
</p>
</div>
<p id="changed_description">
You have changed your hotkey to <strong><span
class="hold_key_name"></span></strong> in Advanced Options.
</p>
<h2>Customize hotkeys</h2>
<p>
Hit a <strong>Hotkey</strong> with your hold key to navigate to the
Expand Down Expand Up @@ -47,6 +58,22 @@ <h2>Customize hotkeys</h2>
<input id="add_hotkey" type="button" value="Add Hotkey"></input>
<input id="save" type="submit" value="Save all">
<input id="close" type="button" value="Close"></input>

<div id="open_advanced">
<a>Open advanced options</a>
</div>
<div id="advanced">
<h2>Advanced options</h2>
<p>Note that these options and features come with less instructions
and less guarantee of stability; they are recommended for
developers and advanced users.</p>
<label for="hold_key">Change hold key: </label><select id="hold_key">
<!-- Values are Chrome e.key values -->
<option value="Control">Control</option>
<option value="Alt"></option>
<option value="Meta"></option>
</select>
</div>
</form>

<script src="jquery-3.2.1.min.js"></script>
Expand Down
109 changes: 94 additions & 15 deletions options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
// CSS selectors.
var HOLD_KEY_SELECTOR = '#hold_key';
var RECOMMENDED_DESCRIPTION_SELECTOR = "#recommended_description";
var CHANGED_DESCRIPTION_SELECTOR = "#changed_description";
var DETECTED_OS_SELECTOR = "#detected_os";
var HOLD_KEY_NAME_SELECTOR = ".hold_key_name";
var EXTRA_SUGGESTION_SELECTOR = "#extra_suggestion";
var HOTKEY_ENTRYS_TABLE_SELECTOR = '#hotkey_entry > tbody';
var HOTKEY_ENTRY_ROWS_SELECTOR = '#hotkey_entry tr:not(:first-child)';
var HOTKEY_ENTRY_LAST_ROW_SELECTOR = '#hotkey_entry tr:last-child';
Expand All @@ -18,12 +22,28 @@ var OPTIONS_FORM_SELECTOR = '#options';
var ADD_HOTKEY_ENTRY_BUTTON_SELECTOR = '#add_hotkey';
var SAVE_BUTTON_SELECTOR = '#save';
var CLOSE_BUTTON_SELECTOR = '#close';
var OPEN_ADVANCED_SELECTOR = "#open_advanced > a";
var ADVANCED_SELECTOR = "#advanced";
var HOLD_KEY_SELECTOR = '#hold_key';
var OPTION_ALT_SELECTOR = 'option[value="Alt"]';
var OPTION_META_SELECTOR = 'option[value="Meta"]';
var CHECKED = 'checked';
var DISABLED = 'disabled';
// Messages.
var UNSAVED_WARNING_MSG = "You may have unsaved changes. Are you sure you want to close without saving them?";
var CLOSE_BUTTON_SAVED_MSG = "Close";
var CLOSE_BUTTON_UNSAVED_MSG = "Close (drops unsaved changes)";
// Maps OS to extra suggestion for reducing interference with system shortcuts.
var OS_TO_EXTRA_SUGGESTION = {
[MAC_OS]: "",
[WINDOWS_OS]: 'You may also consider disabling the Alt+space shortcut using <a href="https://autohotkey.com/">AutoHotkey</a> to avoid interference with the KeepTabs previous tab hotkey.',
[ANDROID_OS]: "",
[CHROME_OS]: "",
[LINUX_OS]: "If you're on Ubuntu with Unity, it's recommended that you disable the default Alt+space (System Settings > Keyboard > Shortcuts > Windows > 'Activate the window menu') and Alt tap (System Settings > Keyboard > Shortcuts > Launchers > 'Key to show the HUD') shortcuts. Other distros: I'm sure you can figure it out; you're using Linux after all.",
[OPEN_BSD_OS]: ""
};
// Save OS so we know what the default hold key choice is.
var OS;

var HOTKEY_ENTRY_HTML = ' \
<tr> \
Expand Down Expand Up @@ -241,14 +261,49 @@ function saveOptions() {
return false;
}

// Fill in the OS-specific names of the hold key choices.
function fillHoldKeyChoiceNames(os) {
$(OPTION_ALT_SELECTOR).html(OS_TO_HOLD_KEY_NAMES[os][ALT]);
$(OPTION_META_SELECTOR).html(OS_TO_HOLD_KEY_NAMES[os][META]);
}

// Restore all elements related to OS and hold key.
function restoreOsAndHoldKey(os, hold_key) {
if (os == OS_EMPTY) {
// This should never happen, unless the background script
// somehow failed to save the OS.
LOG_ERROR("No OS saved in chrome.storage.sync.");
os = WINDOWS_OS;
}
// Save operating system in global.
OS = os;
fillHoldKeyChoiceNames(os);
if (hold_key == HOLD_KEY_EMPTY || hold_key == OS_TO_DEFAULT_HOLD_KEY[os]) {
// Use OS default hold key choice.
hold_key = OS_TO_DEFAULT_HOLD_KEY[os];
$(RECOMMENDED_DESCRIPTION_SELECTOR).show();
$(DETECTED_OS_SELECTOR).html(OS_TO_READABLE_NAME[os]);
$(EXTRA_SUGGESTION_SELECTOR).html(OS_TO_EXTRA_SUGGESTION[os]);
}
else {
// Hold key changed to non-default.
$(CHANGED_DESCRIPTION_SELECTOR).show();
}
$(HOLD_KEY_NAME_SELECTOR).html(OS_TO_HOLD_KEY_NAMES[os][hold_key]);
$(HOLD_KEY_SELECTOR).val(hold_key);
}

// Restores options as previously stored in chrome.storage.sync.
function restoreOptions() {
// Default values.
chrome.storage.sync.get({
[HOLD_KEY_KEY]: HOLD_KEY_DEFAULT,
[HOTKEYS_KEY]: HOTKEYS_DEFAULT
}, function(items) {
$(HOLD_KEY_SELECTOR).val(items[HOLD_KEY_KEY]);
[OS_KEY]: OS_EMPTY,
[HOLD_KEY_KEY]: HOLD_KEY_EMPTY,
[HOTKEYS_KEY]: HOTKEYS_DEFAULT
}, function(items) {
var hold_key = items[HOLD_KEY_KEY];
var os = items[OS_KEY];
restoreOsAndHoldKey(os, hold_key);
restoreHotkeyEntrys(items[HOTKEYS_KEY]);
});
}
Expand Down Expand Up @@ -278,16 +333,40 @@ function warnIfUnsaved() {
window.close();
}

// Load stored options.
$(document).ready(restoreOptions);
function openAdvancedOptions() {
$(OPEN_ADVANCED_SELECTOR).hide();
$(ADVANCED_SELECTOR).show();
}

$(document).ready(function() {
// Load stored options.
restoreOptions();

// Set up add button.
$(ADD_HOTKEY_ENTRY_BUTTON_SELECTOR).click(addHotkeyEntry);

// Set up add button.
$(ADD_HOTKEY_ENTRY_BUTTON_SELECTOR).click(addHotkeyEntry);
// Set up save button.
$(OPTIONS_FORM_SELECTOR).submit(saveOptions);
$(SAVE_BUTTON_SELECTOR).prop(DISABLED, true);

// Set up hold key select element.
$(HOLD_KEY_SELECTOR).change(function() {
var new_hold_key = $(this).val();
$(HOLD_KEY_NAME_SELECTOR).html(OS_TO_HOLD_KEY_NAMES[OS][new_hold_key]);
if (new_hold_key == OS_TO_DEFAULT_HOLD_KEY[OS]) {
$(RECOMMENDED_DESCRIPTION_SELECTOR).show();
$(CHANGED_DESCRIPTION_SELECTOR).hide();
}
else {
$(CHANGED_DESCRIPTION_SELECTOR).show();
$(RECOMMENDED_DESCRIPTION_SELECTOR).hide();
}
markUnsaved();
});

// Set up save button.
$(OPTIONS_FORM_SELECTOR).submit(saveOptions);
$(SAVE_BUTTON_SELECTOR).prop(DISABLED, true);
$(HOLD_KEY_SELECTOR).change(markUnsaved);
// Set up the close button.
$(CLOSE_BUTTON_SELECTOR).click(warnIfUnsaved);

// Set up the close button.
$(CLOSE_BUTTON_SELECTOR).click(warnIfUnsaved);
// Set up advanced section.
$(OPEN_ADVANCED_SELECTOR).click(openAdvancedOptions);
});
Loading

0 comments on commit f03b5ef

Please sign in to comment.