hs.window.animationDuration = 0 hs.window.setShadows(false) local hyper = { "ctrl", "alt", "cmd" } -- move window to next screen hs.hotkey.bind(hyper, "N", function() local win = hs.window.focusedWindow() win:moveToScreen(win:screen():next()) end) local wm = { sizes = { 1 / 2, 2 / 3, 1 / 3 }, fullScreenSizes = { 1, 3 / 4, 1 / 2 }, } function wm:_nextStep(dim, offs, cb) if hs.window.focusedWindow() then local axis = dim == "w" and "x" or "y" local oppDim = dim == "w" and "h" or "w" local oppAxis = dim == "w" and "y" or "x" local win = hs.window.frontmostWindow() local id = win:id() local screen = win:screen() local cell = hs.grid.get(win, screen) local nextSize = self.sizes[1] for i = 1, #self.sizes do if cell[dim] == self.GRID[dim] * self.sizes[i] and (cell[axis] + (offs and cell[dim] or 0)) == (offs and self.GRID[dim] or 0) then nextSize = self.sizes[(i % #self.sizes) + 1] break end end cb(cell, nextSize) if cell[oppAxis] ~= 0 and cell[oppAxis] + cell[oppDim] ~= self.GRID[oppDim] then cell[oppDim] = self.GRID[oppDim] cell[oppAxis] = 0 end hs.grid.set(win, cell, screen) end end function wm:_nextFullScreenStep() if hs.window.focusedWindow() then local win = hs.window.frontmostWindow() local id = win:id() local screen = win:screen() local cell = hs.grid.get(win, screen) local nextSize = self.fullScreenSizes[1] for i = 1, #self.fullScreenSizes do if cell.w == self.GRID.w * self.fullScreenSizes[i] and cell.h == self.GRID.h * self.fullScreenSizes[i] and cell.x == (self.GRID.w - self.GRID.w * self.fullScreenSizes[i]) / 2 and cell.y == (self.GRID.h - self.GRID.h * self.fullScreenSizes[i]) / 2 then nextSize = self.fullScreenSizes[(i % #self.fullScreenSizes) + 1] break end end cell.w = self.GRID.w * nextSize cell.h = self.GRID.h * nextSize cell.x = (self.GRID.w - self.GRID.w * nextSize) / 2 cell.y = (self.GRID.h - self.GRID.h * nextSize) / 2 hs.grid.set(win, cell, screen) end end function wm:_fullDimension(dim) if hs.window.focusedWindow() then local win = hs.window.frontmostWindow() local id = win:id() local screen = win:screen() local cell = hs.grid.get(win, screen) if dim == "x" then cell = "0,0 " .. self.GRID.w .. "x" .. self.GRID.h else cell[dim] = self.GRID[dim] cell[dim == "w" and "x" or "y"] = 0 end hs.grid.set(win, cell, screen) end end function wm:init() self._pressed = { up = false, down = false, left = false, right = false, } self.GRID = { w = 24, h = 24 } hs.grid.setGrid(self.GRID.w .. "x" .. self.GRID.h) hs.grid.MARGINX = 0 hs.grid.MARGINY = 0 hs.hotkey.bind(hyper, "down", function() self._pressed.down = true if self._pressed.up then self:_fullDimension("h") else self:_nextStep("h", true, function(cell, nextSize) cell.y = self.GRID.h - self.GRID.h * nextSize cell.h = self.GRID.h * nextSize end) end end, function() self._pressed.down = false end) hs.hotkey.bind(hyper, "right", function() self._pressed.right = true if self._pressed.left then self:_fullDimension("w") else self:_nextStep("w", true, function(cell, nextSize) cell.x = self.GRID.w - self.GRID.w * nextSize cell.w = self.GRID.w * nextSize end) end end, function() self._pressed.right = false end) hs.hotkey.bind(hyper, "left", function() self._pressed.left = true if self._pressed.right then self:_fullDimension("w") else self:_nextStep("w", false, function(cell, nextSize) cell.x = 0 cell.w = self.GRID.w * nextSize end) end end, function() self._pressed.left = false end) hs.hotkey.bind(hyper, "up", function() self._pressed.up = true if self._pressed.down then self:_fullDimension("h") else self:_nextStep("h", false, function(cell, nextSize) cell.y = 0 cell.h = self.GRID.h * nextSize end) end end, function() self._pressed.up = false end) hs.hotkey.bind(hyper, "m", function() self:_nextFullScreenStep() end) end wm:init() hs.notify.show("Welcome to Hammerspoon", "Have fun!", "")