From a4925b92547cc067aa9bcb66fd53a1350c95e531 Mon Sep 17 00:00:00 2001 From: Csaba Garay Date: Thu, 6 Aug 2020 15:59:56 +0200 Subject: [PATCH] Preferred window size and position offsets --- app/bg/background.js | 31 +++++++++ app/common/setting-definitions.js | 22 ++++++ app/settings/manifest.js | 74 +++++++++++++++++++- package-lock.json | 111 +++++++++--------------------- 4 files changed, 157 insertions(+), 81 deletions(-) diff --git a/app/bg/background.js b/app/bg/background.js index f60a333d..e00387ee 100644 --- a/app/bg/background.js +++ b/app/bg/background.js @@ -127,6 +127,37 @@ let onCommandListener = function(cmd) { } //onCommandListener() chrome.commands.onCommand.addListener(onCommandListener); +// When a window is created +chrome.windows.onCreated.addListener(function(window){ + // Leave TabFern window alone... + if (window.id === me.viewWindowID) return; + + if (S.getBool(S.FIXED_WINDOW_SIZE) && window.type === 'normal') { + let windowSize = S.getString(S.S_WINDOW_SIZE); + [windowWidth, windowHeight] = windowSize.split('x').map((value) => parseInt(value)); + chrome.windows.update(window.id, {width: windowWidth, height: windowHeight}); + } + if (S.getBool(S.PREFERRED_WINDOW_POSITION_OFFSET) && window.type === 'normal') { + let fixedOffsetFormat = RegExp(/^([0-9]+):([0-9]+)$/) + let fixedOffsetValues = S.getString(S.S_WINDOW_POSITION_OFFSET_VALUES).match(fixedOffsetFormat); + if(fixedOffsetValues) { + topOffset = parseInt(fixedOffsetValues[1]); + leftOffset = parseInt(fixedOffsetValues[2]); + chrome.windows.update(window.id, {top:topOffset, left:leftOffset}); + } + let relativeOffsetFormat = RegExp(/^\+([0-9]+):\+([0-9]+)$/) + let relativeOffsetValues = S.getString(S.S_WINDOW_POSITION_OFFSET_VALUES).match(relativeOffsetFormat); + if(relativeOffsetValues) { + // According to Window features documentation default new window offset is 22px + // https://developer.mozilla.org/en-US/docs/Web/API/Window/open#Window_features + // If user has a preferred relative offset preference we need to discount the default offset + topOffset = window.top + parseInt(relativeOffsetValues[1])-22; + leftOffset = window.left + parseInt(relativeOffsetValues[2])-22; + chrome.windows.update(window.id, {top:topOffset, left:leftOffset}); + } + } +}); + // When a window is closed chrome.windows.onRemoved.addListener(function(windowId) { // If the window getting closed is the popup we created diff --git a/app/common/setting-definitions.js b/app/common/setting-definitions.js index d10585cd..4dfb69d9 100644 --- a/app/common/setting-definitions.js +++ b/app/common/setting-definitions.js @@ -105,6 +105,14 @@ _NAM.CFG_TITLE_IN_TOOLTIP = 'tooltip-has-title'; _DEF[_NAM.CFG_TITLE_IN_TOOLTIP] = false; _VAL[_NAM.CFG_TITLE_IN_TOOLTIP] = _vbool; +_NAM.CFG_FIXED_WINDOW_SIZE = 'window-size-is-fixed'; +_DEF[_NAM.CFG_FIXED_WINDOW_SIZE] = false; +_VAL[_NAM.CFG_FIXED_WINDOW_SIZE] = _vbool; + +_NAM.CFG_PREFERRED_WINDOW_POSITION_OFFSET = 'window-position-offset-is-fixed'; +_DEF[_NAM.CFG_PREFERRED_WINDOW_POSITION_OFFSET] = false; +_VAL[_NAM.CFG_PREFERRED_WINDOW_POSITION_OFFSET] = _vbool; + /// Not actually a setting, but an indicator that we loaded settings OK. /// Used by src/settings/main.js. _NAM.SETTINGS_LOADED_OK = '__settings_loaded_OK'; @@ -168,6 +176,20 @@ _VAL[_NAM.CFGS_FAVICON_SOURCE] = (v)=>{ return (( v === FAVICON_SITE || v === FAVICON_CHROME || v === FAVICON_DDG ) ? v : undefined); }; +_NAM.CFGS_WINDOW_SIZE = 'window-size'; +_DEF[_NAM.CFGS_WINDOW_SIZE] = '800x600'; +_VAL[_NAM.CFGS_WINDOW_SIZE] = (v)=>{ + let regex = RegExp(/^[0-9]+[xX][0-9]+$/); + return (( v.match(regex) ) ? v : undefined); +}; + +_NAM.CFGS_WINDOW_POSITION_OFFSET_VALUES = 'window-position-offset-values'; +_DEF[_NAM.CFGS_WINDOW_POSITION_OFFSET_VALUES] = '+36:+36'; +_VAL[_NAM.CFGS_WINDOW_POSITION_OFFSET_VALUES] = (v)=>{ + let regex = RegExp(/^\+?[0-9]+:\+?[0-9]+$/); + return (( v.match(regex) ) ? v : undefined); +}; + // }}}2 /// The default values for the configuration settings. diff --git a/app/settings/manifest.js b/app/settings/manifest.js index 1248972a..c5412217 100644 --- a/app/settings/manifest.js +++ b/app/settings/manifest.js @@ -143,6 +143,77 @@ vote at ${issue(125,true)}. "type": "checkbox", "label": future_i18n('Sort open windows to the top, scroll to the top of the list'), }, + { + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "name": S.FIXED_WINDOW_SIZE, + "type": "checkbox", + "label": future_i18n('Open a window, always open it with a preferred fixed size'), + }, + { // some extra descriptive text for S.FIXED_WINDOW_SIZE + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "type": "description", + "text": future_i18n(`If you change this value please refresh Settings + page (this page) to reveal preferred window size parameter`) + }, + ]; + + if(S.getBool(S.FIXED_WINDOW_SIZE)) setting_definitions.push( + { + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "name": S.S_WINDOW_SIZE, + "type": "text", + "label": future_i18n('Window size'), + }, + { // some extra descriptive text for S.FIXED_WINDOW_SIZE + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "type": "description", + "text": future_i18n(`The format of the window size parameter is [width]x[height] + e.g. 800x600`) + }, + ); + + setting_definitions.push( + { + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "name": S.PREFERRED_WINDOW_POSITION_OFFSET, + "type": "checkbox", + "label": future_i18n('Open a window, use preferred window position offset'), + }, + { // some extra descriptive text for S.PREFERRED_WINDOW_POSITION_OFFSET + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "type": "description", + "text": future_i18n(`Refresh Settings page (this page) when changed + to reveal preferred window position offset parameter`) + }, + ) + + if(S.getBool(S.PREFERRED_WINDOW_POSITION_OFFSET)) setting_definitions.push( + { + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "name": S.S_WINDOW_POSITION_OFFSET_VALUES, + "type": "text", + "label": future_i18n('Window position offset'), + }, + { // some extra descriptive text for S.FIXED_WINDOW_SIZE + "tab": future_i18n("Behaviour"), + "group": future_i18n("When I..."), + "type": "description", + "text": future_i18n( + `If format is [top]:[left] e.g. 16:16 the offset is relative to screen
+ If format is +[top]:+[left] e.g. +36:+36 the offset is relative to last focused window
+ +0:+0 opens new window exactly on top of previously focused window
+ 0:0 opens new window exactly positioned top left corner of screen
`) + }, + ); + + setting_definitions.push( { "tab": future_i18n("Behaviour"), "group": future_i18n("When I..."), @@ -159,8 +230,7 @@ vote at ${issue(125,true)}. TabFern window, even if you didn't check the "Sort open windows" box above.` }, - -]; //setting_definitions +); if(S.ISSUE35) setting_definitions.push( { diff --git a/package-lock.json b/package-lock.json index e97c71cf..89bef1ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1128,9 +1128,9 @@ }, "dependencies": { "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true } } @@ -2417,9 +2417,9 @@ "dev": true }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -2912,19 +2912,13 @@ "rimraf": "2" }, "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } } } @@ -3684,9 +3678,9 @@ "integrity": "sha512-PQpeWxG6vNuTT0Gq20LyAzqSpeBWtQ6DTYIJB7JMJEetgF730Om9e6y82GdEv06o1iaJiH1hh2JpSOXK3zIAdA==" }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, "lazystream": { @@ -3741,9 +3735,9 @@ } }, "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "dev": true }, "lodash.assign": { @@ -4133,19 +4127,13 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "semver": { @@ -4259,19 +4247,13 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "supports-color": { @@ -5951,19 +5933,13 @@ "rimraf": "2" } }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } } } @@ -6189,38 +6165,15 @@ "dev": true }, "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", "dev": true, "requires": { "arr-union": "^3.1.0", "get-value": "^2.0.6", "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } + "set-value": "^2.0.1" } }, "universal-path": {