diff --git a/build.zig b/build.zig index 86bc076..58b92d0 100644 --- a/build.zig +++ b/build.zig @@ -318,16 +318,13 @@ pub fn build_exe( const renderer_mod = blk: { if (gui) switch (target.result.os.tag) { .windows => { - const direct2d_dep = b.lazyDependency("direct2d", .{}) orelse break :blk tui_renderer_mod; - - const win32_dep = direct2d_dep.builder.dependency("win32", .{}); - const win32_mod = win32_dep.module("zigwin32"); + const win32_dep = b.lazyDependency("win32", .{}) orelse break :blk tui_renderer_mod; + const win32_mod = win32_dep.module("win32"); const gui_mod = b.createModule(.{ .root_source_file = b.path("src/win32/gui.zig"), .imports = &.{ .{ .name = "build_options", .module = options_mod }, .{ .name = "win32", .module = win32_mod }, - .{ .name = "ddui", .module = direct2d_dep.module("ddui") }, .{ .name = "cbor", .module = cbor_mod }, .{ .name = "thespian", .module = thespian_mod }, .{ .name = "input", .module = input_mod }, diff --git a/build.zig.zon b/build.zig.zon index 6e5cfb0..d04bd53 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -37,9 +37,9 @@ .url = "https://github.com/rockorager/zeit/archive/9cca8ec620a54c3b07cd249f25e5bcb3153d03d7.tar.gz", .hash = "1220755ea2a5aa6bb3713437aaafefd44812169fe43f1da755c3ee6101b85940f441", }, - .direct2d = .{ - .url = "https://github.com/marler8997/direct2d-zig/archive/0d031389a26653bb71f81c2340d1b8ba6bd339c3.tar.gz", - .hash = "122069b40656962c6ba9b9b3f9f882ba2e9cf4c5e1afebac7b7501404129e6bb4705", + .win32 = .{ + .url = "https://github.com/marlersoft/zigwin32/archive/259b6f353a48968d7e3171573db4fd898b046188.tar.gz", + .hash = "1220925614447b54ccc9894bbba8b202c6a8b750267890edab7732064867e46f3217", .lazy = true, }, }, diff --git a/src/renderer/win32/renderer.zig b/src/renderer/win32/renderer.zig index ac0f899..6c63388 100644 --- a/src/renderer/win32/renderer.zig +++ b/src/renderer/win32/renderer.zig @@ -19,6 +19,8 @@ const gui = @import("gui"); const DropWriter = gui.DropWriter; pub const style = StyleBits; +pub const panic = win32.messageBoxThenPanic(.{ .title = "Flow Panic" }); + allocator: std.mem.Allocator, vx: vaxis.Vaxis, @@ -84,25 +86,6 @@ pub fn deinit(self: *Self) void { self.title_buf.deinit(); } -threadlocal var thread_is_panicing = false; - -pub fn panic( - msg: []const u8, - error_return_trace: ?*std.builtin.StackTrace, - ret_addr: ?usize, -) noreturn { - if (!thread_is_panicing) { - thread_is_panicing = true; - const msg_z: [:0]const u8 = if (std.fmt.allocPrintZ( - std.heap.page_allocator, - "{s}", - .{msg}, - )) |msg_z| msg_z else |_| "failed allocate error message"; - _ = win32.MessageBoxA(null, msg_z, "Flow Panic", .{ .ICONASTERISK = 1 }); - } - std.builtin.default_panic(msg, error_return_trace, ret_addr); -} - pub fn run(self: *Self) !void { if (self.thread) |_| return; @@ -353,7 +336,7 @@ fn update_window_title(self: *Self) void { const title = self.title_buf.toOwnedSliceSentinel(0) catch @panic("OOM:update_window_title"); if (win32.SetWindowTextW(hwnd, title) == 0) { - std.log.warn("SetWindowText failed with {}", .{win32.GetLastError().fmt()}); + std.log.warn("SetWindowText failed, error={}", .{win32.GetLastError()}); self.title_buf = std.ArrayList(u16).fromOwnedSlice(self.allocator, title); } else { self.allocator.free(title); diff --git a/src/win32/gui.zig b/src/win32/gui.zig index 2faa947..71761eb 100644 --- a/src/win32/gui.zig +++ b/src/win32/gui.zig @@ -123,7 +123,7 @@ fn getIcons(dpi: XY(u32)) Icons { small_x, small_y, win32.LR_SHARED, - ) orelse fatalWin32("LoadImage for small icon", win32.GetLastError()); + ) orelse win32.panicWin32("LoadImage for small icon", win32.GetLastError()); const large = win32.LoadImageW( win32.GetModuleHandleW(null), @ptrFromInt(c.ID_ICON_FLOW), @@ -131,7 +131,7 @@ fn getIcons(dpi: XY(u32)) Icons { large_x, large_y, win32.LR_SHARED, - ) orelse fatalWin32("LoadImage for large icon", win32.GetLastError()); + ) orelse win32.panicWin32("LoadImage for large icon", win32.GetLastError()); return .{ .small = @ptrCast(small), .large = @ptrCast(large) }; } @@ -268,7 +268,7 @@ fn calcWindowPlacement( var info: win32.MONITORINFO = undefined; info.cbSize = @sizeOf(win32.MONITORINFO); if (0 == win32.GetMonitorInfoW(monitor, &info)) { - std.log.warn("GetMonitorInfo failed with {}", .{win32.GetLastError().fmt()}); + std.log.warn("GetMonitorInfo failed, error={}", .{win32.GetLastError()}); return result; } break :blk info.rcWork; @@ -335,7 +335,7 @@ fn entry(pid: thespian.pid) !void { }, win32.MONITOR_DEFAULTTOPRIMARY, ) orelse { - std.log.warn("MonitorFromPoint failed with {}", .{win32.GetLastError().fmt()}); + std.log.warn("MonitorFromPoint failed, error={}", .{win32.GetLastError()}); break :blk null; }; }; @@ -384,7 +384,7 @@ fn entry(pid: thespian.pid) !void { .lpszClassName = CLASS_NAME, .hIconSm = global.icons.small, }; - if (0 == win32.RegisterClassExW(&wc)) fatalWin32( + if (0 == win32.RegisterClassExW(&wc)) win32.panicWin32( "RegisterClass for main window", win32.GetLastError(), ); @@ -403,7 +403,7 @@ fn entry(pid: thespian.pid) !void { null, // Menu win32.GetModuleHandleW(null), @ptrCast(&create_args), - ) orelse fatalWin32("CreateWindow", win32.GetLastError()); + ) orelse win32.panicWin32("CreateWindow", win32.GetLastError()); // NEVER DESTROY THE WINDOW! // This allows us to send the hwnd to other thread/parts // of the app and it will always be valid. @@ -430,7 +430,7 @@ fn entry(pid: thespian.pid) !void { ); } - if (0 == win32.UpdateWindow(hwnd)) fatalWin32("UpdateWindow", win32.GetLastError()); + if (0 == win32.UpdateWindow(hwnd)) win32.panicWin32("UpdateWindow", win32.GetLastError()); _ = win32.ShowWindow(hwnd, win32.SW_SHOWNORMAL); // try some things to bring our window to the top @@ -547,7 +547,7 @@ fn updateWindowSize( const cell_size = font.getCellSize(i32); var window_rect: win32.RECT = undefined; - if (0 == win32.GetWindowRect(hwnd, &window_rect)) fatalWin32( + if (0 == win32.GetWindowRect(hwnd, &window_rect)) win32.panicWin32( "GetWindowRect", win32.GetLastError(), ); @@ -646,7 +646,7 @@ fn sendMouse( ) void { const frame = tracy.initZone(@src(), .{ .name = "gui sendMouse" }); defer frame.deinit(); - const point = win32ext.pointFromLparam(lparam); + const point = win32.pointFromLparam(lparam); const state = stateFromHwnd(hwnd); const dpi = win32.dpiFromHwnd(hwnd); const cell_size = getFont(dpi, getFontSize(), getFontFace()).getCellSize(i32); @@ -699,7 +699,7 @@ fn sendMouseWheel( ) void { const frame = tracy.initZone(@src(), .{ .name = "gui sendMouseWheel" }); defer frame.deinit(); - var point = win32ext.pointFromLparam(lparam); + var point = win32.pointFromLparam(lparam); _ = win32.ScreenToClient(hwnd, &point); const state = stateFromHwnd(hwnd); const dpi = win32.dpiFromHwnd(hwnd); @@ -754,7 +754,7 @@ fn sendKey( const state = stateFromHwnd(hwnd); var keyboard_state: [256]u8 = undefined; - if (0 == win32.GetKeyboardState(&keyboard_state)) fatalWin32( + if (0 == win32.GetKeyboardState(&keyboard_state)) win32.panicWin32( "GetKeyboardState", win32.GetLastError(), ); @@ -1065,8 +1065,8 @@ fn WndProc( const client_size = getClientSize(u32, hwnd); var ps: win32.PAINTSTRUCT = undefined; - _ = win32.BeginPaint(hwnd, &ps) orelse return fatalWin32("BeginPaint", win32.GetLastError()); - defer if (0 == win32.EndPaint(hwnd, &ps)) fatalWin32("EndPaint", win32.GetLastError()); + _ = win32.BeginPaint(hwnd, &ps) orelse return win32.panicWin32("BeginPaint", win32.GetLastError()); + defer if (0 == win32.EndPaint(hwnd, &ps)) win32.panicWin32("EndPaint", win32.GetLastError()); global.render_cells.resize( global.render_cells_arena.allocator(), @@ -1343,19 +1343,13 @@ fn renderColorFromVaxis(color: vaxis.Color) render.Color { }; } -fn fatalWin32(what: []const u8, err: win32.WIN32_ERROR) noreturn { - std.debug.panic("{s} failed with {}", .{ what, err.fmt() }); -} -fn fatalHr(what: []const u8, hresult: win32.HRESULT) noreturn { - std.debug.panic("{s} failed, hresult=0x{x}", .{ what, @as(u32, @bitCast(hresult)) }); -} fn deleteObject(obj: ?win32.HGDIOBJ) void { - if (0 == win32.DeleteObject(obj)) fatalWin32("DeleteObject", win32.GetLastError()); + if (0 == win32.DeleteObject(obj)) win32.panicWin32("DeleteObject", win32.GetLastError()); } fn getClientSize(comptime T: type, hwnd: win32.HWND) XY(T) { var rect: win32.RECT = undefined; if (0 == win32.GetClientRect(hwnd, &rect)) - fatalWin32("GetClientRect", win32.GetLastError()); + win32.panicWin32("GetClientRect", win32.GetLastError()); std.debug.assert(rect.left == 0); std.debug.assert(rect.top == 0); return .{ .x = @intCast(rect.right), .y = @intCast(rect.bottom) }; @@ -1428,7 +1422,7 @@ fn getClientInset(dpi: u32) XY(i32) { 0, window_style_ex, dpi, - )) fatalWin32( + )) win32.panicWin32( "AdjustWindowRect", win32.GetLastError(), ); @@ -1456,5 +1450,5 @@ fn setWindowPosRect(hwnd: win32.HWND, rect: win32.RECT) void { rect.right - rect.left, rect.bottom - rect.top, .{ .NOZORDER = 1 }, - )) fatalWin32("SetWindowPos", win32.GetLastError()); + )) win32.panicWin32("SetWindowPos", win32.GetLastError()); } diff --git a/src/win32/win32ext.zig b/src/win32/win32ext.zig index f70d244..fc93085 100644 --- a/src/win32/win32ext.zig +++ b/src/win32/win32ext.zig @@ -1,17 +1,6 @@ const std = @import("std"); const win32 = @import("win32").everything; -// todo: these should be available in zigwin32 -fn xFromLparam(lparam: win32.LPARAM) i16 { - return @bitCast(win32.loword(lparam)); -} -fn yFromLparam(lparam: win32.LPARAM) i16 { - return @bitCast(win32.hiword(lparam)); -} -pub fn pointFromLparam(lparam: win32.LPARAM) win32.POINT { - return win32.POINT{ .x = xFromLparam(lparam), .y = yFromLparam(lparam) }; -} - // TODO: update zigwin32 with a way to get the corresponding IID for any COM interface pub fn queryInterface(obj: anytype, comptime Interface: type) *Interface { const obj_basename_start: usize = comptime if (std.mem.lastIndexOfScalar(u8, @typeName(@TypeOf(obj)), '.')) |i| (i + 1) else 0;