From 301078a00e2717ee36038fa86eb3d61dba0d65f5 Mon Sep 17 00:00:00 2001 From: Nimaoth Date: Sat, 21 Aug 2021 12:35:47 +0200 Subject: [PATCH] added more logging, fixed some bugs --- .gitignore | 5 +- build.zig | 15 ++- config.json | 4 +- src/layer.zig | 16 +++ src/main.zig | 42 ++++++- src/misc.zig | 2 +- src/monitor.zig | 270 ++++++++++++++++------------------------- src/window_manager.zig | 74 +++++++++-- 8 files changed, 233 insertions(+), 195 deletions(-) diff --git a/.gitignore b/.gitignore index 4144952..1690aa7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ zig-cache -/window_data.json -/dist +window_data.json +dist +.vs log.txt \ No newline at end of file diff --git a/build.zig b/build.zig index 71e3b24..0ee469f 100644 --- a/build.zig +++ b/build.zig @@ -11,24 +11,23 @@ pub fn build(b: *std.build.Builder) void { // between Debug, ReleaseSafe const release = b.option(bool, "release", "Optimizations on and safety on, log to file") orelse false; - const mode = if (release) std.builtin.Mode.ReleaseSafe else std.builtin.Mode.Debug; + var mode = if (release) std.builtin.Mode.ReleaseSafe else std.builtin.Mode.Debug; + mode = .Debug; b.is_release = mode != .Debug; b.release_mode = mode; - const shipping = mode != .Debug; - - const exe = b.addExecutable(if (shipping) "zwtwm" else "zwtwm_debug", "src/main.zig"); - exe.addBuildOption(bool, "RUN_IN_CONSOLE", !shipping); - if (shipping) { + const exe = b.addExecutable(if (release) "zwtwm" else "zwtwm_debug", "src/main.zig"); + exe.addBuildOption(bool, "RUN_IN_CONSOLE", !release); + if (release) { exe.addBuildOption([]const u8, "TRAY_GUID", "99b74174-d3a4-48ba-a886-9af100149755"); } else { exe.addBuildOption([]const u8, "TRAY_GUID", "b3e926bb-e7ee-4f2a-b513-0080167ec220"); } - exe.subsystem = if (shipping) .Windows else .Console; + exe.subsystem = if (release) .Windows else .Console; exe.addPackage(.{ .name = "zigwin32", .path = "./deps/custom_zigwin32/win32.zig" }); exe.setTarget(target); - exe.setBuildMode(if (shipping) .ReleaseSafe else mode); + exe.setBuildMode(mode); exe.install(); // Add config to install. diff --git a/config.json b/config.json index 77152df..12624e2 100644 --- a/config.json +++ b/config.json @@ -45,7 +45,9 @@ "Main HighGUI class", "WindowsForms10.Window.8.app.0.3e799b_r6_ad1", "TSC_POPUP_PARENT_WNDCLASS", - "BBarWindowClass" + "BBarWindowClass", + "TmForever", + "#32770" ], "ignoredTitles": [ diff --git a/src/layer.zig b/src/layer.zig index 7fd0b65..52b79ea 100644 --- a/src/layer.zig +++ b/src/layer.zig @@ -40,6 +40,7 @@ pub const Layer = struct { const Self = @This(); windows: std.ArrayList(Window), + currentWindow: usize = 0, fullscreen: bool = false, options: Options = .{}, @@ -126,6 +127,13 @@ pub const Layer = struct { } } + pub fn getCurrentWindow(self: *Self) ?*Window { + if (self.currentWindow >= self.windows.items.len) { + return null; + } + return &self.windows.items[self.currentWindow]; + } + pub fn getWindowAt(self: *Self, index: usize) ?*Window { if (index >= self.windows.items.len) { return null; @@ -159,6 +167,14 @@ pub const Layer = struct { std.sort.sort(Window, self.windows.items, self, Self.compareWindowIndex); } + pub fn clampCurrentWindowIndex(self: *Self) void { + if (self.windows.items.len == 0) { + self.currentWindow = 0; + } else if (self.currentWindow >= self.windows.items.len) { + self.currentWindow = self.windows.items.len - 1; + } + } + fn compareWindowIndex(context: *Self, a: Window, b: Window) bool { return a.index < b.index; } diff --git a/src/main.zig b/src/main.zig index 6aacce1..4de00d2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -13,7 +13,6 @@ pub const ONLY_USE_HALF_MONITOR = false; pub const TRAY_GUID = Guid.initString(BuildOptions.TRAY_GUID); const LOG_TO_FILE = !BuildOptions.RUN_IN_CONSOLE; -const LOG_FILE_PATH = "log.txt"; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; pub var gWindowManager: WindowManager = undefined; pub var gWindowStringArena: *std.mem.Allocator = undefined; @@ -22,21 +21,56 @@ var gLogFile: ?std.fs.File = undefined; pub const log_level: std.log.Level = switch (std.builtin.mode) { .Debug => .debug, - .ReleaseSafe => .info, + .ReleaseSafe => .debug, .ReleaseFast => .err, .ReleaseSmall => .err, }; pub fn main() anyerror!void { + defer _ = gpa.deinit(); + if (LOG_TO_FILE) { - gLogFile = try std.fs.cwd().createFile(LOG_FILE_PATH, .{}); + const time = @divFloor(std.time.milliTimestamp(), std.time.ms_per_s); + var fileNameBuffer = std.ArrayList(u8).init(&gpa.allocator); + if (std.fmt.format(fileNameBuffer.writer(), "log-{}.txt", .{time})) { + gLogFile = try std.fs.cwd().createFile(fileNameBuffer.items, .{}); + } else |err| { + gLogFile = try std.fs.cwd().createFile("log.txt", .{}); + } } defer if (gLogFile) |logFile| { logFile.close(); }; - defer _ = gpa.deinit(); + zwtwmMain() catch |err| { + std.log.crit("{}", .{err}); + if (gLogFile) |logFile| { + if (@errorReturnTrace()) |trace| { + writeStackTraceToLogFile(logFile.writer(), trace.*); + } + } else { + return err; + } + }; + std.log.notice("Terminating zwtwm", .{}); +} + +fn writeStackTraceToLogFile(writer: anytype, trace: std.builtin.StackTrace) void { + nosuspend { + if (!std.builtin.strip_debug_info) { + const debug_info = std.debug.getSelfDebugInfo() catch |err| { + writer.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}) catch return; + return; + }; + std.debug.writeStackTrace(trace, writer, &gpa.allocator, debug_info, std.debug.detectTTYConfig()) catch |err| { + writer.print("Unable to dump stack trace: {s}\n", .{@errorName(err)}) catch return; + return; + }; + } + } +} +pub fn zwtwmMain() anyerror!void { var windowStringArena = std.heap.ArenaAllocator.init(&gpa.allocator); defer windowStringArena.deinit(); gWindowStringArena = &windowStringArena.allocator; diff --git a/src/misc.zig b/src/misc.zig index 5ed7354..0fd2d4e 100644 --- a/src/misc.zig +++ b/src/misc.zig @@ -172,7 +172,7 @@ pub fn setWindowVisibility(hwnd: HWND, shouldBeVisible: bool) void { } if (shouldBeVisible) { - _ = ShowWindow(hwnd, SW_RESTORE); + _ = ShowWindow(hwnd, SW_SHOW); } else { _ = ShowWindow(hwnd, SW_HIDE); } diff --git a/src/monitor.zig b/src/monitor.zig index 242dcbc..48ce1f8 100644 --- a/src/monitor.zig +++ b/src/monitor.zig @@ -17,7 +17,6 @@ pub const Monitor = struct { layers: std.ArrayList(Layer), currentLayer: usize = 0, - currentWindow: usize = 0, index: usize = 0, hmonitor: HMONITOR, @@ -181,7 +180,7 @@ pub const Monitor = struct { var layer = self.getCurrentLayer(); try layer.addWindow(hwnd, index); if (index) |i| { - self.currentWindow = i; + layer.currentWindow = i; } } @@ -190,25 +189,21 @@ pub const Monitor = struct { return; } - var removedIndex: usize = 0; for (self.layers.items) |*layer, i| { - const k = layer.removeWindow(hwnd); - if (i == self.currentLayer) { - removedIndex = k; - } - } + const removedIndex = layer.removeWindow(hwnd); - if (removedIndex < self.currentWindow) { - self.currentWindow -= 1; + if (removedIndex < layer.currentWindow) { + layer.currentWindow -= 1; + } + layer.clampCurrentWindowIndex(); } - self.clampCurrentWindowIndex(); } pub fn setCurrentWindow(self: *Self, hwnd: HWND) void { const layer = self.getCurrentLayer(); if (layer.getWindowIndex(hwnd)) |index| { - self.currentWindow = index; + layer.currentWindow = index; } } @@ -222,24 +217,15 @@ pub const Monitor = struct { } pub fn getCurrentWindow(self: *Self) ?*Window { - return self.getCurrentLayer().getWindowAt(self.currentWindow); - } - - pub fn clampCurrentWindowIndex(self: *Self) void { - const layer = self.getCurrentLayer(); - if (layer.windows.items.len == 0) { - self.currentWindow = 0; - } else if (self.currentWindow >= layer.windows.items.len) { - self.currentWindow = layer.windows.items.len - 1; - } + return self.getCurrentLayer().getCurrentWindow(); } pub fn selectPrevWindow(self: *Self) void { const layer = self.getCurrentLayer(); if (layer.windows.items.len == 0) { - self.currentWindow = 0; + layer.currentWindow = 0; } else { - self.currentWindow = moveIndex(self.currentWindow, -1, layer.windows.items.len, self.windowManager.config.wrapWindows); + layer.currentWindow = moveIndex(layer.currentWindow, -1, layer.windows.items.len, self.windowManager.config.wrapWindows); } self.focusCurrentWindow(); @@ -250,9 +236,9 @@ pub const Monitor = struct { pub fn selectNextWindow(self: *Self) void { const layer = self.getCurrentLayer(); if (layer.windows.items.len == 0) { - self.currentWindow = 0; + layer.currentWindow = 0; } else { - self.currentWindow = moveIndex(self.currentWindow, 1, layer.windows.items.len, self.windowManager.config.wrapWindows); + layer.currentWindow = moveIndex(layer.currentWindow, 1, layer.windows.items.len, self.windowManager.config.wrapWindows); } self.focusCurrentWindow(); @@ -263,34 +249,39 @@ pub const Monitor = struct { pub fn moveWindowToIndex(self: *Self, srcIndex: usize, dstIndex: usize) void { const layer = self.getCurrentLayer(); layer.moveWindowToIndex(srcIndex, dstIndex); - self.currentWindow = dstIndex; + layer.currentWindow = dstIndex; } pub fn moveCurrentWindowUp(self: *Self) void { const layer = self.getCurrentLayer(); - const dstIndex = moveIndex(self.currentWindow, -1, layer.windows.items.len, self.windowManager.config.wrapWindows); - layer.moveWindowToIndex(self.currentWindow, dstIndex); - self.currentWindow = dstIndex; + const dstIndex = moveIndex(layer.currentWindow, -1, layer.windows.items.len, self.windowManager.config.wrapWindows); + layer.moveWindowToIndex(layer.currentWindow, dstIndex); + layer.currentWindow = dstIndex; } pub fn moveCurrentWindowDown(self: *Self) void { const layer = self.getCurrentLayer(); - const dstIndex = moveIndex(self.currentWindow, 1, layer.windows.items.len, self.windowManager.config.wrapWindows); - layer.moveWindowToIndex(self.currentWindow, dstIndex); - self.currentWindow = dstIndex; + const dstIndex = moveIndex(layer.currentWindow, 1, layer.windows.items.len, self.windowManager.config.wrapWindows); + layer.moveWindowToIndex(layer.currentWindow, dstIndex); + layer.currentWindow = dstIndex; } pub fn moveCurrentWindowToTop(self: *Self) void { - self.moveWindowToIndex(self.currentWindow, 0); + self.moveWindowToIndex(self.getCurrentLayer().currentWindow, 0); } pub fn moveCurrentWindowToIndex(self: *Self, index: usize) void { - self.moveWindowToIndex(self.currentWindow, index); + self.moveWindowToIndex(self.getCurrentLayer().currentWindow, index); } + pub fn bringCurrentWindowToTop(self: *Self) void { + if (self.getCurrentWindow()) |window| { + _ = BringWindowToTop(window.hwnd); + } + } pub fn focusCurrentWindow(self: *Self) void { const layer = self.getCurrentLayer(); - if (layer.getWindowAt(self.currentWindow)) |window| { + if (layer.getWindowAt(layer.currentWindow)) |window| { _ = SetForegroundWindow(window.hwnd); } } @@ -318,144 +309,100 @@ pub const Monitor = struct { const maximizeFullSizeWindows = self.windowManager.config.maximizeFullSizeWindows; const noGapForSingleWindow = self.windowManager.config.noGapForSingleWindow; - var area = RECT{ + const monitorAreaWithGap = RECT{ .left = monitorArea.left + gap, .top = monitorArea.top + gap, .right = monitorArea.right - gap, .bottom = monitorArea.bottom - gap, }; + var area = monitorAreaWithGap; + + const singleWindow = layer.fullscreen or (layer.windows.items.len == 1); const numWindows: i32 = @intCast(i32, layer.windows.items.len); if (numWindows > 0) { - if (layer.fullscreen) { - const window = layer.getWindowAt(self.currentWindow).?; - - if (maximizeFullSizeWindows) { - window.rect = monitorArea; - maximizeWindowOnMonitor(window.hwnd, self.hmonitor) catch {}; - } else { - if (windowHasRect(window.hwnd, self.rect) catch false) { - // Special case: window is in true fullscreen mode (meaning the entire screen, including the task bar). - // In this case we don't want to mess with the window. - window.rect = self.rect; - } else { - if (isWindowMaximized(window.hwnd) catch false) { - std.log.debug("Restoring window because it is maximized: {}", .{window.hwnd}); - _ = ShowWindow(window.hwnd, SW_RESTORE); - } + var currentWindowFullscreen = false; + if (self.getCurrentWindow()) |window| { + currentWindowFullscreen = windowHasRect(window.hwnd, self.rect) catch false; + } - if (noGapForSingleWindow) { - window.rect = monitorArea; - } else { - window.rect = area; - } + var hdwp = BeginDeferWindowPos(@intCast(i32, numWindows)); + if (hdwp == 0) { + return; + } - const visualRect = getRectWithoutBorder(window.hwnd, window.rect); - setWindowRect(window.hwnd, visualRect, .{}) catch { - std.log.err("Failed to set window position of {}", .{window.hwnd}); - }; - } + var x: i32 = area.left; + for (layer.windows.items) |*window, i| { + if (windowHasRect(window.hwnd, self.rect) catch false) { + // Special case: window is in true fullscreen mode (meaning the entire screen, including the task bar). + // In this case we don't want to mess with the window. + window.rect = self.rect; + continue; } - } else { - var hdwp = BeginDeferWindowPos(@intCast(i32, numWindows)); - if (hdwp == 0) { - return; + + if (singleWindow and maximizeFullSizeWindows) { + window.rect = monitorArea; + maximizeWindowOnMonitor(window.hwnd, self.hmonitor) catch {}; + continue; } - var currentWindowFullscreen = false; - if (self.getCurrentWindow()) |window| { - currentWindowFullscreen = windowHasRect(window.hwnd, self.rect) catch false; + if (isWindowMaximized(window.hwnd) catch false) { + std.log.debug("Restoring window because it is maximized: {}", .{window.hwnd}); + _ = ShowWindow(window.hwnd, SW_RESTORE); } - if (layer.windows.items.len == 1) { - // Only one window and we don't want to use a gap - const window = &layer.windows.items[0]; + var windowArea = area; + if (i + 1 < layer.windows.items.len) { + // More windows after this one. + const horizontalOrVertical = if (root.ONLY_USE_HALF_MONITOR) 1 else 0; + if (@mod(i, 2) == horizontalOrVertical) { + const ratio = if (i == 0) splitRatio else 0.5; + const split = @floatToInt(i32, @intToFloat(f64, windowArea.right - windowArea.left) * ratio); - if (maximizeFullSizeWindows) { - window.rect = monitorArea; - maximizeWindowOnMonitor(window.hwnd, self.hmonitor) catch {}; + area.left += split + gap; + windowArea.right = windowArea.left + split; } else { - // Unmaximize the window. - if (isWindowMaximized(window.hwnd) catch false) { - std.log.debug("Restoring window because it is maximized: {}", .{window.hwnd}); - _ = ShowWindow(window.hwnd, SW_RESTORE); - } - - if (noGapForSingleWindow) { - window.rect = monitorArea; - } else { - window.rect = area; - } + const ratio = if (i == 0) splitRatio else 0.5; + const split = @floatToInt(i32, @intToFloat(f64, windowArea.bottom - windowArea.top) * ratio); - const visualRect = getRectWithoutBorder(window.hwnd, window.rect); - setWindowRect(window.hwnd, visualRect, .{}) catch { - std.log.err("Failed to set window position of {}", .{window.hwnd}); - }; + area.top += split + gap; + windowArea.bottom = windowArea.top + split; } - } else { - var x: i32 = area.left; - for (layer.windows.items) |*window, i| { - if (windowHasRect(window.hwnd, self.rect) catch false) { - // Window is true fullscreen, don't mess with it. - window.rect = self.rect; - continue; - } - - if (isWindowMaximized(window.hwnd) catch false) { - std.log.debug("Restoring window because it is maximized: {}", .{window.hwnd}); - _ = ShowWindow(window.hwnd, SW_RESTORE); - } + } - var windowArea = area; - if (i + 1 < layer.windows.items.len) { - // More windows after this one. - const horizontalOrVertical = if (root.ONLY_USE_HALF_MONITOR) 1 else 0; - if (@mod(i, 2) == horizontalOrVertical) { - const ratio = if (i == 0) splitRatio else 0.5; - const split = @floatToInt(i32, @intToFloat(f64, windowArea.right - windowArea.left) * ratio); - - area.left += split + gap; - windowArea.right = windowArea.left + split; - } else { - const ratio = if (i == 0) splitRatio else 0.5; - const split = @floatToInt(i32, @intToFloat(f64, windowArea.bottom - windowArea.top) * ratio); - - area.top += split + gap; - windowArea.bottom = windowArea.top + split; - } - } + if (singleWindow) { + windowArea = if (noGapForSingleWindow) monitorArea else monitorAreaWithGap; + } - window.rect = windowArea; - - const visualRect = getRectWithoutBorder(window.hwnd, window.rect); - hdwp = DeferWindowPos( - hdwp, - window.hwnd, - null, - visualRect.left, - visualRect.top, - visualRect.right - visualRect.left, - visualRect.bottom - visualRect.top, - SET_WINDOW_POS_FLAGS.initFlags(.{ - .NOOWNERZORDER = 1, - .SHOWWINDOW = if (!currentWindowFullscreen) 1 else 0, - .NOACTIVATE = if (currentWindowFullscreen) 1 else 0, - .NOZORDER = if (currentWindowFullscreen) 1 else 0, - }), - ); - - if (hdwp == 0) { - return; - } - } + window.rect = windowArea; + + const visualRect = getRectWithoutBorder(window.hwnd, window.rect); + hdwp = DeferWindowPos( + hdwp, + window.hwnd, + null, + visualRect.left, + visualRect.top, + visualRect.right - visualRect.left, + visualRect.bottom - visualRect.top, + SET_WINDOW_POS_FLAGS.initFlags(.{ + .NOOWNERZORDER = 1, + .SHOWWINDOW = if ((i == layer.currentWindow) or (!singleWindow and !currentWindowFullscreen)) 1 else 0, + .NOACTIVATE = if ((i == layer.currentWindow) or (!singleWindow and !currentWindowFullscreen)) 0 else 1, + .NOZORDER = if ((i == layer.currentWindow) or (!singleWindow and !currentWindowFullscreen)) 0 else 1, + }), + ); - _ = EndDeferWindowPos(hdwp); + if (hdwp == 0) { + return; } } - for (layer.windows.items) |*window| { - _ = InvalidateRect(window.hwnd, null, 1); - } + _ = EndDeferWindowPos(hdwp); + } + + for (layer.windows.items) |*window| { + _ = InvalidateRect(window.hwnd, null, 1); } if (root.LOG_LAYERS) { @@ -509,7 +456,7 @@ pub const Monitor = struct { for (layer.windows.items) |*window, windowIndex| { const winRect = if (convertToClient) screenToClient(self.overlayWindow, window.rect) else window.rect; - if (windowIndex == self.currentWindow) { + if (windowIndex == layer.currentWindow) { var brush = brushUnfocused; var thickness = config.windowUnfocusedBorder.thickness; @@ -562,13 +509,14 @@ pub const Monitor = struct { var fromLayer = self.getCurrentLayer(); var toLayer = self.getLayer(@intCast(usize, newLayer)); - if (fromLayer.getWindowAt(self.currentWindow)) |window| { + if (fromLayer.getWindowAt(fromLayer.currentWindow)) |window| { toLayer.addWindow(window.hwnd, null) catch unreachable; _ = fromLayer.removeWindow(window.hwnd); setWindowVisibility(window.hwnd, false); } - self.clampCurrentWindowIndex(); + fromLayer.clampCurrentWindowIndex(); + toLayer.clampCurrentWindowIndex(); self.focusCurrentWindow(); self.layoutWindows(); self.rerenderOverlay(); @@ -586,7 +534,7 @@ pub const Monitor = struct { var layer = self.getCurrentLayer(); var toLayer = self.getLayer(dstIndex); - if (layer.getWindowAt(self.currentWindow)) |window| { + if (layer.getWindowAt(layer.currentWindow)) |window| { if (toLayer.containsWindow(window.hwnd)) { _ = toLayer.removeWindow(window.hwnd); } else { @@ -595,7 +543,7 @@ pub const Monitor = struct { } } - pub fn switchLayer(self: *Self, dstIndex: usize, partOfBatch: bool) void { + pub fn switchLayer(self: *Self, dstIndex: usize, windowsToHide: *std.ArrayList(*Window)) void { const newLayer = dstIndex; if (newLayer == self.currentLayer) return; @@ -613,23 +561,11 @@ pub const Monitor = struct { } self.currentLayer = dstIndex; - self.currentWindow = 0; - - if (!partOfBatch) { - self.focusCurrentWindow(); - self.layoutWindows(); - self.rerenderOverlay(); - - // Just for aesthetics, so the above windows will be show before - // the other windows get hidden, which prevents a short flicker. - // @todo: is there a better way to do this? - Sleep(30); - } // Hide windows in the current layer except ones that are also on the target layer. for (fromLayer.windows.items) |*window| { if (!toLayer.containsWindow(window.hwnd)) { - setWindowVisibility(window.hwnd, false); + windowsToHide.append(window) catch {}; } } } diff --git a/src/window_manager.zig b/src/window_manager.zig index 6aa5ca5..1eb764a 100644 --- a/src/window_manager.zig +++ b/src/window_manager.zig @@ -455,7 +455,7 @@ pub const WindowManager = struct { std.log.err("Failed to manage window {}:{s}: '{s}'", .{ hwnd, className.value, windowTitle.value }); return; }; - monitor.currentWindow = 0; + monitor.getCurrentLayer().currentWindow = 0; monitor.layoutWindows(); self.rerenderOverlay(); } @@ -1267,12 +1267,14 @@ pub const WindowManager = struct { } fn cmdIncreaseGap(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdIncreaseGap: {}", .{args}); self.config.gap += @intCast(i32, args.intParam); self.layoutWindowsOnAllMonitors(); self.rerenderOverlay(); } fn cmdDecreaseGap(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdDecreaseGap: {}", .{args}); self.config.gap -= @intCast(i32, args.intParam); if (self.config.gap < 0) { self.config.gap = 0; @@ -1282,6 +1284,7 @@ pub const WindowManager = struct { } fn cmdIncreaseSplit(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdIncreaseSplit: {}", .{args}); self.config.splitRatio += args.floatParam; if (self.config.splitRatio > 0.9) { self.config.splitRatio = 0.9; @@ -1291,6 +1294,7 @@ pub const WindowManager = struct { } fn cmdDecreaseSplit(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdDecreaseSplit: {}", .{args}); self.config.splitRatio -= args.floatParam; if (self.config.splitRatio < 0.1) { self.config.splitRatio = 0.1; @@ -1300,30 +1304,66 @@ pub const WindowManager = struct { } fn cmdMoveCurrentWindowToLayer(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveCurrentWindowToLayer: {}", .{args}); self.getCurrentMonitor().moveCurrentWindowToLayer(args.usizeParam); } fn cmdToggleCurrentWindowOnLayer(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdToggleCurrentWindowOnLayer: {}", .{args}); self.getCurrentMonitor().toggleCurrentWindowOnLayer(args.usizeParam); } fn cmdSwitchLayer(self: *Self, args: HotkeyArgs) void { - std.log.info("cmdSwitchLayer({}, {})", .{ args.usizeParam, args.boolParam }); + std.log.debug("cmdSwitchLayer: {}", .{args}); if (args.boolParam) { + var windowsToHide = std.ArrayList(*Window).init(self.allocator); + defer windowsToHide.deinit(); + for (self.monitors.items) |*monitor| { - monitor.switchLayer(args.usizeParam, true); + monitor.switchLayer(args.usizeParam, &windowsToHide); } - self.focusCurrentWindow(); self.layoutWindowsOnAllMonitors(); + + for (self.monitors.items) |*monitor| { + monitor.bringCurrentWindowToTop(); + } + self.rerenderOverlay(); + + // Just for aesthetics, so the above windows will be show before + // the other windows get hidden, which prevents a short flicker. + // @todo: is there a better way to do this? + Sleep(15); + + // Hide windows in the current layer except ones that are also on the target layer. + for (windowsToHide.items) |window| { + setWindowVisibility(window.hwnd, false); + } } else { - self.getCurrentMonitor().switchLayer(args.usizeParam, false); + var windowsToHide = std.ArrayList(*Window).init(self.allocator); + defer windowsToHide.deinit(); + + self.getCurrentMonitor().switchLayer(args.usizeParam, &windowsToHide); + self.focusCurrentWindow(); + self.layoutWindows(); + self.getCurrentMonitor().bringCurrentWindowToTop(); + self.rerenderOverlay(); + + // Just for aesthetics, so the above windows will be show before + // the other windows get hidden, which prevents a short flicker. + // @todo: is there a better way to do this? + Sleep(15); + + // Hide windows in the current layer except ones that are also on the target layer. + for (windowsToHide.items) |window| { + setWindowVisibility(window.hwnd, false); + } } } fn cmdLayerCommand(self: *Self, args: HotkeyArgs) void { - std.log.info("Layer command", .{}); + std.log.debug("cmdLayerCommand: {}", .{args}); switch (self.currentCommand) { .None => self.cmdSwitchLayer(args), .ToggleWindowOnLayer => self.cmdToggleCurrentWindowOnLayer(args), @@ -1333,17 +1373,17 @@ pub const WindowManager = struct { } fn cmdMoveNextWindowToLayer(self: *Self, args: HotkeyArgs) void { - std.log.info("Move next window to layer", .{}); + std.log.debug("cmdMoveNextWindowToLayer: {}", .{args}); self.nextCommand = .MoveWindowToLayer; } fn cmdToggleNextWindowOnLayer(self: *Self, args: HotkeyArgs) void { - std.log.info("Toggle next window on layer", .{}); + std.log.debug("cmdToggleNextWindowOnLayer: {}", .{args}); self.nextCommand = .ToggleWindowOnLayer; } fn cmdGoToPrevMonitor(self: *Self, args: HotkeyArgs) void { - std.log.info("cmdGoToPrevMonitor", .{}); + std.log.debug("cmdGoToPrevMonitor: {}", .{args}); if (self.monitors.items.len < 2) { // Only zero/one monitor, nothing to do. return; @@ -1354,7 +1394,7 @@ pub const WindowManager = struct { } fn cmdGoToNextMonitor(self: *Self, args: HotkeyArgs) void { - std.log.info("cmdGoToNextMonitor", .{}); + std.log.debug("cmdGoToNextMonitor: {}", .{args}); if (self.monitors.items.len < 2) { // Only zero/one monitor, nothing to do. return; @@ -1365,6 +1405,7 @@ pub const WindowManager = struct { } fn cmdMoveWindowToPrevMonitor(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveWindowToPrevMonitor: {}", .{args}); if (self.monitors.items.len < 2) { // Only zero/one monitor, nothing to do. return; @@ -1378,7 +1419,7 @@ pub const WindowManager = struct { if (srcMonitor.getCurrentWindow()) |window| { self.moveWindowToMonitor(window.hwnd, srcMonitor, dstMonitor, 0); - dstMonitor.currentWindow = 0; + dstMonitor.getCurrentLayer().currentWindow = 0; } self.setCurrentMonitor(dstMonitor.hmonitor); @@ -1389,6 +1430,7 @@ pub const WindowManager = struct { } fn cmdMoveWindowToNextMonitor(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveWindowToNextMonitor: {}", .{args}); if (self.monitors.items.len < 2) { // Only zero/one monitor, nothing to do. return; @@ -1402,7 +1444,7 @@ pub const WindowManager = struct { if (srcMonitor.getCurrentWindow()) |window| { self.moveWindowToMonitor(window.hwnd, srcMonitor, dstMonitor, 0); - dstMonitor.currentWindow = 0; + dstMonitor.getCurrentLayer().currentWindow = 0; } self.setCurrentMonitor(dstMonitor.hmonitor); @@ -1413,10 +1455,12 @@ pub const WindowManager = struct { } fn cmdToggleWindowFullscreen(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdToggleWindowFullscreen: {}", .{args}); self.getCurrentMonitor().toggleWindowFullscreen(); } fn cmdToggleForegroundWindowManaged(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdToggleForegroundWindowManaged: {}", .{args}); const hwnd = GetForegroundWindow(); if (self.isWindowManaged(hwnd)) { self.removeManagedWindow(hwnd); @@ -1431,14 +1475,17 @@ pub const WindowManager = struct { } fn cmdSelectPrevWindow(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdSelectPrevWindow: {}", .{args}); self.getCurrentMonitor().selectPrevWindow(); } fn cmdSelectNextWindow(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdSelectNextWindow: {}", .{args}); self.getCurrentMonitor().selectNextWindow(); } fn cmdMoveCurrentWindowToTop(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveCurrentWindowToTop: {}", .{args}); self.getCurrentMonitor().moveCurrentWindowToTop(); self.focusCurrentWindow(); self.layoutWindows(); @@ -1446,6 +1493,7 @@ pub const WindowManager = struct { } fn cmdMoveWindowUp(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveWindowUp: {}", .{args}); self.getCurrentMonitor().moveCurrentWindowUp(); self.focusCurrentWindow(); self.layoutWindows(); @@ -1453,6 +1501,7 @@ pub const WindowManager = struct { } fn cmdMoveWindowDown(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdMoveWindowDown: {}", .{args}); self.getCurrentMonitor().moveCurrentWindowDown(); self.focusCurrentWindow(); self.layoutWindows(); @@ -1460,6 +1509,7 @@ pub const WindowManager = struct { } fn cmdPrintForegroundWindowInfo(self: *Self, args: HotkeyArgs) void { + std.log.debug("cmdPrintForegroundWindowInfo: {}", .{args}); const hwnd = GetForegroundWindow(); var className = getWindowString(hwnd, GetClassNameA, .{}, root.gWindowStringArena) catch return; defer className.deinit();