From 3e43c62dd5f25aa32e28a65f2c4777b03b6ca3ee Mon Sep 17 00:00:00 2001 From: GrylledCheez <68041324+GrylledCheez@users.noreply.github.com> Date: Sun, 25 Jun 2023 20:34:22 -1000 Subject: [PATCH] Add gaps option (#146) * added config.rows with default of 2 * simplified showPreview * added gaps around tiles (#133) default gap is zero, but can can be increased to 50 in 2px increments * fixes requested by gnome Changed version checking to be float instead of int so we can deprecate < 3.36 later Added settings-schema to metadata.json so ExtensionUtils.getSettings can find it Removed disable function from prefs.js Made extension.js definitions consistent with prefs.js resolves #137 * cleaner resize-checker (#141) Instead of doing silly pixel math with the pointer, check to see if the metaGrabOp is any of the Meta.GrabOp resize constants. * Update README.md Fixed manual instalation instructions * Fixed column math for previews * inverted windowMoving guard clause reduced indent level * renamed loop variable * Update prefs.js removed a single newline that was causing github to go crazy and double create init in prefs.js * mention gaps in metadata.json * update gitignore * standardized _log each log line will now start with the name of the function followed by a ")" This will make it easier to grep for relevant logs * Update README.md Gave instructions on getting wintile logs * update README.md --- .gitignore | 1 + README.md | 11 +- extension.js | 806 +++++++++--------- metadata.json | 4 +- prefs.js | 68 +- schemas/gschemas.compiled | Bin 759 -> 813 bytes ...gnome.shell.extensions.wintile.gschema.xml | 6 + 7 files changed, 481 insertions(+), 415 deletions(-) diff --git a/.gitignore b/.gitignore index 0b719e7..a7970b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ wintile@nowsci.com.zip node_modules/ package-lock.json +package.json diff --git a/README.md b/README.md index 49a8680..c7dfc6f 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ WinTile also supports: - Mouse preview and snapping for placing tiles - "Maximize" mode, which adds/removes GNOME animations - Ultrawide-only mode limits 16:9 screens to a 2x2 grid +- Adding gaps around tiles @@ -61,10 +62,18 @@ https://extensions.gnome.org/extension/1723/wintile-windows-10-window-tiling-for 1. unzip the file 1. cd into the directory it creates 1. run `./build.sh` -1. run `unzip wintile@nowsci.com.zip` +1. run `unzip -d wintile@nowsci.com wintile@nowsci.com.zip` 1. run `cp -r wintile@nowsci.com ~/.local/share/gnome-shell/extensions/` 1. restart your session Wayland users need to reboot to enable the extension. Gnome users can press ``+`` and run `r` from the prompt. **(IT WILL NOT WORK from a terminal)** + +### Debugging +If you're having issues, please attach some debug logs to your issue. +Note: debugging must be enabled in WinTile settings + +```bash +journalctl -qf | grep -i -e wintile -e 'js error' +``` diff --git a/extension.js b/extension.js index 8a3eee5..d9fb200 100644 --- a/extension.js +++ b/extension.js @@ -29,16 +29,18 @@ function _log(message) { let config = { cols: 2, + rows: 2, ultrawideOnly: false, useMaximize: true, useMinimize: true, - debug: true, preview: { enabled: true, doubleWidth: true, distance: 75, delay: 500, }, + gap: 0, + debug: true, }; /** @@ -53,6 +55,7 @@ function updateSettings() { config.preview.enabled = gsettings.get_value('preview').deep_unpack(); config.preview.distance = gsettings.get_value('distance').deep_unpack(); config.preview.delay = gsettings.get_value('delay').deep_unpack(); + config.gap = gsettings.get_value('gap').deep_unpack(); config.debug = gsettings.get_value('debug').deep_unpack(); _log(JSON.stringify(config)); } @@ -102,7 +105,14 @@ function requestMinimize(app) { * @param {number} h - desired height */ function moveAppCoordinates(app, x, y, w, h) { - _log(`Moving window to (${x},${y}), size (${w},${h})`); + if (config.gap) { + const halfGap = Math.floor(config.gap / 2); + w -= config.gap; + h -= config.gap; + x += halfGap; + y += halfGap; + } + _log(`moveAppCoordinates) Moving window to (${x},${y}), size (${w},${h}) with ${config.gap}px gaps`); app.move_frame(true, x, y); app.move_resize_frame(true, x, y, w, h); } @@ -113,7 +123,7 @@ function moveAppCoordinates(app, x, y, w, h) { * @param {object} loc = { col, row, width, height } */ function moveApp(app, loc) { - _log(`moveApp: ${JSON.stringify(loc)}`); + _log(`moveApp) ${JSON.stringify(loc)}`); var space = null; if (loc.mouse) { var curMonitor = getCurrentMonitor(); @@ -124,12 +134,13 @@ function moveApp(app, loc) { const isNotUltrawide = (space.width / space.height) < 1.9; _log(`moveApp) isNotUltrawide: ${isNotUltrawide}`); - var colCount = config.cols === 2 || (config.ultrawideOnly && isNotUltrawide) ? 2 : config.cols; + var colCount = config.ultrawideOnly && isNotUltrawide ? 2 : config.cols; + // if the colCount >= than loc.col means that we're moving into a non-ultrawide monitor if (loc.col >= colCount) loc.col = 1; var colWidth = Math.floor(space.width / colCount); - var rowHeight = Math.floor(space.height / 2); + var rowHeight = Math.floor(space.height / config.rows); let x = loc.col * colWidth + space.x; let y = loc.row * rowHeight + space.y; @@ -143,21 +154,21 @@ function moveApp(app, loc) { unMaximizeIfMaximized(app); moveAppCoordinates(app, x, y, w, h); } else { - if (loc.height < 2 || loc.width < config.cols) + if (loc.height < config.rows || loc.width < colCount) unMaximizeIfMaximized(app); moveAppCoordinates(app, x, y, w, h); - if (loc.height === 2 && loc.width === config.cols) { + if (loc.height === config.rows && loc.width === colCount) { // Maximize - _log('maximize'); + _log('moveApp) maximize'); app.maximize(Meta.MaximizeFlags.HORIZONTAL | Meta.MaximizeFlags.VERTICAL); - } else if (loc.height === 2) { + } else if (loc.height === config.rows && !config.gap) { // Maximize vertically - _log('maximize - v'); + _log('moveApp) maximize - v'); app.maximize(Meta.MaximizeFlags.VERTICAL); - } else if (loc.width === config.cols) { + } else if (loc.width === colCount && !config.gap) { // Maximize horizontally - _log('maximize - h'); + _log('moveApp) maximize - h'); app.maximize(Meta.MaximizeFlags.HORIZONTAL); } } @@ -167,8 +178,8 @@ function moveApp(app, loc) { app.wintile.width = loc.width; app.wintile.height = loc.height; let window = app.get_frame_rect(); - let leftShift = window.width - w; - let upShift = window.height - h; + let leftShift = window.width - w + config.gap; + let upShift = window.height - h + config.gap; if (leftShift && loc.col === colCount - 1) { _log(`moveApp) window wider than anticipated. Shift left by ${leftShift} px`); x -= leftShift; @@ -200,10 +211,9 @@ function unMaximizeIfMaximized(app) { * @param {boolean} maximized - Treat as already maximized */ function initApp(app, maximized = false) { - _log('initApp'); const coords = app.get_frame_rect() || getDefaultFloatingRectangle(app); if (!maximized) { - _log('init as normal'); + _log('initApp) init as normal'); app.wintile = { origFrame: {'x': coords.x, 'y': coords.y, 'width': coords.width, 'height': coords.height}, row: -1, @@ -212,12 +222,12 @@ function initApp(app, maximized = false) { width: -1, }; } else { - _log('init as maximize'); + _log('initApp) init as maximize'); app.wintile = { origFrame: {'x': coords.x, 'y': coords.y, 'width': coords.width, 'height': coords.height}, row: 0, col: 0, - height: 2, + height: config.rows, width: config.cols, }; } @@ -229,7 +239,7 @@ function initApp(app, maximized = false) { * @param {object} app the window object */ function getDefaultFloatingRectangle(app) { - _log('Getting default rectangle.'); + _log('getDefaultFloatingRectangle) Getting default rectangle.'); let padding = 100; let workspace = app.get_work_area_current_monitor(); return { @@ -246,9 +256,8 @@ function getDefaultFloatingRectangle(app) { * @param {boolean} move - */ function restoreApp(app, move = true) { - _log('restoreApp'); - _log(move); - _log(JSON.stringify(app.wintile)); + _log(`restoreApp) move: ${move}`); + _log(`restoreApp) app.wintile: ${JSON.stringify(app.wintile)}`); unMaximizeIfMaximized(app); const [mouseX, mouseY] = global.get_pointer(); @@ -264,16 +273,16 @@ function restoreApp(app, move = true) { } else { // BUG: when clicking the maximize button, then dragging the window off, it moves to below the mouse cursor let window = app.get_frame_rect(); - _log(`A) mouse - mouseX:${mouseX} mouseY:${mouseY}`); - _log(`A) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + _log(`restoreApp A) mouse - mouseX:${mouseX} mouseY:${mouseY}`); + _log(`restoreApp A) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); window = app.wintile.origFrame; - _log(`A) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + _log(`restoreApp A) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); moveAppCoordinates(app, Math.floor(mouseX - app.wintile.origFrame.width / 2), mouseY - 10, app.wintile.origFrame.width, app.wintile.origFrame.height); window = app.get_frame_rect(); - _log(`B) mouse - mouseX:${mouseX} mouseY:${mouseY}`); - _log(`B) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + _log(`restoreApp B) mouse - mouseX:${mouseX} mouseY:${mouseY}`); + _log(`restoreApp B) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); window = app.wintile.origFrame; - _log(`B) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + _log(`restoreApp B) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); } app.wintile = null; } @@ -284,7 +293,7 @@ function restoreApp(app, move = true) { */ function sendMove(direction) { _log('---'); - _log(`sendMove: ${direction}`); + _log(`sendMove) ${direction}`); var app = global.display.focus_window; var space = app.get_work_area_current_monitor(); var curMonitor = app.get_monitor(); @@ -295,8 +304,8 @@ function sendMove(direction) { // If a monitor's Y is within 100px + height difference, it's beside it. for (var i = 0; i < Main.layoutManager.monitors.length; i++) { let monitorHeightDiff = Math.abs(Main.layoutManager.monitors[i].height - Main.layoutManager.monitors[curMonitor].height); - _log(`monitor ${i} height : ${Main.layoutManager.monitors[i].height}`); - _log(`monitorsHeightDiff :${monitorHeightDiff}`); + _log(`sendMove) monitor ${i} height : ${Main.layoutManager.monitors[i].height}`); + _log(`sendMove) monitorsHeightDiff :${monitorHeightDiff}`); if (Main.layoutManager.monitors[i].x < Main.layoutManager.monitors[curMonitor].x && Math.abs(Main.layoutManager.monitors[i].y - Main.layoutManager.monitors[curMonitor].y) < (100 + monitorHeightDiff) && @@ -307,58 +316,59 @@ function sendMove(direction) { (monitorToRight === -1 || (monitorToRight >= 0 && Main.layoutManager.monitors[i].x < Main.layoutManager.monitors[monitorToRight].x))) monitorToRight = i; } - _log(`monitorToLeft: ${monitorToLeft}`); - _log(`monitorToRight: ${monitorToRight}`); + _log(`sendMove) monitorToLeft: ${monitorToLeft}`); + _log(`sendMove) monitorToRight: ${monitorToRight}`); // First, check if maximized and apply a wintile state if so if (!app.wintile && app.maximized_horizontally && app.maximized_vertically) initApp(app, true); const isNotUltrawide = (space.width / space.height) < 1.9; - _log(`isNotUltrawide: ${isNotUltrawide}`); + _log(`sendMove) isNotUltrawide: ${isNotUltrawide}`); + var colCount = config.ultrawideOnly && isNotUltrawide ? 2 : config.cols; if (!app.wintile) { // We are not in a tile. Reset and find the most logical position - _log('Not in tile.'); - if (config.cols === 2 || (config.ultrawideOnly && isNotUltrawide)) { + _log('sendMove) Not in tile.'); + if (colCount === 2) { // Normal 2x2 grid switch (direction) { case 'left': // Move to the left most column at full height initApp(app); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 1}); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 1}); break; case 'right': // Move to the right most column at full height initApp(app); - moveApp(app, {'row': 0, 'col': 1, 'height': 2, 'width': 1}); + moveApp(app, {'row': 0, 'col': 1, 'height': config.rows, 'width': 1}); break; case 'up': // 1st Maximize initApp(app); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 2}); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); break; case 'down': // Minimize requestMinimize(app); break; } - } else if (config.cols === 3) { + } else if (colCount === 3) { // Ultrawide 3x2 grid switch (direction) { case 'left': // Move to the left most column at full height initApp(app); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 1}); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 1}); break; case 'right': // Move to the right most column at full height initApp(app); - moveApp(app, {'row': 0, 'col': 2, 'height': 2, 'width': 1}); + moveApp(app, {'row': 0, 'col': 2, 'height': config.rows, 'width': 1}); break; case 'up': // 1st Maximize initApp(app); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 3}); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); break; case 'down': // Minimize @@ -371,17 +381,17 @@ function sendMove(direction) { case 'left': // Move to the left half at full height initApp(app); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 2}); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 2}); break; case 'right': // Move to the right half at full height initApp(app); - moveApp(app, {'row': 0, 'col': 2, 'height': 2, 'width': 2}); + moveApp(app, {'row': 0, 'col': 2, 'height': config.rows, 'width': 2}); break; case 'up': // Maximize to center 4 initApp(app); - moveApp(app, {'row': 0, 'col': 1, 'height': 2, 'width': 2}); + moveApp(app, {'row': 0, 'col': 1, 'height': config.rows, 'width': 2}); break; case 'down': // Minimize @@ -391,196 +401,196 @@ function sendMove(direction) { } } else { // We are already in a tile. - _log('Already in a tile.'); + _log('sendMove) Already in a tile.'); _log(JSON.stringify(app.wintile)); - if (config.cols === 2 || (config.ultrawideOnly && isNotUltrawide)) { + if (colCount === 2) { // Normal 2x2 grid switch (direction) { case 'left': - _log('left'); + _log('sendMove) left'); if (app.wintile.col > 0) { // We can move left on this monitor and keep our size - _log('left - 1'); + _log('sendMove) left - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col - 1, 'height': app.wintile.height, 'width': app.wintile.width}); - } else if (app.wintile.width === 2) { + } else if (app.wintile.width === colCount) { // We are full width top or bottom, shrink - _log('left - 2'); + _log('sendMove) left - 2'); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': 1}); } else if (monitorToLeft === -1) { // We are already on the left, and there is no other monitor to the left // Move to the left most column at full height - _log('left - 3'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 1}); + _log('sendMove) left - 3'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 1}); } else { // There is a monitor to the left, so let's go there app.move_to_monitor(monitorToLeft); - _log('left - 4'); - moveApp(app, {'row': app.wintile.row, 'col': config.cols - 1, 'height': app.wintile.height, 'width': app.wintile.width}); + _log('sendMove) left - 4'); + moveApp(app, {'row': app.wintile.row, 'col': colCount - 1, 'height': app.wintile.height, 'width': app.wintile.width}); } break; case 'right': - _log('right'); - if (app.wintile.col === 0 && app.wintile.width === 2 && app.wintile.height === 2) { + _log('sendMove) right'); + if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.height === config.rows) { // We are maximized, move to right - _log('right - 1'); - moveApp(app, {'row': 0, 'col': 1, 'height': 2, 'width': 1}); - } else if (app.wintile.col === 0 && app.wintile.width === 2) { + _log('sendMove) right - 1'); + moveApp(app, {'row': 0, 'col': 1, 'height': config.rows, 'width': 1}); + } else if (app.wintile.col === 0 && app.wintile.width === colCount) { // We are a top or bottom half, shrink - _log('right - 2'); - moveApp(app, {'row': app.wintile.row, 'col': 1, 'height': 2, 'width': 1}); + _log('sendMove) right - 2'); + moveApp(app, {'row': app.wintile.row, 'col': 1, 'height': config.rows, 'width': 1}); } else if (app.wintile.col < 1) { // We can move right on this monitor and keep our size - _log('right - 3'); + _log('sendMove) right - 3'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col + 1, 'height': app.wintile.height, 'width': app.wintile.width}); } else if (monitorToRight === -1) { // We are already on the right, and there is no other monitor to the right // Move to the right most column at full height - _log('right - 4'); - moveApp(app, {'row': 0, 'col': 1, 'height': 2, 'width': 1}); + _log('sendMove) right - 4'); + moveApp(app, {'row': 0, 'col': 1, 'height': config.rows, 'width': 1}); } else { // There is a monitor to the right, so let's go there app.move_to_monitor(monitorToRight); - _log('right - 5'); + _log('sendMove) right - 5'); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': app.wintile.width}); } break; case 'up': - _log('up'); - if (app.wintile.height === 2 && app.wintile.width === 1) { + _log('sendMove) up'); + if (app.wintile.height === config.rows && app.wintile.width === 1) { // We are full height and not maximized, go to half height - _log('up - 1'); + _log('sendMove) up - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col, 'height': 1, 'width': 1}); } else if (app.wintile.row === 1) { // We are bottom half, go to full height - _log('up - 2'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': app.wintile.width}); - } else if (app.wintile.height === 2 && app.wintile.width === 2) { + _log('sendMove) up - 2'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': app.wintile.width}); + } else if (app.wintile.height === config.rows && app.wintile.width === colCount) { // We are maximized, go to top half - _log('up - 3'); + _log('sendMove) up - 3'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col, 'height': 1, 'width': app.wintile.width}); } else { // We are top half, maximize - _log('up - 4'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 2}); + _log('sendMove) up - 4'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); } break; case 'down': - _log('down'); - if (app.wintile.col === 0 && app.wintile.width === 2 && app.wintile.height === 2) { + _log('sendMove) down'); + if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.height === config.rows) { // We are maximized, restore - _log('down - 1'); + _log('sendMove) down - 1'); restoreApp(app); - } else if (app.wintile.col === 0 && app.wintile.width === 2 && app.wintile.row === 0) { + } else if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.row === 0) { // We are top half, go to bottom half - _log('down - 2'); + _log('sendMove) down - 2'); moveApp(app, {'row': 1, 'col': app.wintile.col, 'height': app.wintile.height, 'width': app.wintile.width}); - } else if (app.wintile.height === 2) { + } else if (app.wintile.height === config.rows) { // We are full height, go to half height - _log('down - 3'); + _log('sendMove) down - 3'); moveApp(app, {'row': 1, 'col': app.wintile.col, 'height': 1, 'width': 1}); } else if (app.wintile.row === 0) { // We are top half, go to full height - _log('down - 4'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': 1}); + _log('sendMove) down - 4'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': 1}); } else if (app.wintile.row === 1 && app.wintile.width === 1) { // We are a bottom tile, go full width - _log('down - 5'); - moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': 2}); + _log('sendMove) down - 5'); + moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': colCount}); } else { // We are bottom half, minimize - _log('down - 6'); + _log('sendMove) down - 6'); requestMinimize(app); } break; } - } else if (config.cols === 3) { + } else if (colCount === 3) { // Ultrawide 3x2 grid switch (direction) { case 'left': - _log('left'); + _log('sendMove) left'); if (app.wintile.col > 0) { // We can move left on this monitor and keep our size - _log('left - 1'); + _log('sendMove) left - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col - 1, 'height': app.wintile.height, 'width': app.wintile.width}); } else if (app.wintile.col === 0 && app.wintile.width > 1) { // We are not yet to smallest width, so shrink - _log('left - 2'); + _log('sendMove) left - 2'); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': app.wintile.width - 1}); } else if (monitorToLeft !== -1) { // There is a monitor to the left, so let's go there - _log('left - 3'); + _log('sendMove) left - 3'); app.move_to_monitor(monitorToLeft); - moveApp(app, {'row': app.wintile.row, 'col': 2, 'height': app.wintile.height, 'width': 1}); + moveApp(app, {'row': app.wintile.row, 'col': colCount - 1, 'height': app.wintile.height, 'width': 1}); } else { // We are already on the left, and there is no other monitor to the left // Move to the left most column at full height - _log('left - 4'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 1}); + _log('sendMove) left - 4'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 1}); } break; case 'right': - _log('right'); - if (app.wintile.col + app.wintile.width - 1 < 2) { + _log('sendMove) right'); + if (app.wintile.col + app.wintile.width - 1 < colCount - 1) { // We can move right on this monitor and keep our size - _log('right - 1'); + _log('sendMove) right - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col + 1, 'height': app.wintile.height, 'width': app.wintile.width}); - } else if (app.wintile.col + app.wintile.width - 1 === 2 && app.wintile.width > 1) { + } else if (app.wintile.col + app.wintile.width - 1 === colCount - 1 && app.wintile.width > 1) { // We are not yet to smallest width, so shrink - _log('right - 2'); + _log('sendMove) right - 2'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col + 1, 'height': app.wintile.height, 'width': app.wintile.width - 1}); } else if (monitorToRight !== -1) { // There is a monitor to the right, so let's go there - _log('right - 3'); + _log('sendMove) right - 3'); app.move_to_monitor(monitorToRight); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': 1}); } else { // We are already on the left, and there is no other monitor to the right // Move to the right most column at full height - _log('right - 4'); - moveApp(app, {'row': 0, 'col': 2, 'height': 2, 'width': 1}); + _log('sendMove) right - 4'); + moveApp(app, {'row': 0, 'col': colCount - 1, 'height': config.rows, 'width': 1}); } break; case 'up': - _log('up'); - if (app.wintile.height === 2) { + _log('sendMove) up'); + if (app.wintile.height === config.rows) { // We are full height on half, go to top while keeping width - _log('up - 1'); + _log('sendMove) up - 1'); moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 1, 'width': app.wintile.width}); } else if (app.wintile.row === 1) { // We are bottom half, go to full height, keeping width - _log('up - 2'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': app.wintile.width}); + _log('sendMove) up - 2'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': app.wintile.width}); } else { // We are top half, go straight to 2nd maximize - _log('up - 3'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 3}); + _log('sendMove) up - 3'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); } break; case 'down': - _log('down'); - if (app.wintile.col === 0 && app.wintile.width === 3 && app.wintile.height === 2) { + _log('sendMove) down'); + if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.height === config.rows) { // We are maximized, restore - _log('down - 1'); + _log('sendMove) down - 1'); restoreApp(app); - } else if (app.wintile.col === 0 && app.wintile.width === 3 && app.wintile.row === 0) { + } else if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.row === 0) { // We are top half, go to bottom half - _log('down - 2'); + _log('sendMove) down - 2'); moveApp(app, {'row': 1, 'col': 0, 'height': app.wintile.height, 'width': app.wintile.width}); - } else if (app.wintile.height === 2) { + } else if (app.wintile.height === config.rows) { // We are full height, go to half height - _log('down - 3'); + _log('sendMove) down - 3'); moveApp(app, {'row': 1, 'col': app.wintile.col, 'height': 1, 'width': app.wintile.width}); } else if (app.wintile.row === 0) { // We are top half, go to full height - _log('down - 4'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': app.wintile.width}); - } else if (app.wintile.width !== 3) { + _log('sendMove) down - 4'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': app.wintile.width}); + } else if (app.wintile.width !== colCount) { // We are not full bottom but are a tile, go full width - _log('down - 5'); - moveApp(app, {'row': 1, 'col': 0, 'height': 1, 'width': 3}); + _log('sendMove) down - 5'); + moveApp(app, {'row': 1, 'col': 0, 'height': 1, 'width': colCount}); } else { // We are bottom half, minimize - _log('down - 6'); + _log('sendMove) down - 6'); requestMinimize(app); } break; @@ -589,98 +599,98 @@ function sendMove(direction) { // Ultrawide 4x2 grid switch (direction) { case 'left': - _log('left'); + _log('sendMove) left'); if (app.wintile.col > 0) { // We can move left on this monitor and keep our size - _log('left - 1'); + _log('sendMove) left - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col - 1, 'height': app.wintile.height, 'width': app.wintile.width}); } else if (app.wintile.col === 0 && app.wintile.width > 1) { // We are not yet to smallest width, so shrink - _log('left - 2'); + _log('sendMove) left - 2'); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': app.wintile.width - 1}); } else if (monitorToLeft !== -1) { // There is a monitor to the left, so let's go there - _log('left - 3'); + _log('sendMove) left - 3'); app.move_to_monitor(monitorToLeft); - moveApp(app, {'row': app.wintile.row, 'col': 3, 'height': app.wintile.height, 'width': 1}); + moveApp(app, {'row': app.wintile.row, 'col': colCount - 1, 'height': app.wintile.height, 'width': 1}); } else { // We are already on the left, and there is no other monitor to the left // Move to the left most column at full height - _log('left - 4'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 1}); + _log('sendMove) left - 4'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': 1}); } break; case 'right': - _log('right'); - if (app.wintile.col + app.wintile.width - 1 < 3) { + _log('sendMove) right'); + if (app.wintile.col + app.wintile.width - 1 < colCount - 1) { // We can move right on this monitor and keep our size - _log('right - 1'); + _log('sendMove) right - 1'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col + 1, 'height': app.wintile.height, 'width': app.wintile.width}); - } else if (app.wintile.col + app.wintile.width - 1 === 3 && app.wintile.width > 1) { + } else if (app.wintile.col + app.wintile.width - 1 === colCount - 1 && app.wintile.width > 1) { // We are not yet to smallest width, so shrink - _log('right - 2'); + _log('sendMove) right - 2'); moveApp(app, {'row': app.wintile.row, 'col': app.wintile.col + 1, 'height': app.wintile.height, 'width': app.wintile.width - 1}); } else if (monitorToRight !== -1) { // There is a monitor to the right, so let's go there - _log('right - 3'); + _log('sendMove) right - 3'); app.move_to_monitor(monitorToRight); moveApp(app, {'row': app.wintile.row, 'col': 0, 'height': app.wintile.height, 'width': 1}); } else { // We are already on the left, and there is no other monitor to the right // Move to the right most column at full height - _log('right - 4'); - moveApp(app, {'row': 0, 'col': 3, 'height': 2, 'width': 1}); + _log('sendMove) right - 4'); + moveApp(app, {'row': 0, 'col': colCount - 1, 'height': config.rows, 'width': 1}); } break; case 'up': - _log('up'); - if (app.wintile.height === 2 && app.wintile.width === 2 && app.wintile.col === 1) { + _log('sendMove) up'); + if (app.wintile.height === config.rows && app.wintile.width === 2 && app.wintile.col === 1) { // We are in 1st maximize, go to full maximize - _log('up - 1'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 4}); - } else if (app.wintile.height === 2) { + _log('sendMove) up - 1'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); + } else if (app.wintile.height === config.rows) { // We are full height on half, go to top while keeping width - _log('up - 2'); + _log('sendMove) up - 2'); moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 1, 'width': app.wintile.width}); } else if (app.wintile.row === 1) { // We are bottom half, go to full height, keeping width - _log('up - 3'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': app.wintile.width}); + _log('sendMove) up - 3'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': app.wintile.width}); } else { // We are top half, go straight to 2nd maximize - _log('up - 4'); - moveApp(app, {'row': 0, 'col': 0, 'height': 2, 'width': 4}); + _log('sendMove) up - 4'); + moveApp(app, {'row': 0, 'col': 0, 'height': config.rows, 'width': colCount}); } break; case 'down': - _log('down'); - if (app.wintile.col === 0 && app.wintile.width === 4 && app.wintile.height === 2) { + _log('sendMove) down'); + if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.height === config.rows) { // We are 2nd maximized, go to 1st maximized - _log('down - 1'); - moveApp(app, {'row': 0, 'col': 1, 'height': 2, 'width': 2}); - } else if (app.wintile.col === 0 && app.wintile.width === 4 && app.wintile.row === 0) { + _log('sendMove) down - 1'); + moveApp(app, {'row': 0, 'col': 1, 'height': config.rows, 'width': 2}); + } else if (app.wintile.col === 0 && app.wintile.width === colCount && app.wintile.row === 0) { // We are top half, go to bottom half - _log('down - 2'); + _log('sendMove) down - 2'); moveApp(app, {'row': 1, 'col': 0, 'height': app.wintile.height, 'width': app.wintile.width}); } else if (app.wintile.col === 1 && app.wintile.width === 2) { // We are 1st maximized, restore - _log('down - 3'); + _log('sendMove) down - 3'); restoreApp(app); - } else if (app.wintile.height === 2) { + } else if (app.wintile.height === config.rows) { // We are full height, go to half height - _log('down - 4'); + _log('sendMove) down - 4'); moveApp(app, {'row': 1, 'col': app.wintile.col, 'height': 1, 'width': app.wintile.width}); } else if (app.wintile.row === 0) { // We are top half, go to full height - _log('down - 5'); - moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': 2, 'width': app.wintile.width}); - } else if (app.wintile.width !== 4) { + _log('sendMove) down - 5'); + moveApp(app, {'row': 0, 'col': app.wintile.col, 'height': config.rows, 'width': app.wintile.width}); + } else if (app.wintile.width !== colCount) { // We are not full bottom but are a tile, go full width - _log('down - 6'); - moveApp(app, {'row': 1, 'col': 0, 'height': 1, 'width': 4}); + _log('sendMove) down - 6'); + moveApp(app, {'row': 1, 'col': 0, 'height': 1, 'width': colCount}); } else { // We are bottom half, minimize - _log('down - 7'); + _log('sendMove) down - 7'); requestMinimize(app); } break; @@ -718,42 +728,48 @@ function checkForMove(x, y, app) { } } +/** + * + * @param {object} mask - the mouse event mask from metaGrabOp + * + */ +function isResize(mask) { + let resizes = [Meta.GrabOp.RESIZING_NW, + Meta.GrabOp.RESIZING_N, + Meta.GrabOp.RESIZING_NE, + Meta.GrabOp.RESIZING_E, + Meta.GrabOp.RESIZING_SW, + Meta.GrabOp.RESIZING_S, + Meta.GrabOp.RESIZING_SE, + Meta.GrabOp.RESIZING_W]; + + const resize = resizes.some(value => mask === value); + _log(`isResize) mask: ${mask} resize: ${resize}`); + return resize; +} + + /** * * @param {object} metaWindow - window object * @param {object} metaGrabOp - type of window being grabbed */ function windowGrabBegin(metaWindow, metaGrabOp) { - _log('windowGrabBegin'); let [mouseX, mouseY] = global.get_pointer(); + if (isResize(metaGrabOp)) + return false; + var app = global.display.focus_window; let window = app.get_frame_rect(); - var leeway = 10; - _log(`grabBegin) mouse - mouseX:${mouseX} mouseY:${mouseY}`); - _log(`grabBegin) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); - var output = ''; - if (mouseY > window.y - leeway && mouseY < window.y + leeway) - output += 'top '; - - if (mouseY > window.y + window.height - leeway && mouseY < window.y + window.height + leeway) - output += 'bottom '; - - if (mouseX > window.x - leeway && mouseX < window.x + leeway) - output += 'left '; + _log(`windowGrabBegin) mouse - mouseX:${mouseX} mouseY:${mouseY}`); + _log(`windowGrabBegin) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); - if (mouseX > window.x + window.width - leeway && mouseX < window.x + window.width + leeway) - output += 'right '; - - if (output) { - _log(`grabBegin) Mouse is on the ${output}side. Ignoring`); - return; - } if (metaWindow && metaGrabOp !== Meta.GrabOp.WAYLAND_POPUP) { windowMoving = true; if (app.wintile) { window = app.wintile.origFrame; - _log(`grabBegin) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + _log(`windowGrabBegin) origFrame - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); checkForMove(mouseX, mouseY, app); } if (metaWindow.resizeable && config.preview.enabled) { @@ -771,7 +787,7 @@ function windowGrabBegin(metaWindow, metaGrabOp) { * @param {object} metaGrabOp - another window object */ function windowGrabEnd(metaWindow, metaGrabOp) { - _log('windowGrabEnd'); + _log('windowGrabEnd)'); if (metaWindow && metaGrabOp !== Meta.GrabOp.WAYLAND_POPUP) { windowMoving = false; if (metaWindow.resizeable && config.preview.enabled) { @@ -833,12 +849,12 @@ function isClose(a, b, distance = config.preview.distance) { /** * * @param {object} loc = { col, row, width, height } - * @param {number} _x - The x-coordinate of the preview. - * @param {number} _y - The y-coordinate of the preview. - * @param {number} _w - The width of the preview. - * @param {number} _h - The height of the preview. + * @param {number} spaceX - starting x of the screen + * @param {number} spaceY - starting y of the screen + * @param {number} colWidth - single col width + * @param {number} rowHeight - single row height */ -function showPreview(loc, _x, _y, _w, _h) { +function showPreview(loc, spaceX, spaceY, colWidth, rowHeight) { if (preview.loc && JSON.stringify(preview.loc) === JSON.stringify(loc)) return; @@ -852,10 +868,10 @@ function showPreview(loc, _x, _y, _w, _h) { opacity: 255, visible: true, transition: Clutter.AnimationMode.EASE_OUT_QUAD, - x: _x, - y: _y, - width: _w, - height: _h, + x: spaceX + (colWidth * loc.col) + Math.floor(config.gap / 2), + y: spaceY + (rowHeight * loc.row) + Math.floor(config.gap / 2), + width: colWidth * loc.width - config.gap, + height: rowHeight * loc.height - config.gap, }); } @@ -876,223 +892,224 @@ function hidePreview() { * @param {object} app the window object */ function checkIfNearGrid(app) { - _log('checkIfNearGrid'); - if (windowMoving) { - let [mouseX, mouseY] = global.get_pointer(); - var close = false; - var curMonitor = getCurrentMonitor(); - var monitor = Main.layoutManager.monitors[curMonitor]; - var space = getActiveWorkspace().get_work_area_for_monitor(curMonitor); - const isNotUltrawide = (space.width / space.height) < 1.9; - _log(`checkIfNearGrid) isNotUltrawide: ${isNotUltrawide}`); + _log('checkIfNearGrid)'); + if (!windowMoving) + return; - var colCount = config.ultrawideOnly && isNotUltrawide ? 2 : config.cols; - var colWidth = Math.floor(space.width / colCount); + let [mouseX, mouseY] = global.get_pointer(); + var close = false; + var curMonitor = getCurrentMonitor(); + var monitor = Main.layoutManager.monitors[curMonitor]; + var space = getActiveWorkspace().get_work_area_for_monitor(curMonitor); + const isNotUltrawide = (space.width / space.height) < 1.9; + _log(`checkIfNearGrid) isNotUltrawide: ${isNotUltrawide}`); - var rowHeight = Math.floor(space.height / 2); - var inMonitorBounds = false; - if (mouseX >= monitor.x && mouseX < monitor.x + monitor.width && mouseY >= monitor.y && mouseY < monitor.y + monitor.width) - inMonitorBounds = true; + var colCount = config.ultrawideOnly && isNotUltrawide ? 2 : config.cols; + var colWidth = Math.floor(space.width / colCount); - let window = app.get_frame_rect(); - _log(`mouse - mouseX:${mouseX} mouseY:${mouseY}`); - _log(`monitor - x:${monitor.x} y:${monitor.y} w:${monitor.width} h:${monitor.height} inB:${inMonitorBounds}`); - _log(`space - x:${space.x} y:${space.y} w:${space.width} h:${space.height}`); - _log(`window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); - if (inMonitorBounds) { - for (var i = 0; i < colCount; i++) { - var gridX = i * colWidth + space.x; - var inGrid = mouseX > gridX && mouseX < gridX + colWidth; - var centerOfGrid = mouseX > Math.floor(gridX + colWidth / 3) && mouseX < Math.floor(gridX + colWidth - (colWidth / 3)); - var topRow = space.y < mouseY && mouseY < space.y + rowHeight; - var bottomRow = mouseY > space.y + rowHeight; - var nearTop = isClose(mouseY, space.y) || mouseY < space.y; - var nearBottom = isClose(mouseY, space.y + space.height) || mouseY > space.y + space.height; - var nearLeft = isClose(mouseX, space.x) || mouseX < space.x; - var nearRight = isClose(mouseX, space.x + space.width) || mouseX > space.x + space.width; - - var centerHorizontalLeft = Math.floor(space.x + (space.width / 2) - (colWidth / 5)); - var centerHorizontalRight = Math.floor(space.x + (space.width / 2) + (colWidth / 5)); - var nearCenterH = centerHorizontalLeft < mouseX && mouseX < centerHorizontalRight; - - var centerVerticalTop = Math.floor(space.height / 2 + space.y - rowHeight / 2); - var centerVerticalBottom = Math.floor(space.height / 2 + space.y + rowHeight / 2); - var nearCenterV = centerVerticalTop < mouseY && mouseY < centerVerticalBottom; - - if (nearTop && nearCenterH) { - // If we are in the center top, show a preview for maximize + var rowHeight = Math.floor(space.height / config.rows); + var inMonitorBounds = false; + if (mouseX >= monitor.x && mouseX < monitor.x + monitor.width && mouseY >= monitor.y && mouseY < monitor.y + monitor.width) + inMonitorBounds = true; + + let window = app.get_frame_rect(); + _log(`checkIfNearGrid) mouse - mouseX:${mouseX} mouseY:${mouseY}`); + _log(`checkIfNearGrid) monitor - x:${monitor.x} y:${monitor.y} w:${monitor.width} h:${monitor.height} inB:${inMonitorBounds}`); + _log(`checkIfNearGrid) space - x:${space.x} y:${space.y} w:${space.width} h:${space.height}`); + _log(`checkIfNearGrid) window - x:${window.x} y:${window.y} w:${window.width} h:${window.height}`); + if (inMonitorBounds) { + for (var c = 0; c < colCount; c++) { + var gridX = c * colWidth + space.x; + var inGrid = mouseX > gridX && mouseX < gridX + colWidth; + var centerOfGrid = mouseX > Math.floor(gridX + colWidth / 3) && mouseX < Math.floor(gridX + (2 * colWidth / 3)); + var topRow = mouseY < space.y + rowHeight; + var bottomRow = mouseY > space.y + space.height - rowHeight; + var nearTop = isClose(mouseY, space.y) || mouseY < space.y; + var nearBottom = isClose(mouseY, space.y + space.height) || mouseY > space.y + space.height; + var nearLeft = isClose(mouseX, space.x) || mouseX < space.x; + var nearRight = isClose(mouseX, space.x + space.width) || mouseX > space.x + space.width; + + var centerOfScreen = space.x + Math.floor(space.width / 2); + var columnWidthFraction = Math.floor(colWidth / 5); + var nearCenterH = mouseX > centerOfScreen - (columnWidthFraction / 2) && mouseX < centerOfScreen + (columnWidthFraction / 2); + + var centerVerticalTop = Math.floor(space.height / 2 + space.y - rowHeight / 2); + var centerVerticalBottom = Math.floor(space.height / 2 + space.y + rowHeight / 2); + var nearCenterV = centerVerticalTop < mouseY && mouseY < centerVerticalBottom; + + if (nearTop && nearCenterH) { + // If we are in the center top, show a preview for maximize + showPreview({ + col: 0, + row: 0, + width: colCount, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + close = true; + break; + } else if (nearBottom && nearCenterH) { + // If we are in the center bottom, show a preview for bottom maximized horizontally + showPreview({ + col: 0, + row: config.rows - 1, + width: colCount, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + close = true; + break; + } else if (nearLeft && nearCenterV) { + // If we are in the center left, show a preview for left maximize + if (colCount === 4 && config.preview.doubleWidth) { showPreview({ col: 0, row: 0, - width: colCount, - height: 2, - }, space.x, space.y, space.width, space.height); - close = true; - break; - } else if (nearBottom && nearCenterH) { - // If we are in the center bottom, show a preview for bottom maximized horizontally + width: 2, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + } else { showPreview({ col: 0, - row: 1, - width: colCount, + row: 0, + width: 1, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + } + close = true; + break; + } else if (nearRight && nearCenterV) { + // If we are in the center right, show a preview for right maximize + if (colCount === 4 && config.preview.doubleWidth) { + showPreview({ + col: colCount - 2, + row: 0, + width: 2, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + } else { + showPreview({ + col: colCount - 1, + row: 0, + width: 1, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + } + close = true; + break; + } else if (nearLeft && topRow) { + // If we are close to the top left, show the top left grid item + if (colCount === 4 && config.preview.doubleWidth) { + showPreview({ + col: 0, + row: 0, + width: 2, height: 1, - }, space.x, space.y + rowHeight, space.width, rowHeight); - close = true; - break; - } else if (nearLeft && nearCenterV) { - // If we are in the center left, show a preview for left maximize - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: 0, - row: 0, - width: 2, - height: 2, - }, space.x, space.y, colWidth * 2, space.height); - } else { - showPreview({ - col: 0, - row: 0, - width: 1, - height: 2, - }, space.x, space.y, colWidth, space.height); - } - close = true; - break; - } else if (nearRight && nearCenterV) { - // If we are in the center right, show a preview for right maximize - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: colCount - 2, - row: 0, - width: 2, - height: 2, - }, space.x + space.width - colWidth * 2, space.y, colWidth * 2, space.height); - } else { - showPreview({ - col: colCount - 1, - row: 0, - width: 1, - height: 2, - }, space.x + space.width - colWidth, space.y, colWidth, space.height); - } - close = true; - break; - } else if (nearLeft && topRow) { - // If we are close to the top left, show the top left grid item - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: 0, - row: 0, - width: 2, - height: 1, - }, space.x, space.y, colWidth * 2, rowHeight); - } else { - showPreview({ - col: 0, - row: 0, - width: 1, - height: 1, - }, space.x, space.y, colWidth, rowHeight); - } - close = true; - break; - } else if (nearLeft && bottomRow) { - // If we are close to the bottom left, show the bottom left grid item - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: 0, - row: 1, - width: 2, - height: 1, - }, space.x, space.y + rowHeight, colWidth * 2, rowHeight); - } else { - showPreview({ - col: 0, - row: 1, - width: 1, - height: 1, - }, space.x, space.y + rowHeight, colWidth, rowHeight); - } - close = true; - break; - } else if (nearRight && topRow) { - // If we are close to the top right, show the top right grid item - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: colCount - 2, - row: 0, - width: 2, - height: 1, - }, space.x + space.width - colWidth * 2, space.y, colWidth * 2, rowHeight); - } else { - showPreview({ - col: colCount - 1, - row: 0, - width: 1, - height: 1, - }, space.x + space.width - colWidth, space.y, colWidth, rowHeight); - } - close = true; - break; - } else if (nearRight && bottomRow) { - // If we are close to the bottom right, show the bottom right grid item - if (colCount === 4 && config.preview.doubleWidth) { - showPreview({ - col: colCount - 2, - row: 1, - width: 2, - height: 1, - }, space.x + space.width - colWidth * 2, space.y + rowHeight, colWidth * 2, rowHeight); - } else { - showPreview({ - col: colCount - 1, - row: 1, - width: 1, - height: 1, - }, space.x + space.width - colWidth, space.y + rowHeight, colWidth, rowHeight); - } - close = true; - break; - } else if (nearTop && inGrid) { - // If we are close to the top, show a preview for the top grid item + }, space.x, space.y, colWidth, rowHeight); + } else { showPreview({ - col: i, + col: 0, row: 0, width: 1, height: 1, - }, gridX, space.y, colWidth, rowHeight); - close = true; - break; - } else if (nearBottom && centerOfGrid) { - // If we are close to the bottom and in the middle of a grid, show a preview for the bottom grid item at full height + }, space.x, space.y, colWidth, rowHeight); + } + close = true; + break; + } else if (nearLeft && bottomRow) { + // If we are close to the bottom left, show the bottom left grid item + if (colCount === 4 && config.preview.doubleWidth) { + showPreview({ + col: 0, + row: config.rows - 1, + width: 2, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + } else { + showPreview({ + col: 0, + row: config.rows - 1, + width: 1, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + } + close = true; + break; + } else if (nearRight && topRow) { + // If we are close to the top right, show the top right grid item + if (colCount === 4 && config.preview.doubleWidth) { showPreview({ - col: i, + col: colCount - 2, + row: 0, + width: 2, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + } else { + showPreview({ + col: colCount - 1, row: 0, width: 1, - height: 2, - }, gridX, space.y, colWidth, space.height); - close = true; - break; - } else if (nearBottom && inGrid) { - // If we are close to the bottom, show a preview for the bottom grid item + height: 1, + }, space.x, space.y, colWidth, rowHeight); + } + close = true; + break; + } else if (nearRight && bottomRow) { + // If we are close to the bottom right, show the bottom right grid item + if (colCount === 4 && config.preview.doubleWidth) { + showPreview({ + col: colCount - 2, + row: config.rows - 1, + width: 2, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + } else { showPreview({ - col: i, - row: 1, + col: colCount - 1, + row: config.rows - 1, width: 1, height: 1, - }, gridX, space.y + rowHeight, colWidth, rowHeight); - close = true; - break; + }, space.x, space.y, colWidth, rowHeight); } + close = true; + break; + } else if (nearTop && inGrid) { + // If we are close to the top, show a preview for the top grid item + showPreview({ + col: c, + row: 0, + width: 1, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + close = true; + break; + } else if (nearBottom && centerOfGrid) { + // If we are close to the bottom and in the middle of a grid, show a preview for the bottom grid item at full height + showPreview({ + col: c, + row: 0, + width: 1, + height: config.rows, + }, space.x, space.y, colWidth, rowHeight); + close = true; + break; + } else if (nearBottom && inGrid) { + // If we are close to the bottom, show a preview for the bottom grid item + showPreview({ + col: c, + row: config.rows - 1, + width: 1, + height: 1, + }, space.x, space.y, colWidth, rowHeight); + close = true; + break; } } - if (!close) - hidePreview(); - - checkIfNearGridTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, config.preview.delay, () => { - checkIfNearGrid(app); - }); } + if (!close) + hidePreview(); + + checkIfNearGridTimer = GLib.timeout_add(GLib.PRIORITY_DEFAULT, config.preview.delay, () => { + checkIfNearGrid(app); + }); } /** @@ -1119,8 +1136,7 @@ function getCurrentMonitor() { * */ function enable() { - _log('Enable'); - _log('Keymanager is being defined'); + _log('enable) Keymanager is being defined'); keyManager = new KeyBindings.Manager(); let desktopSettings = new Gio.Settings({schema_id: 'org.gnome.desktop.wm.keybindings'}); let mutterKeybindingSettings = new Gio.Settings({schema_id: 'org.gnome.mutter.keybindings'}); @@ -1129,7 +1145,7 @@ function enable() { let shellSettings = new Gio.Settings({schema_id: 'org.gnome.shell.overrides'}); shellSettings.set_boolean('edge-tiling', false); } catch (error) { - _log('org.gnome.shell.overrides does not exist'); + _log('enable) org.gnome.shell.overrides does not exist'); } oldbindings['unmaximize'] = desktopSettings.get_strv('unmaximize'); oldbindings['maximize'] = desktopSettings.get_strv('maximize'); @@ -1177,7 +1193,6 @@ function enable() { }); Main.uiGroup.add_actor(preview); - log(`[WinTile] buildPrefsWidget SHELL_VERSION ${SHELL_VERSION}`); gsettings = ExtensionUtils.getSettings(); updateSettings(); @@ -1189,8 +1204,7 @@ function enable() { * */ function disable() { - _log('Disable'); - _log('Keymanager is being removed'); + _log('disable) Keymanager is being removed'); keyManager.removeAll(); keyManager.destroy(); keyManager = null; @@ -1201,7 +1215,7 @@ function disable() { let shellSettings = new Gio.Settings({schema_id: 'org.gnome.shell.overrides'}); shellSettings.reset('edge-tiling'); } catch (error) { - _log('org.gnome.shell.overrides does not exist'); + _log('disable) org.gnome.shell.overrides does not exist'); } desktopSettings.reset('unmaximize'); desktopSettings.reset('maximize'); diff --git a/metadata.json b/metadata.json index a6a8f3f..2f2ea2d 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "WinTile: Windows 10 window tiling for GNOME", - "description": "WinTile is a hotkey driven window tiling system for GNOME that imitates the standard Win-Arrow keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner across a single or multiple monitors using just Super+Arrow.\n\nAs of v10, WinTile also supports:\n- 2, 3, or 4 columns for standard or ultrawide monitors\n- Top/bottom half support\n- Mouse preview and snapping for placing windows\n- 'Maximize' mode, which adds/removes GNOME animations\n- 'Ultrawide-only' mode, to limit standard screens to 2x2 while allowing ultrawides to still have 3 or 4 columns.", + "description": "WinTile is a hotkey driven window tiling system for GNOME that imitates the standard Win-Arrow keys of Windows 10, allowing you to maximize, maximize to sides, or 1/4 sized to corner across a single or multiple monitors using just Super+Arrow.\n\nAs of v10, WinTile also supports:\n- 2, 3, or 4 columns for standard or ultrawide monitors\n- Top/bottom half support\n- Mouse preview and snapping for placing windows\n- 'Maximize' mode, which adds/removes GNOME animations\n- 'Ultrawide-only' mode, to limit standard screens to 2x2 while allowing ultrawides to still have 3 or 4 columns.\n- Add gaps around tiles to avoid the 'crowded elevator' feeling'.", "uuid": "wintile@nowsci.com", "url": "https://github.com/fmstrat/wintile", "settings-schema":"org.gnome.shell.extensions.wintile", @@ -13,5 +13,5 @@ "43", "44" ], - "version": 11.2 + "version": 12 } diff --git a/prefs.js b/prefs.js index 2c22c71..ad579ea 100644 --- a/prefs.js +++ b/prefs.js @@ -215,6 +215,36 @@ function buildPrefsWidget() { layout.attach(previewDelayLabel, 0, row, 1, 1); layout.attach(previewDelayInput, 1, row++, 1, 1); + // Gap setting + let gapLabel = new Gtk.Label({ + label: _('Gap width around tiles'), + visible: true, + hexpand: true, + halign: Gtk.Align.START, + }); + let gapInput = new Gtk.Box({ + orientation: Gtk.Orientation.HORIZONTAL, + visible: true, + }); + let gapAdjustment = new Gtk.Adjustment({ + lower: 0, + upper: 50, + step_increment: 2, + }); + let gapSettingInt = new Gtk.SpinButton({ + adjustment: gapAdjustment, + snap_to_ticks: true, + visible: true, + }); + gapSettingInt.set_value(gsettings.get_int('gap')); + if (SHELL_VERSION >= 40) + gapInput.append(gapSettingInt); + else + gapInput.add(gapSettingInt); + + layout.attach(gapLabel, 0, row, 1, 1); + layout.attach(gapInput, 1, row++, 1, 1); + // Debug setting let debugLabel = new Gtk.Label({ label: _('Turn on debugging'), @@ -230,23 +260,29 @@ function buildPrefsWidget() { layout.attach(debugLabel, 0, row, 1, 1); layout.attach(debugInput, 1, row++, 1, 1); - gsettings.bind('cols', colsInput, 'active', Gio.SettingsBindFlags.DEFAULT); - gsettings.bind('ultrawide-only', ultrawideOnlyInput, 'active', Gio.SettingsBindFlags.DEFAULT); - gsettings.bind('use-maximize', maximizeInput, 'active', Gio.SettingsBindFlags.DEFAULT); - gsettings.bind('use-minimize', minimizeInput, 'active', Gio.SettingsBindFlags.DEFAULT); - gsettings.bind('preview', previewInput, 'active', Gio.SettingsBindFlags.DEFAULT); - gsettings.bind('double-width', doubleWidthInput, 'active', Gio.SettingsBindFlags.DEFAULT); - colsSettingInt.connect('value-changed', function (entry) { - gsettings.set_int('cols', entry.value); - }); - previewDistanceSettingInt.connect('value-changed', function (entry) { - gsettings.set_int('distance', entry.value); - }); - previewDelaySettingInt.connect('value-changed', function (entry) { - gsettings.set_int('delay', entry.value); - }); - gsettings.bind('debug', debugInput, 'active', Gio.SettingsBindFlags.DEFAULT); + const bindSettings = (key, input) => { + gsettings.bind(key, input, 'active', Gio.SettingsBindFlags.DEFAULT); + }; + + const connectAndSetInt = (setting, key) => { + setting.connect('value-changed', entry => { + gsettings.set_int(key, entry.value); + }); + }; + + // settings that aren't toggles need a connect + connectAndSetInt(colsSettingInt, 'cols'); + connectAndSetInt(previewDistanceSettingInt, 'distance'); + connectAndSetInt(previewDelaySettingInt, 'delay'); + connectAndSetInt(gapSettingInt, 'gap'); + // all other settings need a bind + bindSettings('ultrawide-only', ultrawideOnlyInput); + bindSettings('use-maximize', maximizeInput); + bindSettings('use-minimize', minimizeInput); + bindSettings('preview', previewInput); + bindSettings('double-width', doubleWidthInput); + bindSettings('debug', debugInput); // Return our widget which will be added to the window return layout; diff --git a/schemas/gschemas.compiled b/schemas/gschemas.compiled index 4f4344a1a0a8f5f2887a17a05123dcc3b97ba583..fe4d6ffac1b356f93bd19ee0f6b59c3907288186 100644 GIT binary patch literal 813 zcmYjPJxE(o82xNaqeiM7gm!g$LGvC+K^M`@3QiqFP>>sQNiN*H7v7Ia#1_X69a~qy z(%nUHEaKwe?&uP55ju1#6g}s@_;bneoSb+3-g{rp%DRe;3R4-Jci@d&d#@f%aB)iH z9w)!H<}zFGm);(2Ge$ivALRgiJtTsUL~+A!gi%ZTNmEu##U#6)4@cTAWXs}U0M z#vO?iz{LSxgG<0DFb0$dV3wHuwK_2Z=DmutD>vXiaB_KO=~Iuu{{t@LMLt~Rd1~e- z!85>JX>Xo+>T&oB;6>nn_O(o(x&VI}ya}vi-_Ge%m*6+SE#UX(FJwXW!v~dpk$1`5fGp16h)U{Q;zt|VAGk1$QFRw>g&FX5$ z)YB$@U(9W&HWE+s=J@4#UOU#iMt5kk56Js%g@1J?Ksf?ej=+^8crHgUC`TZYWQne} zOlVqWFE5Lmg9+>f57y(l#z!3n*dKOJG$0(2YC9fyu7y4--Y@$}24IYz0NI z5iBjP5K*`*1WW$`!Ny8Ku<_oT-H;(K@8#_`Z)U%I^GiXZgD8`7jf0m9?eup|aAi#7 z1FLwpXlqvB&wV*sWf}FPe3c*IKYb$jNSrjiW)!!Smu@IyJk`lmlcTsrJ+w< zgZ~qJ0!*D2`P9rm1D^wrQoUh4^$7ec@GWq)w?E9@Q?vda{08Kys<(oUZs{G>Cr-m% zk4=jGTzD)=$pbVT?QA<*yRN&Ls4cD9G}&|Pv&=iPZ$+iU5_UaQCtc0Z|MAT=zNj%KbOUgng9R* diff --git a/schemas/org.gnome.shell.extensions.wintile.gschema.xml b/schemas/org.gnome.shell.extensions.wintile.gschema.xml index a655e10..0e17ac4 100644 --- a/schemas/org.gnome.shell.extensions.wintile.gschema.xml +++ b/schemas/org.gnome.shell.extensions.wintile.gschema.xml @@ -44,6 +44,12 @@ + + 0 + Gap width around tiles + + + false Turn on/off debug output