├── src ├── linux │ ├── init.zig │ ├── context.zig │ ├── event.zig │ ├── platform.zig │ └── window.zig ├── macOS │ ├── init.zig │ ├── context.zig │ ├── event.zig │ ├── platform.zig │ └── window.zig ├── demo.frag ├── demo.vert ├── windows │ ├── gdi32_bs.zig │ ├── kernel32_bs.zig │ ├── opengl32_bs.zig │ ├── platform.zig │ ├── event.zig │ ├── user32_bs.zig │ ├── context.zig │ ├── init.zig │ ├── window.zig │ └── w32.zig ├── event.zig ├── context.zig ├── key.zig ├── main.zig ├── zwl.zig └── window.zig ├── .gitignore ├── LICENSE └── README.md /src/linux/init.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/macOS/init.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/linux/context.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/linux/event.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/linux/platform.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/linux/window.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/macOS/context.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/macOS/event.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/macOS/platform.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /src/macOS/window.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | @compileError("Platform WIP"); 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.vscode/ 2 | **/.zig-cache/ 3 | **/zig-cache/ 4 | **/zig-out/ 5 | **/*.h 6 | **/*.c -------------------------------------------------------------------------------- /src/demo.frag: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | out vec4 FragColor; 4 | 5 | in vec3 color; 6 | 7 | void main() { 8 | FragColor = vec4(color, 1); 9 | } 10 | -------------------------------------------------------------------------------- /src/demo.vert: -------------------------------------------------------------------------------- 1 | #version 460 core 2 | 3 | layout(location = 0) in vec2 aPosition; 4 | layout(location = 1) in vec3 aColor; 5 | 6 | out vec3 color; 7 | 8 | void main() { 9 | gl_Position = vec4(aPosition, 0, 1); 10 | color = aColor; 11 | } 12 | -------------------------------------------------------------------------------- /src/windows/gdi32_bs.zig: -------------------------------------------------------------------------------- 1 | //! Opengl32 bootstrap for foreign compilation 2 | 3 | pub export fn SetPixelFormat() noreturn { 4 | @panic("Unexpected"); 5 | } 6 | pub export fn ChoosePixelFormat() noreturn { 7 | @panic("Unexpected"); 8 | } 9 | pub export fn SwapBuffers() noreturn { 10 | @panic("Unexpected"); 11 | } 12 | -------------------------------------------------------------------------------- /src/windows/kernel32_bs.zig: -------------------------------------------------------------------------------- 1 | //! Kernel32 bootstrap for foreign compilation 2 | 3 | pub export fn GetModuleHandleW() noreturn { 4 | @panic("Unexpected"); 5 | } 6 | pub export fn GetLastError() noreturn { 7 | @panic("Unexpected"); 8 | } 9 | pub export fn SetConsoleOutputCP() noreturn { 10 | @panic("Unexpected"); 11 | } -------------------------------------------------------------------------------- /src/windows/opengl32_bs.zig: -------------------------------------------------------------------------------- 1 | //! Opengl32 bootstrap for foreign compilation 2 | 3 | pub export fn wglCreateContext() noreturn { 4 | @panic("Unexpected"); 5 | } 6 | pub export fn wglDeleteContext() noreturn { 7 | @panic("Unexpected"); 8 | } 9 | pub export fn wglMakeCurrent() noreturn { 10 | @panic("Unexpected"); 11 | } 12 | pub export fn wglGetProcAddress() noreturn { 13 | @panic("Unexpected"); 14 | } 15 | pub export fn wglShareLists() noreturn { 16 | @panic("Unexpected"); 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Darkfllame 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Zig Windowing Library 2 | ZWL (Zig Windowing Library, /zwil/) is a cross-platform zig windowing library with loop-based event polling (like SDL) and aimed to be lightweight thanks to zig's conditional compilation/lazy evaluation. 3 | 4 | ## Current state: ![](https://progress-bar.xyz/3?scale=12&show_text=false&title=3/12) 5 |
6 | Win32 7 | 8 | - [x] Window 9 | - [x] Event 10 | - [x] OpenGL Context 11 |
12 |
13 | Linux 14 | 15 | - X11 ![](https://progress-bar.xyz/0?scale=3&show_text=false&title=0/3) 16 | - [ ] Window 17 | - [ ] Event 18 | - [ ] OpenGL Context 19 | - Wayland ![](https://progress-bar.xyz/0?scale=3&show_text=false&title=0/3) 20 | - [ ] Window 21 | - [ ] Event 22 | - [ ] OpenGL Context 23 |
24 |
25 | MacOS 26 | 27 | - [ ] Window 28 | - [ ] Event 29 | - [ ] OpenGL Context 30 |
31 | 32 | ### 33 | ZWL is very WIP, so expect bugs, inconsistencies and lack of support on certain platforms. If you wish you can help me by [contributing](#contributing) to this project via pull requests or filing issues. 34 | 35 | # Contributing 36 | Feel free to contribute to the library by making PRs or by filing issues. My machine is a windows one, so I'll prioritize my work (and might only work) on the Win32 implementation. -------------------------------------------------------------------------------- /src/windows/platform.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Zwl = @import("../Zwl.zig"); 3 | const init = @import("init.zig"); 4 | const window = @import("window.zig"); 5 | const event = @import("event.zig"); 6 | const context = @import("context.zig"); 7 | pub const W32 = @import("w32.zig"); 8 | 9 | const Platform = Zwl.Platform; 10 | 11 | pub const NativeData = init.NativeData; 12 | pub const Window = window.NativeWindow; 13 | pub const GLContext = context.GLContext; 14 | pub const platform = Zwl.Platform{ 15 | .init = &init.init, 16 | .deinit = &init.deinit, 17 | .keyName = &init.keyName, 18 | .window = .{ 19 | .createMessageBox = &window.NativeWindow.createMessageBox, 20 | .init = &window.NativeWindow.init, 21 | .deinit = &window.NativeWindow.deinit, 22 | .setPosition = &window.NativeWindow.setPosition, 23 | .setSize = &window.NativeWindow.setSize, 24 | .setSizeLimits = &window.NativeWindow.setSizeLimits, 25 | .getFramebufferSize = &window.NativeWindow.getFramebufferSize, 26 | .setVisible = &window.NativeWindow.setVisible, 27 | .setTitle = &window.NativeWindow.setTitle, 28 | .isFocused = &window.NativeWindow.isFocused, 29 | .getMousePos = &window.NativeWindow.getMousePos, 30 | .setMousePos = &window.NativeWindow.setMousePos, 31 | .setMouseVisible = &window.NativeWindow.setMouseVisible, 32 | .setFocus = &window.NativeWindow.setFocus, 33 | .setMouseConfined = &window.NativeWindow.setMouseConfined, 34 | }, 35 | .event = .{ 36 | .pollEvent = &event.pollEvent, 37 | }, 38 | .glContext = .{ 39 | .init = &context.GLContext.init, 40 | .deinit = &context.GLContext.deinit, 41 | .makeCurrent = &context.GLContext.makeCurrent, 42 | .swapBuffers = &context.GLContext.swapBuffers, 43 | .swapInterval = &context.GLContext.swapInterval, 44 | }, 45 | }; -------------------------------------------------------------------------------- /src/windows/event.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Zwl = @import("../Zwl.zig"); 3 | const W32 = @import("w32.zig"); 4 | const window = @import("window.zig"); 5 | const event = @import("../event.zig"); 6 | 7 | const Window = Zwl.Window; 8 | const Error = Zwl.Error; 9 | const Event = Zwl.Event; 10 | const Key = Zwl.Key; 11 | 12 | pub var pollingError: ?Error = null; 13 | 14 | pub fn pollEvent(lib: *Zwl, opt_window: ?*Window) Error!void { 15 | pollingError = null; 16 | 17 | var msg: W32.MSG = undefined; 18 | 19 | if (W32.PeekMessageW( 20 | &msg, 21 | if (opt_window) |wnd| wnd.native.handle else null, 22 | 0, 23 | 0, 24 | W32.PM_REMOVE, 25 | ) != 0) { 26 | switch (msg.message) { 27 | W32.WM_QUIT => try queueEvent(lib, .{ .quit = msg.wParam }), 28 | else => { 29 | _ = W32.TranslateMessage(&msg); 30 | _ = W32.DispatchMessageW(&msg); 31 | }, 32 | } 33 | } 34 | 35 | if (pollingError) |pErr| return pErr; 36 | 37 | if (W32.GetActiveWindow()) |handle| { 38 | if (@as(?*Window, @ptrCast(@alignCast(W32.GetPropW(handle, window.WND_PTR_PROP_NAME.ptr))))) |wnd| { 39 | const keys = [_]struct { u8, Key }{ 40 | .{ 0xA0, .left_shift }, 41 | .{ 0xA1, .right_shift }, 42 | .{ 0x5B, .left_super }, 43 | .{ 0x5C, .right_super }, 44 | }; 45 | 46 | for (keys) |keypair| { 47 | const vk = keypair[0]; 48 | const key = keypair[1]; 49 | 50 | if (W32.GetKeyState(vk) & 0x8000 != 0) { 51 | continue; 52 | } 53 | if (!wnd.keys[@intFromEnum(key)]) { 54 | continue; 55 | } 56 | 57 | try queueEvent(lib, .{ .key = .{ 58 | .window = wnd, 59 | .key = key, 60 | .action = .release, 61 | .mods = window.getKeyMods(), 62 | } }); 63 | } 64 | } 65 | } 66 | } 67 | 68 | pub const queueEvent = event.queueEvent; 69 | -------------------------------------------------------------------------------- /src/event.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | const config = @import("config"); 4 | const Zwl = @import("Zwl.zig"); 5 | pub const Key = @import("key.zig").Key; 6 | 7 | const Error = Zwl.Error; 8 | const Window = Zwl.Window; 9 | 10 | pub const Event = union(enum) { 11 | quit: u64, 12 | windowClosed: *Window, 13 | windowFocused: struct { 14 | window: *Window, 15 | gained: bool, 16 | }, 17 | windowResized: struct { 18 | window: *Window, 19 | width: u16, 20 | height: u16, 21 | }, 22 | windowMoved: struct { 23 | window: *Window, 24 | x: u16, 25 | y: u16, 26 | }, 27 | mouseMoved: struct { 28 | window: *Window, 29 | x: u16, 30 | y: u16, 31 | dx: i16, 32 | dy: i16, 33 | }, 34 | mouseButton: struct { 35 | window: *Window, 36 | clicked: bool, 37 | /// | value | button | 38 | /// |-|-| 39 | /// |1|left| 40 | /// |2|middle| 41 | /// |3|right| 42 | /// |4|4th button| 43 | /// |5|5th button| 44 | /// and so on... 45 | button: u8, 46 | mods: EventMods, 47 | }, 48 | mouseWheel: struct { 49 | window: *Window, 50 | x: f32, 51 | y: f32, 52 | mods: EventMods, 53 | }, 54 | key: struct { 55 | window: *Window, 56 | key: Key, 57 | action: Key.Action, 58 | mods: Key.Mods, 59 | }, 60 | 61 | pub const EventMods = packed struct { 62 | control: bool, 63 | shift: bool, 64 | }; 65 | }; 66 | 67 | pub fn pollEvent(lib: *Zwl, opt_window: ?*Window) Error!?Event { 68 | return popQueue(lib) orelse { 69 | try lib.platform.event.pollEvent(lib, opt_window); 70 | return popQueue(lib); 71 | }; 72 | } 73 | 74 | fn popQueue(lib: *Zwl) ?Event { 75 | if (lib.eventQueueSize > 0) { 76 | const retItem = lib.eventQueue[0]; 77 | lib.eventQueueSize -= 1; 78 | if (lib.eventQueueSize > 1) { 79 | for (lib.eventQueue[1..lib.eventQueueSize], 0..) |item, i| { 80 | lib.eventQueue[i] = item; 81 | } 82 | } 83 | return retItem; 84 | } 85 | return null; 86 | } 87 | 88 | pub fn queueEvent(lib: *Zwl, event: Event) Error!void { 89 | const newSize = lib.eventQueueSize + 1; 90 | if (newSize > lib.eventQueue.len) { 91 | return Error.QueueFull; 92 | } 93 | lib.eventQueue[newSize - 1] = event; 94 | lib.eventQueueSize = newSize; 95 | } 96 | -------------------------------------------------------------------------------- /src/context.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | const Zwl = @import("Zwl.zig"); 4 | 5 | const Error = Zwl.Error; 6 | const Window = Zwl.Window; 7 | 8 | pub const GLContext = struct { 9 | owner: *Window, 10 | config: Config, 11 | native: Zwl.platform.GLContext, 12 | 13 | pub const VersionAPI = enum(u2) { 14 | opengl, 15 | opengl_es, 16 | }; 17 | pub const OpenGLProfile = enum(u2) { 18 | any, 19 | core, 20 | compat, 21 | }; 22 | pub const Version = struct { 23 | api: VersionAPI = .opengl, 24 | major: u8 = 0, 25 | minor: u8 = 0, 26 | }; 27 | pub const Config = struct { 28 | version: Version = .{}, 29 | debug: bool = builtin.mode == .Debug, 30 | forward: bool = false, 31 | profile: OpenGLProfile = .any, 32 | share: ?*GLContext = null, 33 | pixelFormat: PixelFormat = .{}, 34 | }; 35 | pub const PixelFormat = packed struct(u56) { 36 | /// 0 means default 37 | redBits: u8 = 0, 38 | /// 0 means default 39 | greenBits: u8 = 0, 40 | /// 0 means default 41 | blueBits: u8 = 0, 42 | /// 0 means default 43 | alphaBits: u8 = 0, 44 | /// 0 means default 45 | depthBits: u8 = 0, 46 | /// 0 means default 47 | stencilBits: u8 = 0, 48 | /// 0 means default 49 | samples: u8 = 0, 50 | }; 51 | 52 | pub fn create(window: *Window, config: Config) Error!*GLContext { 53 | const lib = window.owner; 54 | const allocator = lib.allocator; 55 | const self = allocator.create(GLContext) catch |e| { 56 | return lib.setError("Cannot create GLContext", .{}, e); 57 | }; 58 | errdefer allocator.destroy(self); 59 | try self.init(window, config); 60 | return self; 61 | } 62 | pub fn init(self: *GLContext, window: *Window, config: Config) Error!void{ 63 | const lib = window.owner; 64 | self.owner = window; 65 | self.config = config; 66 | try lib.platform.glContext.init(&self.native, lib, window, config); 67 | } 68 | pub fn destroy(self: *GLContext) void { 69 | const lib = self.owner.owner; 70 | self.deinit(); 71 | lib.allocator.destroy(self); 72 | } 73 | pub fn deinit(self: *GLContext) void { 74 | const lib = self.owner.owner; 75 | lib.platform.glContext.deinit(&self.native); 76 | } 77 | 78 | pub fn makeCurrent(lib: *Zwl, opt_ctx: ?*GLContext) Error!void { 79 | if (opt_ctx) |ctx| { 80 | if (ctx.owner.owner != lib) { 81 | @panic("Bad library passed to GLContext.makeCurrent"); 82 | } 83 | } 84 | return lib.platform.glContext.makeCurrent(lib, opt_ctx); 85 | } 86 | pub fn swapBuffers(ctx: *GLContext) Error!void { 87 | return ctx.owner.owner.platform.glContext.swapBuffers(ctx); 88 | } 89 | pub fn swapInterval(lib: *Zwl, interval: i32) Error!void { 90 | return lib.platform.glContext.swapInterval(lib, interval); 91 | } 92 | }; 93 | -------------------------------------------------------------------------------- /src/key.zig: -------------------------------------------------------------------------------- 1 | pub const Key = enum(u16) { 2 | pub const Action = enum(u2) { 3 | release = 0, 4 | press, 5 | repeat, 6 | }; 7 | 8 | pub const Mods = packed struct { 9 | shift: bool = false, 10 | control: bool = false, 11 | alt: bool = false, 12 | super: bool = false, 13 | capsLock: bool = false, 14 | numLock: bool = false, 15 | }; 16 | 17 | unkown = 0xFFFF, 18 | space = 32, 19 | apostrophe = 39, 20 | comma = 44, 21 | minus = 45, 22 | period = 46, 23 | slash = 47, 24 | @"0" = 48, 25 | @"1" = 49, 26 | @"2" = 50, 27 | @"3" = 51, 28 | @"4" = 52, 29 | @"5" = 53, 30 | @"6" = 54, 31 | @"7" = 55, 32 | @"8" = 56, 33 | @"9" = 57, 34 | semicolon = 59, 35 | equal = 61, 36 | a = 65, 37 | b = 66, 38 | c = 67, 39 | d = 68, 40 | e = 69, 41 | f = 70, 42 | g = 71, 43 | h = 72, 44 | i = 73, 45 | j = 74, 46 | k = 75, 47 | l = 76, 48 | m = 77, 49 | n = 78, 50 | o = 79, 51 | p = 80, 52 | q = 81, 53 | r = 82, 54 | s = 83, 55 | t = 84, 56 | u = 85, 57 | v = 86, 58 | w = 87, 59 | x = 88, 60 | y = 89, 61 | z = 90, 62 | left_bracket = 91, 63 | backslash = 92, 64 | right_bracket = 93, 65 | grave_accent = 96, 66 | world_1 = 161, 67 | world_2 = 162, 68 | escape = 256, 69 | enter = 257, 70 | tab = 258, 71 | backspace = 259, 72 | insert = 260, 73 | delete = 261, 74 | right = 262, 75 | left = 263, 76 | down = 264, 77 | up = 265, 78 | page_up = 266, 79 | page_down = 267, 80 | home = 268, 81 | end = 269, 82 | caps_lock = 280, 83 | scroll_lock = 281, 84 | num_lock = 282, 85 | print_screen = 283, 86 | pause = 284, 87 | f1 = 290, 88 | f2 = 291, 89 | f3 = 292, 90 | f4 = 293, 91 | f5 = 294, 92 | f6 = 295, 93 | f7 = 296, 94 | f8 = 297, 95 | f9 = 298, 96 | f10 = 299, 97 | f11 = 300, 98 | f12 = 301, 99 | f13 = 302, 100 | f14 = 303, 101 | f15 = 304, 102 | f16 = 305, 103 | f17 = 306, 104 | f18 = 307, 105 | f19 = 308, 106 | f20 = 309, 107 | f21 = 310, 108 | f22 = 311, 109 | f23 = 312, 110 | f24 = 313, 111 | f25 = 314, 112 | kp_0 = 320, 113 | kp_1 = 321, 114 | kp_2 = 322, 115 | kp_3 = 323, 116 | kp_4 = 324, 117 | kp_5 = 325, 118 | kp_6 = 326, 119 | kp_7 = 327, 120 | kp_8 = 328, 121 | kp_9 = 329, 122 | kp_decimal = 330, 123 | kp_divide = 331, 124 | kp_multiply = 332, 125 | kp_subtract = 333, 126 | kp_add = 334, 127 | kp_enter = 335, 128 | kp_equal = 336, 129 | left_shift = 340, 130 | left_control = 341, 131 | left_alt = 342, 132 | left_super = 343, 133 | right_shift = 344, 134 | right_control = 345, 135 | right_alt = 346, 136 | right_super = 347, 137 | menu = 348, 138 | /// Isn't used except to get the 139 | /// `Window.keys` size 140 | last = 349, 141 | }; 142 | -------------------------------------------------------------------------------- /src/windows/user32_bs.zig: -------------------------------------------------------------------------------- 1 | //! User32 bootstrap for foreign compilation 2 | 3 | pub export fn GetSystemMetrics() noreturn { 4 | @panic("Unexpected"); 5 | } 6 | pub export fn CreateWindowExW() noreturn { 7 | @panic("Unexpected"); 8 | } 9 | pub export fn DestroyWindow() noreturn { 10 | @panic("Unexpected"); 11 | } 12 | pub export fn DefWindowProcW() noreturn { 13 | @panic("Unexpected"); 14 | } 15 | pub export fn RegisterClassExW() noreturn { 16 | @panic("Unexpected"); 17 | } 18 | pub export fn UnregisterClassW() noreturn { 19 | @panic("Unexpected"); 20 | } 21 | pub export fn LoadCursorW() noreturn { 22 | @panic("Unexpected"); 23 | } 24 | pub export fn GetPropW() noreturn { 25 | @panic("Unexpected"); 26 | } 27 | pub export fn SetPropW() noreturn { 28 | @panic("Unexpected"); 29 | } 30 | pub export fn GetActiveWindow() noreturn { 31 | @panic("Unexpected"); 32 | } 33 | pub export fn SetActiveWindow() noreturn { 34 | @panic("Unexpected"); 35 | } 36 | pub export fn SetFocus() noreturn { 37 | @panic("Unexpected"); 38 | } 39 | pub export fn PeekMessageW() noreturn { 40 | @panic("Unexpected"); 41 | } 42 | pub export fn TranslateMessage() noreturn { 43 | @panic("Unexpected"); 44 | } 45 | pub export fn DispatchMessageW() noreturn { 46 | @panic("Unexpected"); 47 | } 48 | pub export fn ClientToScreen() noreturn { 49 | @panic("Unexpected"); 50 | } 51 | pub export fn AdjustWindowRectEx() noreturn { 52 | @panic("Unexpected"); 53 | } 54 | pub export fn GetClientRect() noreturn { 55 | @panic("Unexpected"); 56 | } 57 | pub export fn SetWindowPos() noreturn { 58 | @panic("Unexpected"); 59 | } 60 | pub export fn GetDC() noreturn { 61 | @panic("Unexpected"); 62 | } 63 | pub export fn ShowWindow() noreturn { 64 | @panic("Unexpected"); 65 | } 66 | pub export fn SetWindowTextW() noreturn { 67 | @panic("Unexpected"); 68 | } 69 | pub export fn GetWindowTextLengthW() noreturn { 70 | @panic("Unexpected"); 71 | } 72 | pub export fn GetWindowTextW() noreturn { 73 | @panic("Unexpected"); 74 | } 75 | pub export fn GetWindowRect() noreturn { 76 | @panic("Unexpected"); 77 | } 78 | pub export fn MoveWindow() noreturn { 79 | @panic("Unexpected"); 80 | } 81 | pub export fn GetCursorPos() noreturn { 82 | @panic("Unexpected"); 83 | } 84 | pub export fn SetCursorPos() noreturn { 85 | @panic("Unexpected"); 86 | } 87 | pub export fn ScreenToClient() noreturn { 88 | @panic("Unexpected"); 89 | } 90 | pub export fn SetCursor() noreturn { 91 | @panic("Unexpected"); 92 | } 93 | pub export fn ClipCursor() noreturn { 94 | @panic("Unexpected"); 95 | } 96 | pub export fn WindowFromPoint() noreturn { 97 | @panic("Unexpected"); 98 | } 99 | pub export fn PtInRect() noreturn { 100 | @panic("Unexpected"); 101 | } 102 | pub export fn ShowCursor() noreturn { 103 | @panic("Unexpected"); 104 | } 105 | pub export fn GetKeyState() noreturn { 106 | @panic("Unexpected"); 107 | } 108 | pub export fn MapVirtualKeyW() noreturn { 109 | @panic("Unexpected"); 110 | } 111 | pub export fn GetMessageTime() noreturn { 112 | @panic("Unexpected"); 113 | } 114 | pub export fn MessageBoxW() noreturn { 115 | @panic("Unexpected"); 116 | } 117 | pub export fn ToUniform() noreturn { 118 | @panic("Unexpected"); 119 | } 120 | pub export fn SendMessage() noreturn { 121 | @panic("Unexpected"); 122 | } 123 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | const Zwl = @import("zwl"); 4 | const GL = @import("zgll").GL; 5 | 6 | const VERTEX_SHADER_SOURCE: []const u8 = @embedFile("demo.vert"); 7 | const FRAGMENT_SHADER_SOURCE: []const u8 = @embedFile("demo.frag"); 8 | const TRIANGLE_VERTICES = [_]f32{ 9 | -0.5, -0.5, 1, 0, 0, 10 | 0.5, -0.5, 0, 1, 0, 11 | 0, 0.5, 0, 0, 1, 12 | }; 13 | 14 | pub fn main() !void { 15 | if (builtin.os.tag == .windows) { 16 | // manually set console output mode for windows, because zig doesn't 17 | const W32 = Zwl.platform.W32; 18 | _ = W32.SetConsoleOutputCP(W32.CP_UTF8); 19 | } else if (builtin.os.tag == .linux) { 20 | return linuxMain(); 21 | } 22 | 23 | const DEBUG = builtin.mode == .Debug; 24 | var gpa = if (DEBUG) 25 | std.heap.GeneralPurposeAllocator(.{}){} 26 | else {}; 27 | defer _ = if (DEBUG) gpa.deinit(); 28 | const allocator = if (DEBUG) gpa.allocator() else std.heap.page_allocator; 29 | 30 | const zwl = try allocator.create(Zwl); 31 | defer allocator.destroy(zwl); 32 | 33 | errdefer |e| { 34 | std.debug.print("[FATAL | {s}] {s}\n", .{ @errorName(e), zwl.getError() }); 35 | } 36 | 37 | try zwl.init(allocator, .{}); 38 | defer zwl.deinit(); 39 | 40 | const window = try zwl.createWindow(.{ 41 | .title = "ZWL demo", 42 | .width = 800, 43 | .height = 600, 44 | }); 45 | defer window.destroy(); 46 | 47 | const ctx = try window.createGLContext(Zwl.GLContext.Config{ 48 | .pixelFormat = .{ .samples = 8 }, 49 | .version = .{ 50 | .major = 3, 51 | .minor = 2, 52 | }, 53 | }); 54 | defer ctx.destroy(); 55 | try zwl.makeContextCurrent(ctx); 56 | 57 | const gl = try allocator.create(GL); 58 | defer allocator.destroy(gl); 59 | try gl.init(null); 60 | 61 | std.debug.print("Using OpenGL {s}\n", .{gl.getString(GL.VERSION).?}); 62 | 63 | var VAO: u32 = 0; 64 | gl.genVertexArrays(1, @ptrCast(&VAO)); 65 | defer gl.deleteVertexArrays(1, @ptrCast(&VAO)); 66 | 67 | var VBO: u32 = 0; 68 | gl.genBuffers(1, @ptrCast(&VBO)); 69 | defer gl.deleteBuffers(1, @ptrCast(&VBO)); 70 | 71 | gl.bindVertexArray(VAO); 72 | 73 | gl.bindBuffer(GL.ARRAY_BUFFER, VBO); 74 | 75 | gl.bufferData(GL.ARRAY_BUFFER, @sizeOf(@TypeOf(TRIANGLE_VERTICES)), &TRIANGLE_VERTICES, GL.STATIC_DRAW); 76 | 77 | gl.vertexAttribPointer(0, 2, GL.FLOAT, false, @sizeOf(f32) * 5, 0); 78 | gl.enableVertexArrayAttrib(VAO, 0); 79 | 80 | gl.vertexAttribPointer(1, 3, GL.FLOAT, false, @sizeOf(f32) * 5, @sizeOf(f32) * 2); 81 | gl.enableVertexArrayAttrib(VAO, 1); 82 | 83 | gl.bindBuffer(GL.ARRAY_BUFFER, 0); 84 | 85 | gl.bindVertexArray(0); 86 | 87 | const shaderProgram = gl.createProgram(); 88 | defer gl.deleteProgram(shaderProgram); 89 | { 90 | const vertexShader = gl.createShader(GL.VERTEX_SHADER); 91 | defer gl.deleteShader(vertexShader); 92 | gl.shaderSource(vertexShader, 1, @ptrCast(&VERTEX_SHADER_SOURCE.ptr), null); 93 | gl.compileShader(vertexShader); 94 | 95 | const fragmentShader = gl.createShader(GL.FRAGMENT_SHADER); 96 | defer gl.deleteShader(fragmentShader); 97 | gl.shaderSource(fragmentShader, 1, @ptrCast(&FRAGMENT_SHADER_SOURCE.ptr), null); 98 | gl.compileShader(fragmentShader); 99 | 100 | gl.attachShader(shaderProgram, vertexShader); 101 | defer gl.detachShader(shaderProgram, vertexShader); 102 | gl.attachShader(shaderProgram, fragmentShader); 103 | defer gl.detachShader(shaderProgram, fragmentShader); 104 | 105 | gl.linkProgram(shaderProgram); 106 | } 107 | 108 | gl.viewport(0, 0, 800, 600); 109 | gl.enable(GL.MULTISAMPLE); 110 | gameloop: while (true) { 111 | while (try zwl.pollEvent(null)) |event| { 112 | switch (event) { 113 | .quit, .windowClosed => break :gameloop, 114 | .key => |input| if (input.action == .press) { 115 | std.debug.print("key pressed: {s}\n", .{zwl.keyName(input.key) orelse @tagName(input.key)}); 116 | }, 117 | else => {}, 118 | } 119 | } 120 | 121 | gl.clearColor(0, 0, 0, 1); 122 | gl.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT); 123 | 124 | gl.useProgram(shaderProgram); 125 | 126 | gl.bindVertexArray(VAO); 127 | gl.drawArrays(GL.TRIANGLES, 0, 3); 128 | gl.bindVertexArray(0); 129 | 130 | gl.useProgram(0); 131 | 132 | try ctx.swapBuffers(); 133 | } 134 | } 135 | 136 | fn linuxMain() !void { 137 | std.debug.print("Hello, World!\n", .{}); 138 | // const DEBUG = builtin.mode == .Debug; 139 | // var gpa = if (DEBUG) 140 | // std.heap.GeneralPurposeAllocator(.{}){} 141 | // else {}; 142 | // defer _ = if (DEBUG) gpa.deinit(); 143 | // const allocator = if (DEBUG) gpa.allocator() else std.heap.page_allocator; 144 | 145 | // const zwl = try allocator.create(ZWL.Zwl); 146 | // defer allocator.destroy(zwl); 147 | 148 | // errdefer |e| { 149 | // std.debug.print("[FATAL | {s}] {s}\n", .{ @errorName(e), zwl.getError() }); 150 | // } 151 | 152 | // try zwl.init(allocator, .{}); 153 | // defer zwl.deinit(); 154 | } 155 | -------------------------------------------------------------------------------- /src/zwl.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | const config = @import("config"); 4 | const window = @import("window.zig"); 5 | const event = @import("event.zig"); 6 | const context = @import("context.zig"); 7 | 8 | const Allocator = std.mem.Allocator; 9 | const Zwl = @This(); 10 | 11 | pub const platform = switch (builtin.os.tag) { 12 | .windows => @import("windows/platform.zig"), 13 | .linux => @import("linux/platform.zig"), 14 | .macos => @import("macos/platform.zig"), 15 | else => @compileError("Unsupported target"), 16 | }; 17 | 18 | pub const Window = window.Window; 19 | pub const Event = event.Event; 20 | pub const Key = event.Key; 21 | pub const GLContext = context.GLContext; 22 | 23 | pub const Error = error{ 24 | Cocoa, 25 | InvalidUtf8, 26 | OutOfMemory, 27 | QueueFull, 28 | X11, 29 | Wayland, 30 | Win32, 31 | }; 32 | 33 | pub const Config = struct {}; 34 | 35 | comptime platform: Platform = if (@hasDecl(platform, "platform") and @TypeOf(platform.platform) == Platform) 36 | platform.platform 37 | else 38 | @compileError("Expected platform.setPlatform to be 'fn (*Platform) Error!void'"), 39 | 40 | allocator: Allocator, 41 | errorBuffer: [config.ERROR_BUFFER_SIZE]u8, 42 | errFormatBuffer: [config.ERROR_BUFFER_SIZE]u8, 43 | currentError: ?[]u8, 44 | eventQueueSize: usize, 45 | eventQueue: [config.EVENT_QUEUE_SIZE]Event, 46 | native: platform.NativeData, 47 | 48 | pub fn init(self: *Zwl, allocator: Allocator, _config: Config) Error!void { 49 | @memset(std.mem.asBytes(self), 0); 50 | self.allocator = allocator; 51 | try self.platform.init(self, _config); 52 | } 53 | pub fn deinit(self: *Zwl) void { 54 | self.platform.deinit(self); 55 | } 56 | 57 | pub fn clearError(self: *Zwl) void { 58 | self.currentError = null; 59 | } 60 | pub fn getError(self: *const Zwl) []const u8 { 61 | return self.currentError orelse config.DEFAULT_ERROR_MESSAGE; 62 | } 63 | pub fn setError(self: *Zwl, comptime fmt: []const u8, args: anytype, err: anytype) @TypeOf(err) { 64 | if (@typeInfo(@TypeOf(err)) != .ErrorSet) { 65 | @compileError("'err' must be an error"); 66 | } 67 | 68 | self.clearError(); 69 | 70 | const formatted = std.fmt.bufPrint(&self.errFormatBuffer, fmt, args) catch blk: { 71 | const TRUNC_MESSAGE = " (truncated)"; 72 | @memcpy( 73 | self.errFormatBuffer[self.errFormatBuffer.len - TRUNC_MESSAGE.len ..], 74 | TRUNC_MESSAGE, 75 | ); 76 | break :blk &self.errFormatBuffer; 77 | }; 78 | 79 | self.currentError = self.errorBuffer[0..formatted.len]; 80 | 81 | @memcpy(self.currentError.?, formatted); 82 | 83 | return err; 84 | } 85 | 86 | pub fn keyName(self: *const Zwl, key: Key) ?[:0]const u8 { 87 | return self.platform.keyName(self, key); 88 | } 89 | 90 | pub const createWindow = Window.create; 91 | pub const createMessageBox = Window.createMessageBox; 92 | 93 | pub const pollEvent = event.pollEvent; 94 | 95 | pub const makeContextCurrent = GLContext.makeCurrent; 96 | pub const swapInterval = GLContext.swapInterval; 97 | 98 | pub const Platform = struct { 99 | init: *const fn (*Zwl, Config) Error!void, 100 | deinit: *const fn (*Zwl) void, 101 | keyName: *const fn (*const Zwl, Key) [:0]const u8, 102 | window: struct { 103 | createMessageBox: *const fn (*Zwl, Window.MBConfig) Error!Window.MBButton, 104 | init: *const fn (*platform.Window, *Zwl, Window.Config) Error!void, 105 | deinit: *const fn (*platform.Window) void, 106 | setPosition: *const fn (*Window, u32, u32) void, 107 | setSize: *const fn (*Window, u32, u32) void, 108 | setSizeLimits: *const fn (*Window, ?u32, ?u32, ?u32, ?u32) void, 109 | getFramebufferSize: *const fn (*Window, ?*u32, ?*u32) void, 110 | setVisible: *const fn (*Window, bool) void, 111 | setTitle: *const fn (*Window, []const u8) Error!void, 112 | isFocused: *const fn (*Window) bool, 113 | getMousePos: *const fn (*Window, ?*u32, ?*u32) void, 114 | setMousePos: *const fn (*Window, u32, u32) void, 115 | setMouseVisible: *const fn (*Window, bool) void, 116 | setFocus: *const fn (*Window) void, 117 | setMouseConfined: *const fn (*Window, bool) void, 118 | }, 119 | event: struct { 120 | pollEvent: *const fn (*Zwl, ?*Window) Error!void, 121 | }, 122 | glContext: struct { 123 | init: *const fn (*platform.GLContext, *Zwl, *Window, GLContext.Config) Error!void, 124 | deinit: *const fn (*platform.GLContext) void, 125 | makeCurrent: *const fn (*Zwl, ?*GLContext) Error!void, 126 | swapBuffers: *const fn (*GLContext) Error!void, 127 | swapInterval: *const fn (*Zwl, i32) Error!void, 128 | }, 129 | }; 130 | 131 | pub fn MBpanic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn { 132 | @setCold(true); 133 | const S = struct { 134 | var inPanic: bool = false; 135 | }; 136 | if (S.inPanic) { 137 | std.builtin.default_panic("Panic in panic, aborting", error_return_trace, null); 138 | } 139 | S.inPanic = true; 140 | const first_ret_addr = ret_addr orelse @returnAddress(); 141 | 142 | var text: [4096]u8 = undefined; 143 | var len: usize = 0; 144 | var fbs = std.io.fixedBufferStream(&text); 145 | fbs.writer().print("{s}\n", .{msg}) catch {}; 146 | if (!builtin.strip_debug_info) { 147 | if (std.debug.getSelfDebugInfo()) |dbi| { 148 | std.debug.writeCurrentStackTrace( 149 | fbs.writer(), 150 | dbi, 151 | .no_color, 152 | first_ret_addr, 153 | ) catch {}; 154 | } else |_| {} 155 | } 156 | if (error_return_trace) |ert| { 157 | ert.format("", .{}, fbs.writer()) catch {}; 158 | } 159 | len = fbs.pos; 160 | const mbText = text[0..len]; 161 | 162 | var title: [4096]u8 = undefined; 163 | fbs = std.io.fixedBufferStream(&title); 164 | len = 0; 165 | if (@import("builtin").single_threaded) { 166 | fbs.writer().print("panic", .{}) catch {}; 167 | } else { 168 | fbs.writer().print("thread {d} panic", .{std.Thread.getCurrentId()}) catch {}; 169 | } 170 | len = fbs.pos; 171 | 172 | var zwl: Zwl = undefined; 173 | zwl.init(std.heap.page_allocator, .{}) catch 174 | std.builtin.default_panic(msg, @errorReturnTrace(), null); 175 | 176 | const ret = zwl.createMessageBox(.{ 177 | .title = title[0..len], 178 | .text = mbText, 179 | .icon = .@"error", 180 | }); 181 | zwl.deinit(); 182 | if (ret) |_| {} else |_| {} 183 | std.builtin.default_panic(msg, error_return_trace, first_ret_addr); 184 | } 185 | 186 | comptime { 187 | if (@sizeOf(c_int) != 4) { 188 | @compileError("Bad target platform, c_int MUST be 32 bits"); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/window.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | const Zwl = @import("Zwl.zig"); 4 | 5 | const Allocator = std.mem.Allocator; 6 | 7 | const Key = Zwl.Key; 8 | const Error = Zwl.Error; 9 | const GLContext = Zwl.GLContext; 10 | 11 | const MAX_U32 = std.math.maxInt(u32); 12 | 13 | pub const Window = struct { 14 | owner: *Zwl, 15 | config: Config, 16 | mouse: struct { 17 | lastY: u16 = 0, 18 | lastX: u16 = 0, 19 | } = .{}, 20 | lastY: u16 = 0, 21 | lastX: u16 = 0, 22 | keys: [@intFromEnum(Key.last)]bool = std.mem.zeroes([@intFromEnum(Key.last)]bool), 23 | mouseButtons: [5]bool = [_]bool{false} ** 5, 24 | native: Zwl.platform.Window, 25 | 26 | pub const Flags = packed struct { 27 | resizable: bool = false, 28 | hidden: bool = false, 29 | noDecoration: bool = false, 30 | floating: bool = false, 31 | hideMouse: bool = false, 32 | hasFocus: bool = false, 33 | fullscreen: bool = false, 34 | }; 35 | 36 | pub const Position = union(enum) { 37 | default, 38 | pos: u32, 39 | 40 | pub inline fn toNumber(self: Position, default: u32) u32 { 41 | return switch (self) { 42 | .default => default, 43 | .pos => |pos| pos, 44 | }; 45 | } 46 | }; 47 | 48 | pub const SizeLimits = struct { 49 | wmin: ?u32 = null, 50 | wmax: ?u32 = null, 51 | hmin: ?u32 = null, 52 | hmax: ?u32 = null, 53 | }; 54 | 55 | pub const Config = struct { 56 | title: []const u8, 57 | width: u32, 58 | height: u32, 59 | x: Position = .default, 60 | y: Position = .default, 61 | sizeLimits: SizeLimits = .{}, 62 | flags: Flags = .{}, 63 | aspectRatio: ?struct { 64 | numer: u32, 65 | denom: u32, 66 | } = null, 67 | }; 68 | 69 | pub const MBMode = enum { 70 | ok, 71 | okCancel, 72 | abortRetryIgnore, 73 | yesNoCancel, 74 | yesNo, 75 | retryCancel, 76 | cancelTryContinue, 77 | }; 78 | 79 | pub const MBButton = enum { 80 | ok, 81 | cancel, 82 | abort, 83 | retry, 84 | ignore, 85 | yes, 86 | no, 87 | tryAgain, 88 | @"continue", 89 | }; 90 | 91 | pub const MBIcon = enum { 92 | none, 93 | @"error", 94 | question, 95 | warning, 96 | information, 97 | }; 98 | 99 | pub const MBConfig = struct { 100 | title: []const u8, 101 | text: []const u8, 102 | parent: ?*Window = null, 103 | mode: MBMode = .ok, 104 | icon: MBIcon = .none, 105 | }; 106 | 107 | pub fn create(owner: *Zwl, config: Config) Error!*Window { 108 | const self = owner.allocator.create(Window) catch |e| { 109 | return owner.setError("Cannot allocate window", .{}, e); 110 | }; 111 | errdefer owner.allocator.destroy(self); 112 | try self.init(owner, config); 113 | return self; 114 | } 115 | pub fn init(self: *Window, owner: *Zwl, config: Config) Error!void { 116 | std.debug.assert((config.sizeLimits.wmin orelse 0) < 117 | (config.sizeLimits.wmax orelse MAX_U32)); 118 | std.debug.assert((config.sizeLimits.hmin orelse 0) < 119 | (config.sizeLimits.hmax orelse MAX_U32)); 120 | 121 | self.* = Window{ 122 | .owner = owner, 123 | .config = config, 124 | .native = undefined, 125 | }; 126 | 127 | self.config.title = owner.allocator.dupe(u8, config.title) catch |e| { 128 | return owner.setError("Cannot copy window title", .{}, e); 129 | }; 130 | errdefer owner.allocator.free(self.config.title); 131 | 132 | try owner.platform.window.init(&self.native, owner, config); 133 | errdefer owner.platform.window.deinit(&self.native); 134 | } 135 | 136 | pub fn destroy(self: *Window) void { 137 | self.deinit(); 138 | self.owner.allocator.destroy(self); 139 | } 140 | pub fn deinit(self: *Window) void { 141 | self.setMouseConfined(false); 142 | self.owner.allocator.free(self.config.title); 143 | self.owner.platform.window.deinit(&self.native); 144 | } 145 | 146 | pub fn createMessageBox(owner: *Zwl, config: MBConfig) Error!MBButton { 147 | return owner.platform.window.createMessageBox(owner, config); 148 | } 149 | 150 | pub const createGLContext = GLContext.create; 151 | 152 | pub fn getPosition(self: *Window, x: ?*u32, y: ?*u32) void { 153 | return self.owner.platform.window.getPosition(self, x, y); 154 | } 155 | pub fn setPosition(self: *Window, x: u32, y: u32) void { 156 | if (self.lastX == x and 157 | self.lastY == y) return; 158 | self.lastX = x; 159 | self.lastY = y; 160 | return self.owner.platform.window.setPosition(self, x, y); 161 | } 162 | pub fn getSize(self: *Window, w: ?*u32, h: ?*u32) void { 163 | if (w) |wp| wp.* = self.config.width; 164 | if (h) |hp| hp.* = self.config.height; 165 | } 166 | pub fn setSize(self: *Window, w: u32, h: u32) void { 167 | if (self.config.width == w and 168 | self.config.height == h) return; 169 | 170 | const sl = self.config.sizeLimits; 171 | const width = std.math.clamp( 172 | w, 173 | sl.wmin orelse 0, 174 | sl.wmax orelse std.math.maxInt(u32), 175 | ); 176 | const height = std.math.clamp( 177 | h, 178 | sl.wmin orelse 0, 179 | sl.wmax orelse std.math.maxInt(u32), 180 | ); 181 | 182 | self.config.width = width; 183 | self.config.height = height; 184 | 185 | if (!self.config.flags.resizable) { 186 | return; 187 | } 188 | return self.owner.platform.window.setSize(self, width, height); 189 | } 190 | pub fn setSizeLimits(self: *Window, wmin: ?u32, wmax: ?u32, hmin: ?u32, hmax: ?u32) void { 191 | std.debug.assert((wmin orelse 0) < (wmax orelse MAX_U32)); 192 | std.debug.assert((hmin orelse 0) < (hmax orelse MAX_U32)); 193 | 194 | self.config.sizeLimits = .{ 195 | .wmin = wmin, 196 | .wmax = wmax, 197 | .hmin = hmin, 198 | .hmax = hmax, 199 | }; 200 | 201 | if (!self.config.flags.resizable) { 202 | return; 203 | } 204 | 205 | return self.owner.platform.window.setSizeLimits(self, wmin, wmax, hmin, hmax); 206 | } 207 | pub fn getFramebufferSize(self: *Window, x: ?*u32, y: ?*u32) void { 208 | return self.owner.platform.window.getFramebufferSize(self, x, y); 209 | } 210 | pub fn setVisible(self: *Window, value: bool) void { 211 | if (self.config.flags.hidden == !value) { 212 | return; 213 | } 214 | self.config.flags.hidden = !value; 215 | return self.owner.platform.window.setVisible(self, value); 216 | } 217 | pub fn setTitle(self: *Window, title: []const u8) Error!void { 218 | if (std.mem.eql(u8, title, self.config.title)) { 219 | return; 220 | } 221 | const title_copy = self.owner.allocator.dupe(u8, title) catch |e| { 222 | return self.owner.setError("Cannot copy window title", .{}, e); 223 | }; 224 | self.owner.allocator.free(self.config.title); 225 | self.config.title = title_copy; 226 | return self.owner.platform.window.setTitle(self, title); 227 | } 228 | /// The returned string is allocated via the allocator 229 | /// given to `Zwl.init()`. 230 | pub fn getTitle(self: *Window) []const u8 { 231 | return self.config.title; 232 | } 233 | pub fn isFocused(self: *Window) bool { 234 | return self.owner.platform.window.isFocused(self); 235 | } 236 | pub fn setMousePos(self: *Window, x: u32, y: u32) void { 237 | if (self.mouse.lastX == x and 238 | self.mouse.lastY == y) return; 239 | self.mouse = .{ 240 | .lastX = @intCast(x), 241 | .lastY = @intCast(y), 242 | }; 243 | return self.owner.platform.window.setMousePos(self, x, y); 244 | } 245 | pub fn getMousePos(self: *Window, x: ?*u32, y: ?*u32) void { 246 | return self.owner.platform.window.getMousePos(self, x, y); 247 | } 248 | pub fn setMouseVisible(self: *Window, value: bool) void { 249 | if (self.config.flags.hideMouse == !value) return; 250 | self.config.flags.hideMouse = !value; 251 | return self.owner.platform.window.setMouseVisible(self, value); 252 | } 253 | pub fn getKey(self: *Window, key: Key) bool { 254 | return self.keys[@intFromEnum(key)]; 255 | } 256 | pub fn hasFocus(self: *Window) bool { 257 | return self.config.flags.hasFocus; 258 | } 259 | pub fn setFocus(self: *Window) void { 260 | if (self.config.flags.hasFocus) return; 261 | self.config.flags.hasFocus = true; 262 | self.owner.platform.window.setFocus(self); 263 | } 264 | pub fn setMouseConfined(self: *Window, value: bool) void { 265 | self.owner.platform.window.setMouseConfined(self, value); 266 | } 267 | pub fn getButton(self: *Window, button: u8) bool { 268 | return button < self.mouseButtons.len and self.mouseButtons[button]; 269 | } 270 | }; 271 | -------------------------------------------------------------------------------- /src/windows/context.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Zwl = @import("../Zwl.zig"); 3 | const internal = @import("init.zig"); 4 | const W32 = @import("w32.zig"); 5 | 6 | const Window = Zwl.Window; 7 | const Error = Zwl.Error; 8 | const Event = Zwl.Event; 9 | 10 | pub const PFD = W32.PIXELFORMATDESCRIPTOR{ 11 | .nVersion = 1, 12 | .dwFlags = W32.PFD_DRAW_TO_WINDOW | 13 | W32.PFD_SUPPORT_OPENGL | 14 | W32.PFD_DOUBLEBUFFER, 15 | .iPixelType = W32.PFD_TYPE_RGBA, 16 | .cColorBits = 24, 17 | .cDepthBits = 8, 18 | .cStencilBits = 0, 19 | .cAuxBuffers = 0, 20 | .iLayerType = 0, //W32.PFD_MAIN_PLANE, 21 | }; 22 | 23 | pub const GLContext = struct { 24 | threadlocal var currentContext: ?GLContext = null; 25 | 26 | dc: W32.HDC, 27 | handle: W32.HGLRC, 28 | interval: i32, 29 | 30 | pub fn init(self: *GLContext, lib: *Zwl, window: *Window, config: Zwl.GLContext.Config) Error!void { 31 | const dc = W32.GetDC(window.native.handle) orelse { 32 | return lib.setError("Cannot get device context from window", .{}, Error.Win32); 33 | }; 34 | self.dc = dc; 35 | 36 | const format: i32 = if (@as(u56, @bitCast(config.pixelFormat)) != 0) blk: { 37 | if (lib.native.wglChoosePixelFormatARB) |wglChoosePixelFormatARB| { 38 | const attribs = [_:.{ 0, 0 }][2]i32{ 39 | .{ W32.WGL_DRAW_TO_WINDOW_ARB, 1 }, 40 | .{ W32.WGL_SUPPORT_OPENGL_ARB, 1 }, 41 | .{ W32.WGL_DOUBLE_BUFFER_ARB, 1 }, 42 | .{ W32.WGL_PIXEL_TYPE_ARB, W32.WGL_TYPE_RGBA_ARB }, 43 | .{ W32.WGL_COLOR_BITS_ARB, 24 }, 44 | .{ W32.WGL_RED_BITS_ARB, config.pixelFormat.redBits }, 45 | .{ W32.WGL_GREEN_BITS_ARB, config.pixelFormat.greenBits }, 46 | .{ W32.WGL_BLUE_BITS_ARB, config.pixelFormat.blueBits }, 47 | .{ W32.WGL_ALPHA_BITS_ARB, config.pixelFormat.alphaBits }, 48 | .{ W32.WGL_STENCIL_BITS_ARB, config.pixelFormat.stencilBits }, 49 | .{ W32.WGL_DEPTH_BITS_ARB, config.pixelFormat.depthBits }, 50 | .{ W32.WGL_SAMPLE_BUFFERS_ARB, 1 }, 51 | .{ W32.WGL_SAMPLES_ARB, config.pixelFormat.samples }, 52 | }; 53 | var nFormats: u32 = undefined; 54 | var result: i32 = undefined; 55 | if (wglChoosePixelFormatARB( 56 | dc, 57 | &attribs, 58 | null, 59 | 1, 60 | @ptrCast(&result), 61 | &nFormats, 62 | ) == 0) { 63 | return lib.setError("Cannot find suitable pixel format", .{}, Error.Win32); 64 | } 65 | break :blk result; 66 | } else { 67 | return lib.setError("wglChoosePixelFormatARB unavailable while requested specific pixel format", .{}, Error.Win32); 68 | } 69 | } else W32.ChoosePixelFormat(dc, &PFD); 70 | 71 | if (W32.SetPixelFormat(dc, format, &PFD) == 0) { 72 | return lib.setError("Cannot set pixel format for device context: {d}", .{W32.GetLastError()}, Error.Win32); 73 | } 74 | 75 | if (config.version.api == .opengl and lib.native.wglCreateContextAttribsARB == null) { 76 | if (config.forward) { 77 | return lib.setError("Cannot set forward compatibility without WGL_ARB_create_context (unavailable)", .{}, Error.Win32); 78 | } 79 | if (config.profile != .any) { 80 | return lib.setError("Cannot set opengl profile without WGL_ARB_create_context_profile (unavailable)", .{}, Error.Win32); 81 | } 82 | } else if (config.version.api == .opengl_es) { 83 | @panic("OpenGL ES not yet implemented"); 84 | } 85 | 86 | if (lib.native.wglCreateContextAttribsARB) |wglCreateContextAttribsARB| { 87 | var attribs: [4:.{ 0, 0 }][2]i32 = undefined; 88 | var index: u32 = 0; 89 | var mask: u32 = 0; 90 | var flags: u32 = 0; 91 | 92 | if (config.version.api == .opengl) { 93 | if (config.forward) { 94 | flags |= W32.WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; 95 | } 96 | 97 | if (config.profile == .core) { 98 | mask |= W32.WGL_CONTEXT_CORE_PROFILE_BIT_ARB; 99 | } else if (config.profile == .compat) { 100 | mask |= W32.WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; 101 | } 102 | } else { 103 | @panic("OpenGL ES not yet implemented"); 104 | } 105 | 106 | if (config.version.major != 0 or 107 | config.version.minor != 0) 108 | { 109 | std.debug.assert(config.version.major != 0); 110 | attribs[index] = .{ W32.WGL_CONTEXT_MAJOR_VERSION_ARB, config.version.major }; 111 | attribs[index + 1] = .{ W32.WGL_CONTEXT_MINOR_VERSION_ARB, config.version.minor }; 112 | index += 2; 113 | } 114 | 115 | if (config.debug) { 116 | flags |= W32.WGL_CONTEXT_DEBUG_BIT_ARB; 117 | } 118 | 119 | if (flags != 0) { 120 | attribs[index] = .{ W32.WGL_CONTEXT_FLAGS_ARB, @bitCast(flags) }; 121 | index += 1; 122 | } 123 | if (mask != 0) { 124 | attribs[index] = .{ W32.WGL_CONTEXT_PROFILE_MASK_ARB, @bitCast(mask) }; 125 | index += 1; 126 | } 127 | 128 | self.handle = wglCreateContextAttribsARB( 129 | dc, 130 | if (config.share) |share| share.native.handle else null, 131 | @ptrCast(&attribs), 132 | ) orelse { 133 | switch (W32.GetLastError()) { 134 | @as(i32, @truncate(0xc0070000)) | W32.ERROR_INVALID_VERSION_ARB => { 135 | if (config.version.api == .opengl) { 136 | return lib.setError( 137 | "Driver does not support OpenGL {d}.{d}", 138 | .{ config.version.major, config.version.minor }, 139 | Error.Win32, 140 | ); 141 | } else { 142 | return lib.setError( 143 | "Driver does not support OpenGL ES {d}.{d}", 144 | .{ config.version.major, config.version.minor }, 145 | Error.Win32, 146 | ); 147 | } 148 | }, 149 | @as(i32, @truncate(0xc0070000)) | W32.ERROR_INVALID_PROFILE_ARB => { 150 | return lib.setError( 151 | "Driver does not support requested OpenGL profile", 152 | .{}, 153 | Error.Win32, 154 | ); 155 | }, 156 | @as(i32, @truncate(0xc0070000)) | W32.ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB => { 157 | return lib.setError( 158 | "The share context is not compatible with the requested context", 159 | .{}, 160 | Error.Win32, 161 | ); 162 | }, 163 | else => { 164 | if (config.version.api == .opengl) { 165 | return lib.setError( 166 | "Failed to create OpenGL context", 167 | .{}, 168 | Error.Win32, 169 | ); 170 | } else { 171 | return lib.setError( 172 | "Failed to create OpenGL ES context", 173 | .{}, 174 | Error.Win32, 175 | ); 176 | } 177 | }, 178 | } 179 | }; 180 | return; 181 | } 182 | 183 | self.handle = W32.wglCreateContext(dc) orelse { 184 | return lib.setError("Cannot create WGL context", .{}, Error.Win32); 185 | }; 186 | errdefer _ = W32.wglDeleteContext(self.handle); 187 | 188 | if (config.share) |share| { 189 | if (W32.wglShareLists(share.native.handle, self.handle) == 0) { 190 | return lib.setError( 191 | "Failed to enable sharing with specified OpenGL context", 192 | .{}, 193 | Error.Win32, 194 | ); 195 | } 196 | } 197 | } 198 | pub fn deinit(self: *GLContext) void { 199 | _ = W32.wglDeleteContext(self.handle); 200 | } 201 | 202 | pub fn makeCurrent(lib: *Zwl, opt_ctx: ?*Zwl.GLContext) Error!void { 203 | _ = lib; 204 | currentContext = null; 205 | if (opt_ctx) |ctx| { 206 | if (W32.wglMakeCurrent(ctx.native.dc, ctx.native.handle) == 0) { 207 | return ctx.owner.owner.setError("Failed to make GLContext current", .{}, Error.Win32); 208 | } 209 | currentContext = ctx.native; 210 | } else _ = W32.wglMakeCurrent(undefined, null); 211 | } 212 | 213 | pub fn swapBuffers(ctx: *Zwl.GLContext) Error!void { 214 | _ = W32.SwapBuffers(ctx.native.dc); 215 | } 216 | 217 | pub fn swapInterval(lib: *Zwl, interval: i32) Error!void { 218 | if (lib.native.wglSwapIntervalEXT) |wglSwapIntervalEXT| { 219 | if (wglSwapIntervalEXT(interval) == 0) { 220 | return lib.setError("Cannot find current context", .{}, Error.Win32); 221 | } 222 | } else { 223 | return lib.setError("swapInterval requires wglSwapIntervalEXT (unavailable)", .{}, Error.Win32); 224 | } 225 | } 226 | }; 227 | -------------------------------------------------------------------------------- /src/windows/init.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Zwl = @import("../Zwl.zig"); 3 | const W32 = @import("w32.zig"); 4 | const window = @import("window.zig"); 5 | const event = @import("event.zig"); 6 | const context = @import("context.zig"); 7 | 8 | const unicode = std.unicode; 9 | const Allocator = std.mem.Allocator; 10 | 11 | const Platform = Zwl.Platform; 12 | const Error = Zwl.Error; 13 | const Key = Zwl.Key; 14 | 15 | var initCount: u32 = 0; 16 | 17 | pub const WND_CLASS_NAME = utf8ToUtf16Z(undefined, "ZWL_WND") catch unreachable; 18 | 19 | pub const KEYCODES: [512]Key = blk: { 20 | var keycodes = [_]Key{.unkown} ** 512; 21 | 22 | keycodes[0x002] = .@"1"; 23 | keycodes[0x003] = .@"2"; 24 | keycodes[0x004] = .@"3"; 25 | keycodes[0x005] = .@"4"; 26 | keycodes[0x006] = .@"5"; 27 | keycodes[0x007] = .@"6"; 28 | keycodes[0x008] = .@"7"; 29 | keycodes[0x009] = .@"8"; 30 | keycodes[0x00A] = .@"9"; 31 | keycodes[0x00B] = .@"0"; 32 | keycodes[0x01E] = .a; 33 | keycodes[0x030] = .b; 34 | keycodes[0x02E] = .c; 35 | keycodes[0x020] = .d; 36 | keycodes[0x012] = .e; 37 | keycodes[0x021] = .f; 38 | keycodes[0x022] = .g; 39 | keycodes[0x023] = .h; 40 | keycodes[0x017] = .i; 41 | keycodes[0x024] = .j; 42 | keycodes[0x025] = .k; 43 | keycodes[0x026] = .l; 44 | keycodes[0x032] = .m; 45 | keycodes[0x031] = .n; 46 | keycodes[0x018] = .o; 47 | keycodes[0x019] = .p; 48 | keycodes[0x010] = .q; 49 | keycodes[0x013] = .r; 50 | keycodes[0x01F] = .s; 51 | keycodes[0x014] = .t; 52 | keycodes[0x016] = .u; 53 | keycodes[0x02F] = .v; 54 | keycodes[0x011] = .w; 55 | keycodes[0x02D] = .x; 56 | keycodes[0x015] = .y; 57 | keycodes[0x02C] = .z; 58 | 59 | keycodes[0x028] = .apostrophe; 60 | keycodes[0x02B] = .backslash; 61 | keycodes[0x033] = .comma; 62 | keycodes[0x00D] = .equal; 63 | keycodes[0x029] = .grave_accent; 64 | keycodes[0x01A] = .left_bracket; 65 | keycodes[0x00C] = .minus; 66 | keycodes[0x034] = .period; 67 | keycodes[0x01B] = .right_bracket; 68 | keycodes[0x027] = .semicolon; 69 | keycodes[0x035] = .slash; 70 | keycodes[0x056] = .world_2; 71 | 72 | keycodes[0x00E] = .backspace; 73 | keycodes[0x153] = .delete; 74 | keycodes[0x14F] = .end; 75 | keycodes[0x01C] = .enter; 76 | keycodes[0x001] = .escape; 77 | keycodes[0x147] = .home; 78 | keycodes[0x152] = .insert; 79 | keycodes[0x15D] = .menu; 80 | keycodes[0x151] = .page_down; 81 | keycodes[0x149] = .page_up; 82 | keycodes[0x045] = .pause; 83 | keycodes[0x039] = .space; 84 | keycodes[0x00F] = .tab; 85 | keycodes[0x03A] = .caps_lock; 86 | keycodes[0x145] = .num_lock; 87 | keycodes[0x046] = .scroll_lock; 88 | keycodes[0x03B] = .f1; 89 | keycodes[0x03C] = .f2; 90 | keycodes[0x03D] = .f3; 91 | keycodes[0x03E] = .f4; 92 | keycodes[0x03F] = .f5; 93 | keycodes[0x040] = .f6; 94 | keycodes[0x041] = .f7; 95 | keycodes[0x042] = .f8; 96 | keycodes[0x043] = .f9; 97 | keycodes[0x044] = .f10; 98 | keycodes[0x057] = .f11; 99 | keycodes[0x058] = .f12; 100 | keycodes[0x064] = .f13; 101 | keycodes[0x065] = .f14; 102 | keycodes[0x066] = .f15; 103 | keycodes[0x067] = .f16; 104 | keycodes[0x068] = .f17; 105 | keycodes[0x069] = .f18; 106 | keycodes[0x06A] = .f19; 107 | keycodes[0x06B] = .f20; 108 | keycodes[0x06C] = .f21; 109 | keycodes[0x06D] = .f22; 110 | keycodes[0x06E] = .f23; 111 | keycodes[0x076] = .f24; 112 | keycodes[0x038] = .left_alt; 113 | keycodes[0x01D] = .left_control; 114 | keycodes[0x02A] = .left_shift; 115 | keycodes[0x15B] = .left_super; 116 | keycodes[0x137] = .print_screen; 117 | keycodes[0x138] = .right_alt; 118 | keycodes[0x11D] = .right_control; 119 | keycodes[0x036] = .right_shift; 120 | keycodes[0x15C] = .right_super; 121 | keycodes[0x150] = .down; 122 | keycodes[0x14B] = .left; 123 | keycodes[0x14D] = .right; 124 | keycodes[0x148] = .up; 125 | 126 | keycodes[0x052] = .kp_0; 127 | keycodes[0x04F] = .kp_1; 128 | keycodes[0x050] = .kp_2; 129 | keycodes[0x051] = .kp_3; 130 | keycodes[0x04B] = .kp_4; 131 | keycodes[0x04C] = .kp_5; 132 | keycodes[0x04D] = .kp_6; 133 | keycodes[0x047] = .kp_7; 134 | keycodes[0x048] = .kp_8; 135 | keycodes[0x049] = .kp_9; 136 | keycodes[0x04E] = .kp_add; 137 | keycodes[0x053] = .kp_decimal; 138 | keycodes[0x135] = .kp_divide; 139 | keycodes[0x11C] = .kp_enter; 140 | keycodes[0x059] = .kp_equal; 141 | keycodes[0x037] = .kp_multiply; 142 | keycodes[0x04A] = .kp_subtract; 143 | 144 | break :blk keycodes; 145 | }; 146 | pub const SCANCODES: [@intFromEnum(Key.last)]u16 = blk: { 147 | var res = [_]u16{0xFFFF} ** @intFromEnum(Key.last); 148 | for (0..512) |scancode| { 149 | if (KEYCODES[scancode] != .unkown) { 150 | res[@intFromEnum(KEYCODES[scancode])] = scancode; 151 | } 152 | } 153 | break :blk res; 154 | }; 155 | 156 | pub const NativeData = struct { 157 | hInstance: W32.HINSTANCE, 158 | /// Used to query WGL extensions 159 | helperWindow: struct { 160 | handle: W32.HWND, 161 | dc: W32.HDC, 162 | glrc: W32.HGLRC, 163 | }, 164 | wglCreateContextAttribsARB: ?*const fn (hDC: W32.HDC, hShareContext: ?W32.HGLRC, attribList: [*:.{0,0}]const [2]i32) callconv(W32.WINAPI) ?W32.HGLRC, 165 | wglChoosePixelFormatARB: ?*const fn (hDC: W32.HDC, piAttribIList: ?[*:.{0,0}]const [2]i32, pfAttribFList: ?[*]const f32, nMaxFormats: u32, piFormats: [*]i32, nNumFormats: *u32) callconv(W32.WINAPI) W32.BOOL, 166 | wglSwapIntervalEXT: ?*const fn (interval: i32) callconv(W32.WINAPI) W32.BOOL, 167 | keynames: [@intFromEnum(Key.last)][10:0]u8, 168 | }; 169 | 170 | pub inline fn utf8ToUtf16(allocator: Allocator, utf8: []const u8) error{ InvalidUtf8, OutOfMemory }![]const u16 { 171 | if (@inComptime()) comptime { 172 | return unicode.utf8ToUtf16LeStringLiteral(utf8); 173 | } else { 174 | return unicode.utf8ToUtf16LeAlloc(allocator, utf8); 175 | } 176 | } 177 | 178 | pub inline fn utf8ToUtf16Z(allocator: Allocator, utf8: []const u8) error{ InvalidUtf8, OutOfMemory }![:0]const u16 { 179 | if (@inComptime()) comptime { 180 | return unicode.utf8ToUtf16LeStringLiteral(utf8); 181 | } else { 182 | return unicode.utf8ToUtf16LeAllocZ(allocator, utf8); 183 | } 184 | } 185 | 186 | pub inline fn utf16ToUtf8(allocator: Allocator, utf16: []const u16) error{ InvalidUtf16, OutOfMemory }![]const u16 { 187 | return unicode.utf16LeToUtf8Alloc(allocator, utf16) catch error.InvalidUtf16; 188 | } 189 | 190 | pub inline fn utf16ToUtf8Z(allocator: Allocator, utf16: []const u16) error{ InvalidUtf16, OutOfMemory }![:0]const u16 { 191 | return unicode.utf16LeToUtf8AllocZ(allocator, utf16) catch error.InvalidUtf16; 192 | } 193 | 194 | pub fn updateKeyNames(native: *NativeData) void { 195 | var state = [_]u8{0} ** 256; 196 | @memset(&native.keynames, [_:0]u8{0} ** (@sizeOf(@TypeOf(native.keynames[0])) - 1)); 197 | for (@intFromEnum(Key.space)..@intFromEnum(Key.last)) |key_int| { 198 | const scancode = SCANCODES[key_int]; 199 | if (scancode == 0xFFFF) continue; 200 | 201 | const vks = [_]W32.UINT{ W32.VK_NUMPAD0, W32.VK_NUMPAD1, W32.VK_NUMPAD2, W32.VK_NUMPAD3, W32.VK_NUMPAD4, W32.VK_NUMPAD5, W32.VK_NUMPAD6, W32.VK_NUMPAD7, W32.VK_NUMPAD8, W32.VK_NUMPAD9, W32.VK_DECIMAL, W32.VK_DIVIDE, W32.VK_MULTIPLY, W32.VK_SUBTRACT, W32.VK_ADD }; 202 | 203 | const vk = if (key_int >= @intFromEnum(Key.kp_0) and key_int <= @intFromEnum(Key.kp_add)) 204 | vks[key_int - @intFromEnum(Key.kp_0)] 205 | else 206 | W32.MapVirtualKeyW(scancode, W32.MAPVK_VSC_TO_VK); 207 | 208 | var chars: [16]u16 = undefined; 209 | var length = W32.ToUnicode( 210 | vk, 211 | scancode, 212 | &state, 213 | @ptrCast(&chars), 214 | chars.len, 215 | 0, 216 | ); 217 | if (length == -1) { 218 | length = W32.ToUnicode( 219 | vk, 220 | scancode, 221 | &state, 222 | @ptrCast(&chars), 223 | chars.len + 1, 224 | 0, 225 | ); 226 | } 227 | if (length < 1) return; 228 | 229 | const size = std.unicode.utf16LeToUtf8( 230 | &native.keynames[key_int], 231 | std.mem.span(@as([*:0]const u16, @ptrCast(&chars))), 232 | ) catch continue; 233 | native.keynames[key_int][size] = 0; 234 | } 235 | } 236 | 237 | pub fn init(lib: *Zwl, _: Zwl.Config) Error!void { 238 | const native = &lib.native; 239 | 240 | const hInstance: W32.HINSTANCE = @ptrCast(W32.GetModuleHandleW(null)); 241 | native.hInstance = hInstance; 242 | 243 | if (initCount == 0 and W32.RegisterClassExW(&.{ 244 | .style = W32.CS_HREDRAW | W32.CS_VREDRAW | W32.CS_OWNDC, 245 | .lpfnWndProc = &window.windowProc, 246 | .hInstance = hInstance, 247 | .hCursor = W32.LoadCursorW(null, W32.IDC_ARROW), 248 | .lpszClassName = WND_CLASS_NAME.ptr, 249 | }) == 0) return lib.setError("Cannot register window class", .{}, Error.Win32); 250 | initCount += 1; 251 | 252 | const helperWindow = &native.helperWindow; 253 | const hWindow = W32.CreateWindowExW( 254 | 0, 255 | WND_CLASS_NAME.ptr, 256 | comptime (utf8ToUtf16Z(undefined, "ZWL helper window") catch unreachable).ptr, 257 | 0, 258 | 0, 259 | 0, 260 | 1, 261 | 1, 262 | null, 263 | null, 264 | hInstance, 265 | null, 266 | ) orelse { 267 | return lib.setError("Cannot create helper window", .{}, Error.Win32); 268 | }; 269 | errdefer _ = W32.DestroyWindow(hWindow); 270 | _ = W32.ShowWindow(hWindow, W32.SW_HIDE); 271 | helperWindow.handle = hWindow; 272 | 273 | { // create helper window opengl context 274 | const dc = W32.GetDC(hWindow) orelse { 275 | return lib.setError("Cannot get device context from helper window", .{}, Error.Win32); 276 | }; 277 | helperWindow.dc = dc; 278 | 279 | if (W32.SetPixelFormat(dc, W32.ChoosePixelFormat(dc, &context.PFD), &context.PFD) == 0) { 280 | return lib.setError("Cannot set pixel format for device context", .{}, Error.Win32); 281 | } 282 | 283 | const glrc = W32.wglCreateContext(dc) orelse { 284 | return lib.setError("Cannot create WGL context", .{}, Error.Win32); 285 | }; 286 | errdefer _ = W32.wglDeleteContext(glrc); 287 | helperWindow.glrc = glrc; 288 | 289 | _ = W32.wglMakeCurrent(dc, glrc); 290 | 291 | native.wglCreateContextAttribsARB = @ptrCast(W32.wglGetProcAddress("wglCreateContextAttribsARB")); 292 | native.wglChoosePixelFormatARB = @ptrCast(W32.wglGetProcAddress("wglChoosePixelFormatARB")); 293 | native.wglSwapIntervalEXT = @ptrCast(W32.wglGetProcAddress("wglSwapIntervalEXT")); 294 | 295 | _ = W32.wglMakeCurrent(undefined, null); 296 | } 297 | 298 | updateKeyNames(native); 299 | } 300 | 301 | pub fn deinit(lib: *Zwl) void { 302 | initCount -= 1; 303 | _ = W32.wglDeleteContext(lib.native.helperWindow.glrc); 304 | _ = W32.DestroyWindow(lib.native.helperWindow.handle); 305 | if (initCount == 0) { 306 | _ = W32.UnregisterClassW(WND_CLASS_NAME.ptr, lib.native.hInstance); 307 | } 308 | } 309 | 310 | pub fn keyName(lib: *const Zwl, key: Key) [:0]const u8 { 311 | return std.mem.span(@as([*:0]const u8, @ptrCast(&lib.native.keynames[@intFromEnum(key)]))); 312 | } 313 | -------------------------------------------------------------------------------- /src/windows/window.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const Zwl = @import("../Zwl.zig"); 3 | const internal = @import("init.zig"); 4 | const W32 = @import("w32.zig"); 5 | const event = @import("event.zig"); 6 | 7 | const assert = std.debug.assert; 8 | const math = std.math; 9 | const clamp = math.clamp; 10 | 11 | const Error = Zwl.Error; 12 | const Window = Zwl.Window; 13 | const Event = Zwl.Event; 14 | const Key = Zwl.Key; 15 | 16 | pub const WND_PTR_PROP_NAME = internal.utf8ToUtf16Z(undefined, "ZWL") catch unreachable; 17 | 18 | const MAX_U32 = math.maxInt(u32); 19 | 20 | pub const NativeWindow = struct { 21 | handle: W32.HWND, 22 | dc: W32.HDC, 23 | 24 | pub fn init(self: *NativeWindow, lib: *Zwl, config: Window.Config) Error!void { 25 | const window: *Window = @fieldParentPtr("native", self); 26 | var aa = std.heap.ArenaAllocator.init(window.owner.allocator); 27 | defer _ = aa.reset(.free_all); 28 | const arena = aa.allocator(); 29 | 30 | const wideTitle = internal.utf8ToUtf16Z(arena, config.title) catch |e| { 31 | return lib.setError("Cannot create wide title for Win32", .{}, e); 32 | }; 33 | 34 | const realFlags = blk: { 35 | const sizeLimits = config.sizeLimits; 36 | var flags = config.flags; 37 | if (!flags.noDecoration and 38 | sizeLimits.wmin != null and sizeLimits.wmax != null and 39 | sizeLimits.hmin != null and sizeLimits.hmax != null and 40 | sizeLimits.wmin == sizeLimits.wmax and 41 | sizeLimits.hmin == sizeLimits.hmax) 42 | { 43 | flags.resizable = false; 44 | } 45 | break :blk flags; 46 | }; 47 | const style = windowFlagsToNative(realFlags); 48 | const exStyle = windowFlagsToExNative(config.flags); 49 | 50 | const width, const height = getWindowFullsize( 51 | style, 52 | exStyle, 53 | config.width, 54 | config.height, 55 | ); 56 | 57 | const handle = W32.CreateWindowExW( 58 | exStyle, 59 | internal.WND_CLASS_NAME.ptr, 60 | wideTitle.ptr, 61 | style, 62 | @bitCast(config.x.toNumber(@bitCast(W32.CW_USEDEFAULT))), 63 | @bitCast(config.y.toNumber(@bitCast(W32.CW_USEDEFAULT))), 64 | @intCast(width), 65 | @intCast(height), 66 | null, 67 | null, 68 | lib.native.hInstance, 69 | null, 70 | ) orelse { 71 | return lib.setError("Cannot create window", .{}, Error.Win32); 72 | }; 73 | errdefer _ = W32.DestroyWindow(handle); 74 | 75 | if (W32.SetPropW(handle, WND_PTR_PROP_NAME.ptr, @ptrCast(window)) == 0) { 76 | return lib.setError("Cannot set window property", .{}, Error.Win32); 77 | } 78 | 79 | self.handle = handle; 80 | self.dc = W32.GetDC(handle) orelse { 81 | return lib.setError("Cannot retreive window's device context", .{}, Error.Win32); 82 | }; 83 | 84 | window.setMouseVisible(!config.flags.hideMouse); 85 | } 86 | 87 | pub fn deinit(self: *NativeWindow) void { 88 | _ = W32.ReleaseDC(self.handle, self.dc); 89 | _ = W32.DestroyWindow(self.handle); 90 | } 91 | 92 | pub fn createMessageBox(lib: *Zwl, config: Window.MBConfig) Error!Window.MBButton { 93 | const wideTitle = internal.utf8ToUtf16Z(lib.allocator, config.title) catch |e| { 94 | return lib.setError("Cannot create wide title for Win32", .{}, e); 95 | }; 96 | defer lib.allocator.free(wideTitle); 97 | const wideText = internal.utf8ToUtf16Z(lib.allocator, config.text) catch |e| { 98 | return lib.setError("Cannot create wide text for Win32", .{}, e); 99 | }; 100 | defer lib.allocator.free(wideText); 101 | 102 | var uType: W32.UINT = 0; 103 | uType |= switch (config.mode) { 104 | .ok => 0, 105 | .okCancel => 1, 106 | .abortRetryIgnore => 2, 107 | .yesNoCancel => 3, 108 | .yesNo => 4, 109 | .retryCancel => 5, 110 | .cancelTryContinue => 6, 111 | }; 112 | uType |= switch (config.icon) { 113 | .none => 0, 114 | .@"error" => 0x10, 115 | .question => 0x20, 116 | .warning => 0x30, 117 | .information => 0x40, 118 | }; 119 | 120 | const ret = W32.MessageBoxW( 121 | if (config.parent) |p| p.native.handle else null, 122 | wideText.ptr, 123 | wideTitle.ptr, 124 | uType, 125 | ); 126 | return switch (ret) { 127 | 0 => lib.setError("Cannot create message box", .{}, Error.Win32), 128 | 1 => .ok, 129 | 2 => .cancel, 130 | 3 => .abort, 131 | 4 => .retry, 132 | 5 => .ignore, 133 | 6 => .yes, 134 | 7 => .no, 135 | 11 => .@"continue", 136 | 10 => .tryAgain, 137 | else => unreachable, 138 | }; 139 | } 140 | 141 | pub fn getPosition(window: *Window, x: ?*u32, y: ?*u32) void { 142 | var pt: W32.POINT = .{}; 143 | _ = W32.ClientToScreen(window.native.handle, &pt); 144 | 145 | { 146 | @setRuntimeSafety(false); 147 | if (x) |_| x.?.* = @bitCast(pt.x); 148 | if (y) |_| y.?.* = @bitCast(pt.y); 149 | } 150 | } 151 | 152 | pub fn setPosition(window: *Window, x: u32, y: u32) void { 153 | window.config.x = .{ .pos = x }; 154 | window.config.y = .{ .pos = y }; 155 | 156 | var rect = W32.RECT{ 157 | .left = @bitCast(x), 158 | .top = @bitCast(y), 159 | .right = @bitCast(x), 160 | .bottom = @bitCast(y), 161 | }; 162 | _ = W32.AdjustWindowRectEx( 163 | &rect, 164 | windowFlagsToNative(window.config.flags), 165 | W32.FALSE, 166 | windowFlagsToExNative(window.config.flags), 167 | ); 168 | 169 | _ = W32.SetWindowPos( 170 | window.native.handle, 171 | null, 172 | rect.bottom, 173 | rect.top, 174 | 0, 175 | 0, 176 | W32.SWP_NOACTIVATE | W32.SWP_NOZORDER | W32.SWP_NOSIZE, 177 | ); 178 | } 179 | 180 | pub fn setSize(window: *Window, w: u32, h: u32) void { 181 | var rect = W32.RECT{ 182 | .left = 0, 183 | .top = 0, 184 | .right = @intCast(w), 185 | .bottom = @intCast(h), 186 | }; 187 | 188 | _ = W32.AdjustWindowRectEx( 189 | &rect, 190 | windowFlagsToNative(window.config.flags), 191 | W32.FALSE, 192 | windowFlagsToExNative(window.config.flags), 193 | ); 194 | 195 | _ = W32.SetWindowPos( 196 | window.native.handle, 197 | W32.HWND_TOP, 198 | 0, 199 | 0, 200 | rect.right - rect.left, 201 | rect.bottom - rect.top, 202 | W32.SWP_NOACTIVATE | W32.SWP_NOOWNERZORDER | W32.SWP_NOMOVE | W32.SWP_NOZORDER, 203 | ); 204 | } 205 | 206 | pub fn setSizeLimits( 207 | window: *Window, 208 | wmin: ?u32, 209 | wmax: ?u32, 210 | hmin: ?u32, 211 | hmax: ?u32, 212 | ) void { 213 | if ((wmin == null and hmin == null) and 214 | (wmax == null or hmax == null)) 215 | { 216 | return; 217 | } 218 | 219 | var area: W32.RECT = undefined; 220 | 221 | _ = W32.GetWindowRect(window.native.handle, &area); 222 | 223 | _ = W32.MoveWindow( 224 | window.native.handle, 225 | area.left, 226 | area.top, 227 | area.right - area.left, 228 | area.bottom - area.top, 229 | W32.TRUE, 230 | ); 231 | } 232 | 233 | pub fn getFramebufferSize(window: *Window, w: ?*u32, h: ?*u32) void { 234 | var area: W32.RECT = .{}; 235 | _ = W32.GetClientRect(window.native.handle, &area); 236 | 237 | { 238 | @setRuntimeSafety(false); 239 | if (w) |_| w.?.* = @bitCast(area.right); 240 | if (h) |_| h.?.* = @bitCast(area.bottom); 241 | } 242 | } 243 | 244 | pub fn setVisible(window: *Window, value: bool) void { 245 | _ = W32.ShowWindow(window.native.handle, W32.SW_SHOWNA * @intFromBool(value)); 246 | } 247 | 248 | pub fn setTitle(window: *Window, title: []const u8) Error!void { 249 | const wideTitle = internal.utf8ToUtf16Z(window.owner.allocator, title) catch |e| { 250 | return window.owner.setError("Cannot create wide title for Win32", .{}, e); 251 | }; 252 | defer window.owner.allocator.free(wideTitle); 253 | 254 | _ = W32.SetWindowTextW(window.native.handle, wideTitle.ptr); 255 | } 256 | 257 | pub fn isFocused(window: *Window) bool { 258 | return window.native.handle == W32.GetActiveWindow(); 259 | } 260 | 261 | pub fn getMousePos(window: *Window, x: ?*u32, y: ?*u32) void { 262 | var pos: W32.POINT = undefined; 263 | if (W32.GetCursorPos(&pos) != 0) { 264 | _ = W32.ScreenToClient(window.native.handle, &pos); 265 | 266 | if (x) |xp| xp.* = @bitCast(pos.x); 267 | if (y) |yp| yp.* = @bitCast(pos.y); 268 | } 269 | } 270 | 271 | pub fn setMousePos(window: *Window, x: u32, y: u32) void { 272 | var pos: W32.POINT = .{ .x = @bitCast(x), .y = @bitCast(y) }; 273 | _ = W32.ClientToScreen(window.native.handle, &pos); 274 | _ = W32.SetCursorPos(pos.x, pos.y); 275 | } 276 | 277 | pub fn setMouseVisible(window: *Window, value: bool) void { 278 | _ = window; 279 | _ = W32.ShowCursor(@intFromBool(value)); 280 | } 281 | 282 | pub fn setFocus(window: *Window) void { 283 | _ = W32.SetFocus(window.native.handle); 284 | } 285 | 286 | pub fn setMouseConfined(window: *Window, value: bool) void { 287 | if (value) { 288 | var rect: W32.RECT = .{ 289 | .right = @intCast(window.config.width), 290 | .bottom = @intCast(window.config.height), 291 | }; 292 | _ = W32.ClientToScreen(window.native.handle, @ptrCast(&rect)); 293 | _ = W32.ClientToScreen(window.native.handle, @ptrCast(&rect.right)); 294 | _ = W32.ClipCursor(&rect); 295 | } else { 296 | _ = W32.ClipCursor(null); 297 | } 298 | } 299 | 300 | pub fn freeMouse(window: *Window) void { 301 | _ = window; 302 | _ = W32.ClipCursor(null); 303 | } 304 | 305 | pub fn getDC(window: *NativeWindow) ?W32.HDC { 306 | return W32.GetDC(window.handle); 307 | } 308 | }; 309 | 310 | pub fn windowProc(wind: W32.HWND, msg: W32.UINT, wp: W32.WPARAM, lp: W32.LPARAM) callconv(W32.CALLBACK) W32.LRESULT { 311 | const window: *Window = @ptrCast(@alignCast(W32.GetPropW(wind, WND_PTR_PROP_NAME.ptr) orelse { 312 | return W32.DefWindowProcW(wind, msg, wp, lp); 313 | })); 314 | 315 | return windowProcInner(wind, window, msg, wp, lp) catch |e| blk: { 316 | event.pollingError = e; 317 | break :blk 1; 318 | }; 319 | } 320 | 321 | fn windowProcInner(wind: W32.HWND, window: *Window, msg: W32.UINT, wp: W32.WPARAM, lp: W32.LPARAM) Error!W32.LRESULT { 322 | const lib = window.owner; 323 | 324 | switch (msg) { 325 | W32.WM_CLOSE => { 326 | try event.queueEvent(lib, .{ .windowClosed = window }); 327 | }, 328 | W32.WM_SIZE => { 329 | const width: u16 = @truncate(@as(u64, @bitCast(lp)) & 0xFFFF); 330 | const height: u16 = @truncate(@as(u64, @bitCast(lp >> 16)) & 0xFFFF); 331 | try event.queueEvent(lib, .{ .windowResized = .{ 332 | .window = window, 333 | .width = width, 334 | .height = height, 335 | } }); 336 | window.config.width = width; 337 | window.config.height = height; 338 | }, 339 | W32.WM_MOUSEMOVE => { 340 | const x: u16 = @truncate(@as(u64, @bitCast(lp)) & 0xFFFF); 341 | const y: u16 = @truncate(@as(u64, @bitCast(lp >> 16)) & 0xFFFF); 342 | 343 | const dx = @as(i16, @bitCast(x)) - @as(i16, @bitCast(window.mouse.lastX)); 344 | const dy = @as(i16, @bitCast(y)) - @as(i16, @bitCast(window.mouse.lastY)); 345 | try event.queueEvent(lib, .{ .mouseMoved = .{ 346 | .window = window, 347 | .x = x, 348 | .y = y, 349 | .dx = dx, 350 | .dy = dy, 351 | } }); 352 | 353 | window.mouse.lastX = x; 354 | window.mouse.lastY = y; 355 | }, 356 | W32.WM_LBUTTONDOWN, 357 | W32.WM_LBUTTONUP, 358 | W32.WM_RBUTTONDOWN, 359 | W32.WM_RBUTTONUP, 360 | W32.WM_MBUTTONDOWN, 361 | W32.WM_MBUTTONUP, 362 | W32.WM_XBUTTONDOWN, 363 | W32.WM_XBUTTONUP, 364 | => { 365 | const button: u8 = switch (msg) { 366 | W32.WM_LBUTTONDOWN, W32.WM_LBUTTONUP => 0, 367 | W32.WM_RBUTTONDOWN, W32.WM_RBUTTONUP => 2, 368 | W32.WM_MBUTTONDOWN, W32.WM_MBUTTONUP => 1, 369 | W32.WM_XBUTTONDOWN, W32.WM_XBUTTONUP => @truncate(((wp >> 16) & 0xFFFF) + 2), 370 | else => unreachable, 371 | }; 372 | const pressed: bool = switch (msg) { 373 | W32.WM_LBUTTONDOWN, W32.WM_RBUTTONDOWN, W32.WM_MBUTTONDOWN, W32.WM_XBUTTONDOWN => true, 374 | W32.WM_LBUTTONUP, W32.WM_RBUTTONUP, W32.WM_MBUTTONUP, W32.WM_XBUTTONUP => false, 375 | else => unreachable, 376 | }; 377 | const mods = getKeyMods(); 378 | window.mouseButtons[button] = pressed; 379 | try event.queueEvent(lib, .{ .mouseButton = .{ 380 | .window = window, 381 | .clicked = pressed, 382 | .button = button, 383 | .mods = .{ 384 | .control = mods.control, 385 | .shift = mods.shift, 386 | }, 387 | } }); 388 | }, 389 | W32.WM_MOUSEWHEEL => { 390 | try event.queueEvent(lib, .{ .mouseWheel = .{ 391 | .window = window, 392 | .x = 0, 393 | .y = @as(f32, @floatFromInt((wp >> 16) & 0xFFFF)) / 120, 394 | .mods = .{ 395 | .control = wp & 0x08 != 0, 396 | .shift = wp & 0x04 != 0, 397 | }, 398 | } }); 399 | }, 400 | W32.WM_MOUSEHWHEEL => { 401 | try event.queueEvent(lib, .{ .mouseWheel = .{ 402 | .window = window, 403 | .x = @as(f32, @floatFromInt((wp >> 16) & 0xFFFF)) / 120, 404 | .y = 0, 405 | .mods = .{ 406 | .control = wp & 0x08 != 0, 407 | .shift = wp & 0x04 != 0, 408 | }, 409 | } }); 410 | }, 411 | W32.WM_GETMINMAXINFO => { 412 | if (!window.config.flags.resizable) { 413 | return 0; 414 | } 415 | 416 | const mmi: *W32.MINMAXINFO = @ptrFromInt(@as(u64, @bitCast(lp))); 417 | const config = window.config; 418 | const sl = config.sizeLimits; 419 | 420 | // USER_DEFAULT_SCREEN_DPI 421 | // const dpi: W32.UINT = 96; 422 | 423 | const xoff, const yoff = getWindowFullsize( 424 | windowFlagsToNative(window.config.flags), 425 | windowFlagsToExNative(window.config.flags), 426 | 0, 427 | 0, 428 | ); 429 | 430 | if (sl.wmin) |wmin| { 431 | mmi.ptMinTrackSize.x = @bitCast(wmin + xoff); 432 | } 433 | if (sl.wmax) |wmax| { 434 | mmi.ptMinTrackSize.x = @bitCast(wmax + xoff); 435 | } 436 | if (sl.hmin) |hmin| { 437 | mmi.ptMinTrackSize.y = @bitCast(hmin + yoff); 438 | } 439 | if (sl.hmax) |hmax| { 440 | mmi.ptMinTrackSize.y = @bitCast(hmax + yoff); 441 | } 442 | }, 443 | W32.WM_KEYDOWN, 444 | W32.WM_KEYUP, 445 | W32.WM_SYSKEYDOWN, 446 | W32.WM_SYSKEYUP, 447 | => blk: { 448 | const lp_hiword = @as(u64, @bitCast(lp >> 16)) & 0xFFFF; 449 | 450 | var scancode: u32 = @truncate(lp_hiword & 0x01FF); 451 | var action: Key.Action = if (lp_hiword & 0x8000 != 0) 452 | .release 453 | else 454 | .press; 455 | const mods = getKeyMods(); 456 | 457 | if (scancode == 0) { 458 | scancode = @bitCast(W32.MapVirtualKeyW(@truncate(wp), 0)); 459 | } 460 | 461 | scancode = switch (scancode) { 462 | 0x54 => 0x137, 463 | 0x146 => 0x45, 464 | 0x136 => 0x36, 465 | else => scancode, 466 | }; 467 | 468 | var key = internal.KEYCODES[scancode]; 469 | 470 | if (wp == W32.VK_CONTROL) { 471 | if (lp_hiword & 0x0100 != 0) { 472 | key = .right_control; 473 | } else { 474 | var next: W32.MSG = undefined; 475 | const time = W32.GetMessageTime(); 476 | 477 | if (W32.PeekMessageW(&next, null, 0, 0, W32.PM_NOREMOVE) != 0) { 478 | if (next.message == W32.WM_KEYDOWN or 479 | next.message == W32.WM_SYSKEYDOWN or 480 | next.message == W32.WM_KEYUP or 481 | next.message == W32.WM_SYSKEYUP) 482 | { 483 | if (next.wParam == 0x12 and 484 | @as(u64, @bitCast(next.lParam >> 16)) & 0x0100 != 0 and 485 | next.time == time) 486 | { 487 | break :blk; 488 | } 489 | } 490 | } 491 | 492 | key = .left_control; 493 | } 494 | } else if (wp == W32.VK_PROCESSKEY) { 495 | break :blk; 496 | } 497 | 498 | var repeated: bool = false; 499 | 500 | if (action == .release and !window.keys[@intFromEnum(key)]) { 501 | break :blk; 502 | } 503 | 504 | if (action == .press and window.keys[@intFromEnum(key)]) { 505 | repeated = true; 506 | } 507 | 508 | window.keys[@intFromEnum(key)] = action == .press; 509 | 510 | if (repeated) 511 | action = .repeat; 512 | if (action == .release and wp == W32.VK_SHIFT) { 513 | try event.queueEvent(lib, .{ .key = .{ 514 | .window = window, 515 | .key = .left_shift, 516 | .action = action, 517 | .mods = mods, 518 | } }); 519 | try event.queueEvent(lib, .{ .key = .{ 520 | .window = window, 521 | .key = .right_shift, 522 | .action = action, 523 | .mods = mods, 524 | } }); 525 | } else if (wp == W32.VK_SNAPSHOT) { 526 | try event.queueEvent(lib, .{ .key = .{ 527 | .window = window, 528 | .key = key, 529 | .action = .press, 530 | .mods = mods, 531 | } }); 532 | try event.queueEvent(lib, .{ .key = .{ 533 | .window = window, 534 | .key = key, 535 | .action = .release, 536 | .mods = mods, 537 | } }); 538 | } else { 539 | try event.queueEvent(lib, .{ .key = .{ 540 | .window = window, 541 | .key = key, 542 | .action = action, 543 | .mods = mods, 544 | } }); 545 | } 546 | }, 547 | W32.WM_SETFOCUS, W32.WM_KILLFOCUS => { 548 | const status = msg == W32.WM_SETFOCUS; 549 | window.config.flags.hasFocus = status; 550 | try event.queueEvent(lib, .{ .windowFocused = .{ 551 | .window = window, 552 | .gained = status, 553 | } }); 554 | }, 555 | W32.WM_INPUTLANGCHANGE => { 556 | internal.updateKeyNames(&lib.native); 557 | }, 558 | else => {}, 559 | } 560 | 561 | return W32.DefWindowProcW(wind, msg, wp, lp); 562 | } 563 | fn getWindowFullsize( 564 | style: W32.DWORD, 565 | exStyle: W32.DWORD, 566 | contentWidth: u32, 567 | contentHeight: u32, 568 | ) struct { u32, u32 } { 569 | var rect: W32.RECT = .{ 570 | .left = 0, 571 | .top = 0, 572 | .right = @intCast(contentWidth), 573 | .bottom = @intCast(contentHeight), 574 | }; 575 | 576 | _ = W32.AdjustWindowRectEx(&rect, style, W32.FALSE, exStyle); 577 | 578 | return .{ 579 | @bitCast(rect.right - rect.left), 580 | @bitCast(rect.bottom - rect.top), 581 | }; 582 | } 583 | 584 | pub fn getKeyMods() Key.Mods { 585 | var mods: Key.Mods = .{}; 586 | 587 | if (W32.GetKeyState(0x10) & 0x8000 != 0) 588 | mods.shift = true; 589 | if (W32.GetKeyState(0x11) & 0x8000 != 0) 590 | mods.control = true; 591 | if (W32.GetKeyState(0x12) & 0x8000 != 0) 592 | mods.alt = true; 593 | if (W32.GetKeyState(0x5B) & 0x8000 != 0 and 594 | W32.GetKeyState(0x5C) & 0x8000 != 0) 595 | mods.super = true; 596 | if (W32.GetKeyState(0x14) & 1 != 0) 597 | mods.capsLock = true; 598 | if (W32.GetKeyState(0x90) & 1 != 0) 599 | mods.numLock = true; 600 | 601 | return mods; 602 | } 603 | 604 | fn windowFlagsToNative(flags: Window.Flags) W32.DWORD { 605 | var style = W32.WS_CLIPSIBLINGS | W32.WS_CLIPCHILDREN; 606 | 607 | if (flags.fullscreen) { 608 | style |= W32.WS_POPUP; 609 | } else { 610 | style |= W32.WS_SYSMENU | W32.WS_MINIMIZEBOX; 611 | 612 | if (flags.noDecoration) { 613 | style |= W32.WS_POPUP; 614 | } else { 615 | style |= W32.WS_CAPTION; 616 | 617 | if (flags.resizable) { 618 | style |= W32.WS_MAXIMIZEBOX | W32.WS_THICKFRAME; 619 | } 620 | } 621 | } 622 | 623 | return style; 624 | } 625 | 626 | fn windowFlagsToExNative(flags: Window.Flags) W32.DWORD { 627 | var style = W32.WS_EX_APPWINDOW; 628 | 629 | if (flags.fullscreen or flags.floating) { 630 | style |= W32.WS_EX_TOPMOST; 631 | } 632 | 633 | return style; 634 | } 635 | -------------------------------------------------------------------------------- /src/windows/w32.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const builtin = @import("builtin"); 3 | 4 | pub const CALLBACK: std.builtin.CallingConvention = if (builtin.cpu.arch == .x86) .Stdcall else .C; 5 | pub const WINAPI: std.builtin.CallingConvention = if (builtin.cpu.arch == .x86) .Stdcall else .C; 6 | pub const WINAPIV: std.builtin.CallingConvention = .C; 7 | pub const APIENTRY: std.builtin.CallingConvention = WINAPI; 8 | pub const APIPRIVATE: std.builtin.CallingConvention = if (builtin.cpu.arch == .x86) .Stdcall else .C; 9 | pub const PASCAL: std.builtin.CallingConvention = if (builtin.cpu.arch == .x86) .Stdcall else .C; 10 | 11 | pub const BOOL = i32; 12 | pub const BYTE = u8; 13 | pub const WORD = i16; 14 | pub const SHORT = u16; 15 | pub const ATOM = WORD; 16 | pub const DWORD = i32; 17 | pub const INT = i32; 18 | pub const UINT = u32; 19 | pub const INT_PTR = u64; 20 | pub const LONG = i32; 21 | pub const ULONG = i32; 22 | pub const LONG_PTR = i64; 23 | pub const ULONG_PTR = u64; 24 | pub const LRESULT = LONG_PTR; 25 | pub const LPARAM = LONG_PTR; 26 | pub const WPARAM = INT_PTR; 27 | pub const LPVOID = *anyopaque; 28 | pub const LPCWSTR = [*:0]align(1) const u16; 29 | pub const LPWSTR = [*:0]u16; 30 | pub const HANDLE = *anyopaque; 31 | pub const HINSTANCE = *opaque {}; 32 | pub const HMODULE = *opaque {}; 33 | pub const HWND = *opaque {}; 34 | pub const HICON = *opaque {}; 35 | pub const HBRUSH = *opaque {}; 36 | pub const HCURSOR = *opaque {}; 37 | pub const HDC = *opaque {}; 38 | pub const HGLRC = *opaque {}; 39 | pub const WNDPROC = *const fn (hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(CALLBACK) LRESULT; 40 | pub const PFTASKDIALOGCALLBACK = *const fn (hWnd: HWND, msg: UINT, wParam: WPARAM, lParam: LPARAM, lprefData: LONG_PTR) callconv(CALLBACK) HRESULT; 41 | 42 | pub const FALSE: BOOL = 0; 43 | pub const TRUE: BOOL = 1; 44 | 45 | pub const HWND_NOTOPMOST: HWND = @ptrFromInt(@as(usize, @truncate(-2))); 46 | pub const HWND_TOPMOSt: HWND = @ptrFromInt(@as(usize, @truncate(-1))); 47 | pub const HWND_TOP: ?HWND = @ptrFromInt(0); 48 | pub const HWND_BOTTOM: HWND = @ptrFromInt(1); 49 | pub const HWND_BROADCAST: HWND = @ptrFromInt(0xFFFF); 50 | 51 | pub const SWP_NOSIZE: UINT = 0x0001; 52 | pub const SWP_NOMOVE: UINT = 0x0002; 53 | pub const SWP_NOZORDER: UINT = 0x0004; 54 | pub const SWP_NOREDRAW: UINT = 0x0008; 55 | pub const SWP_NOACTIVATE: UINT = 0x0010; 56 | pub const SWP_FRAMECHANGED: UINT = 0x0020; 57 | pub const SWP_SHOWWINDOW: UINT = 0x0040; 58 | pub const SWP_HIDEWINDOW: UINT = 0x0080; 59 | pub const SWP_NOCOPYBITS: UINT = 0x0100; 60 | pub const SWP_NOOWNERZORDER: UINT = 0x0200; 61 | pub const SWP_NOSENDCHANGING: UINT = 0x0400; 62 | pub const SWP_DRAWFRAME: UINT = SWP_FRAMECHANGED; 63 | pub const SWP_NOREPOSITION: UINT = SWP_NOOWNERZORDER; 64 | pub const SWP_DEFERERASE: UINT = 0x2000; 65 | pub const SWP_ASYNCWINDOWPOS: UINT = 0x4000; 66 | 67 | pub const CW_USEDEFAULT: i32 = @truncate(0x80000000); 68 | 69 | pub const WS_OVERLAPPED: DWORD = 0x00000000; 70 | pub const WS_TILED: DWORD = 0x00000000; 71 | pub const WS_MAXIMIZEBOX: DWORD = 0x00010000; 72 | pub const WS_TABSTOP: DWORD = 0x00010000; 73 | pub const WS_GROUP: DWORD = 0x00020000; 74 | pub const WS_MINIMIZEBOX: DWORD = 0x00020000; 75 | pub const WS_THICKFRAME: DWORD = 0x00040000; 76 | pub const WS_SYSMENU: DWORD = 0x00080000; 77 | pub const WS_HSCROLL: DWORD = 0x00100000; 78 | pub const WS_VSCROLL: DWORD = 0x00200000; 79 | pub const WS_DLGFRAME: DWORD = 0x00400000; 80 | pub const WS_BORDER: DWORD = 0x00800000; 81 | pub const WS_CAPTION: DWORD = WS_BORDER | 0x00400000; 82 | pub const WS_MAXIMIZE: DWORD = 0x01000000; 83 | pub const WS_CLIPCHILDREN: DWORD = 0x02000000; 84 | pub const WS_CLIPSIBLINGS: DWORD = 0x04000000; 85 | pub const WS_DISABLED: DWORD = 0x08000000; 86 | pub const WS_VISIBLE: DWORD = 0x10000000; 87 | pub const WS_ICONIC: DWORD = 0x20000000; 88 | pub const WS_MINIMIZE: DWORD = 0x20000000; 89 | pub const WS_CHILD: DWORD = 0x40000000; 90 | pub const WS_CHILDWINDOW: DWORD = 0x40000000; 91 | pub const WS_POPUP: DWORD = @truncate(0x80000000); 92 | pub const WS_OVERLAPPEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); 93 | pub const WS_POPUPWINDOW = (WS_POPUP | WS_BORDER | WS_SYSMENU); 94 | pub const WS_TILEDWINDOW = (WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); 95 | 96 | pub const WS_EX_LEFT: DWORD = 0x00000000; 97 | pub const WS_EX_RIGHTSCROLLBAR: DWORD = 0x00000000; 98 | pub const WS_EX_LTRREADING: DWORD = 0x00000000; 99 | pub const WS_EX_DLGMODALFRAME: DWORD = 0x00000001; 100 | pub const WS_EX_NOPARENTNOTIFY: DWORD = 0x00000004; 101 | pub const WS_EX_TOPMOST: DWORD = 0x00000008; 102 | pub const WS_EX_ACCEPTFILES: DWORD = 0x00000010; 103 | pub const WS_EX_TRANSPARENT: DWORD = 0x00000020; 104 | pub const WS_EX_MDICHILD: DWORD = 0x00000040; 105 | pub const WS_EX_TOOLWINDOW: DWORD = 0x00000080; 106 | pub const WS_EX_WINDOWEDGE: DWORD = 0x00000100; 107 | pub const WS_EX_CLIENTEDGE: DWORD = 0x00000200; 108 | pub const WS_EX_CONTEXTHELP: DWORD = 0x00000400; 109 | pub const WS_EX_RIGHT: DWORD = 0x00001000; 110 | pub const WS_EX_RTLREADING: DWORD = 0x00002000; 111 | pub const WS_EX_LEFTSCROLLBAR: DWORD = 0x00004000; 112 | pub const WS_EX_CONTROLPARENT: DWORD = 0x00010000; 113 | pub const WS_EX_STATICEDGE: DWORD = 0x00020000; 114 | pub const WS_EX_APPWINDOW: DWORD = 0x00040000; 115 | pub const WS_EX_LAYERED: DWORD = 0x00080000; 116 | pub const WS_EX_NOINHERITLAYOUT: DWORD = 0x00100000; 117 | pub const WS_EX_NOREDIRECTIONBITMAP: DWORD = 0x00200000; 118 | pub const WS_EX_LAYOUTRTL: DWORD = 0x00400000; 119 | pub const WS_EX_COMPOSITED: DWORD = 0x02000000; 120 | pub const WS_EX_NOACTIVATE: DWORD = 0x08000000; 121 | pub const WS_EX_OVERLAPPEDWINDOW: DWORD = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); 122 | pub const WS_EX_PALETTEWINDOW: DWORD = (WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST); 123 | 124 | pub const CS_VREDRAW: UINT = 0x0001; 125 | pub const CS_HREDRAW: UINT = 0x0002; 126 | pub const CS_DBLCLKS: UINT = 0x0008; 127 | pub const CS_OWNDC: UINT = 0x0020; 128 | pub const CS_CLASSDC: UINT = 0x0040; 129 | pub const CS_PARENTDC: UINT = 0x0080; 130 | pub const CS_NOCLOSE: UINT = 0x0200; 131 | pub const CS_SAVEBITS: UINT = 0x0800; 132 | pub const CS_BYTEALIGNCLIENT: UINT = 0x1000; 133 | pub const CS_BYTEALIGNWINDOW: UINT = 0x2000; 134 | pub const CS_GLOBALCLASS: UINT = 0x4000; 135 | pub const CS_IME: UINT = 0x00010000; 136 | pub const CS_DROPSHADOW: UINT = 0x00020000; 137 | 138 | pub inline fn MAKEINTRESOURCE(i: u16) LPCWSTR { 139 | return @ptrFromInt(i); 140 | } 141 | 142 | pub const TD_WARNING_ICON = MAKEINTRESOURCE(@truncate(-1)); 143 | pub const TD_ERROR_ICON = MAKEINTRESOURCE(@truncate(-2)); 144 | pub const TD_INFORMATION_ICON = MAKEINTRESOURCE(@truncate(-3)); 145 | pub const TD_SHIELD_ICON = MAKEINTRESOURCE(@truncate(-4)); 146 | 147 | pub const IDC_ARROW = MAKEINTRESOURCE(32512); 148 | pub const IDC_IBEAM = MAKEINTRESOURCE(32513); 149 | pub const IDC_WAIT = MAKEINTRESOURCE(32514); 150 | pub const IDC_CROSS = MAKEINTRESOURCE(32515); 151 | pub const IDC_UPARROW = MAKEINTRESOURCE(32516); 152 | pub const IDC_SIZE = MAKEINTRESOURCE(32640); 153 | pub const IDC_ICON = MAKEINTRESOURCE(32641); 154 | pub const IDC_SIZENWSE = MAKEINTRESOURCE(32642); 155 | pub const IDC_SIZENESW = MAKEINTRESOURCE(32643); 156 | pub const IDC_SIZEWE = MAKEINTRESOURCE(32644); 157 | pub const IDC_SIZENS = MAKEINTRESOURCE(32645); 158 | pub const IDC_SIZEALL = MAKEINTRESOURCE(32646); 159 | pub const IDC_NO = MAKEINTRESOURCE(32648); 160 | pub const IDC_HAND = MAKEINTRESOURCE(32649); 161 | pub const IDC_APPSTARTING = MAKEINTRESOURCE(32650); 162 | pub const IDC_HELP = MAKEINTRESOURCE(32651); 163 | pub const IDC_PIN = MAKEINTRESOURCE(32671); 164 | pub const IDC_PERSON = MAKEINTRESOURCE(32672); 165 | 166 | pub const PM_NOREMOVE: UINT = 0x0000; 167 | pub const PM_REMOVE: UINT = 0x0001; 168 | pub const PM_NOYIELD: UINT = 0x0002; 169 | 170 | pub const WA_INACTIVE: UINT = 0; 171 | pub const WA_ACTIVE: UINT = 1; 172 | pub const WA_CLICKACTIVE: UINT = 2; 173 | 174 | //#region Window message 175 | pub const WM_NULL: UINT = 0x0000; 176 | pub const WM_CREATE: UINT = 0x0001; 177 | pub const WM_DESTROY: UINT = 0x0002; 178 | pub const WM_MOVE: UINT = 0x0003; 179 | pub const WM_SIZE: UINT = 0x0005; 180 | pub const WM_ACTIVATE: UINT = 0x0006; 181 | pub const WM_SETFOCUS: UINT = 0x0007; 182 | pub const WM_KILLFOCUS: UINT = 0x0008; 183 | pub const WM_ENABLE: UINT = 0x000A; 184 | pub const WM_SETREDRAW: UINT = 0x000B; 185 | pub const WM_SETTEXT: UINT = 0x000C; 186 | pub const WM_GETTEXT: UINT = 0x000D; 187 | pub const WM_GETTEXTLENGTH: UINT = 0x000E; 188 | pub const WM_PAINT: UINT = 0x000F; 189 | pub const WM_CLOSE: UINT = 0x0010; 190 | pub const WM_QUERYENDSESSION: UINT = 0x0011; 191 | pub const WM_QUERYOPEN: UINT = 0x0013; 192 | pub const WM_ENDSESSION: UINT = 0x0016; 193 | pub const WM_QUIT: UINT = 0x0012; 194 | pub const WM_ERASEBKGND: UINT = 0x0014; 195 | pub const WM_SYSCOLORCHANGE: UINT = 0x0015; 196 | pub const WM_SHOWWINDOW: UINT = 0x0018; 197 | pub const WM_WININICHANGE: UINT = 0x001A; 198 | pub const WM_SETTINGCHANGE: UINT = WM_WININICHANGE; 199 | pub const WM_DEVMODECHANGE: UINT = 0x001B; 200 | pub const WM_ACTIVATEAPP: UINT = 0x001C; 201 | pub const WM_FONTCHANGE: UINT = 0x001D; 202 | pub const WM_TIMECHANGE: UINT = 0x001E; 203 | pub const WM_CANCELMODE: UINT = 0x001F; 204 | pub const WM_SETCURSOR: UINT = 0x0020; 205 | pub const WM_MOUSEACTIVATE: UINT = 0x0021; 206 | pub const WM_CHILDACTIVATE: UINT = 0x0022; 207 | pub const WM_QUEUESYNC: UINT = 0x0023; 208 | pub const WM_GETMINMAXINFO: UINT = 0x0024; 209 | pub const WM_PAINTICON: UINT = 0x0026; 210 | pub const WM_ICONERASEBKGND: UINT = 0x0027; 211 | pub const WM_NEXTDLGCTL: UINT = 0x0028; 212 | pub const WM_SPOOLERSTATUS: UINT = 0x002A; 213 | pub const WM_DRAWITEM: UINT = 0x002B; 214 | pub const WM_MEASUREITEM: UINT = 0x002C; 215 | pub const WM_DELETEITEM: UINT = 0x002D; 216 | pub const WM_VKEYTOITEM: UINT = 0x002E; 217 | pub const WM_CHARTOITEM: UINT = 0x002F; 218 | pub const WM_SETFONT: UINT = 0x0030; 219 | pub const WM_GETFONT: UINT = 0x0031; 220 | pub const WM_SETHOTKEY: UINT = 0x0032; 221 | pub const WM_GETHOTKEY: UINT = 0x0033; 222 | pub const WM_QUERYDRAGICON: UINT = 0x0037; 223 | pub const WM_COMPAREITEM: UINT = 0x0039; 224 | pub const WM_GETOBJECT: UINT = 0x003D; 225 | pub const WM_COMPACTING: UINT = 0x0041; 226 | pub const WM_COMMNOTIFY: UINT = 0x0044; 227 | pub const WM_WINDOWPOSCHANGING: UINT = 0x0046; 228 | pub const WM_WINDOWPOSCHANGED: UINT = 0x0047; 229 | pub const WM_POWER: UINT = 0x0048; 230 | pub const WM_COPYDATA: UINT = 0x004A; 231 | pub const WM_CANCELJOURNAL: UINT = 0x004B; 232 | pub const WM_NOTIFY: UINT = 0x004E; 233 | pub const WM_INPUTLANGCHANGEREQUEST: UINT = 0x0050; 234 | pub const WM_INPUTLANGCHANGE: UINT = 0x0051; 235 | pub const WM_TCARD: UINT = 0x0052; 236 | pub const WM_HELP: UINT = 0x0053; 237 | pub const WM_USERCHANGED: UINT = 0x0054; 238 | pub const WM_NOTIFYFORMAT: UINT = 0x0055; 239 | pub const WM_CONTEXTMENU: UINT = 0x007B; 240 | pub const WM_STYLECHANGING: UINT = 0x007C; 241 | pub const WM_STYLECHANGED: UINT = 0x007D; 242 | pub const WM_DISPLAYCHANGE: UINT = 0x007E; 243 | pub const WM_GETICON: UINT = 0x007F; 244 | pub const WM_SETICON: UINT = 0x0080; 245 | pub const WM_NCCREATE: UINT = 0x0081; 246 | pub const WM_NCDESTROY: UINT = 0x0082; 247 | pub const WM_NCCALCSIZE: UINT = 0x0083; 248 | pub const WM_NCHITTEST: UINT = 0x0084; 249 | pub const WM_NCPAINT: UINT = 0x0085; 250 | pub const WM_NCACTIVATE: UINT = 0x0086; 251 | pub const WM_GETDLGCODE: UINT = 0x0087; 252 | pub const WM_SYNCPAINT: UINT = 0x0088; 253 | pub const WM_NCMOUSEMOVE: UINT = 0x00A0; 254 | pub const WM_NCLBUTTONDOWN: UINT = 0x00A1; 255 | pub const WM_NCLBUTTONUP: UINT = 0x00A2; 256 | pub const WM_NCLBUTTONDBLCLK: UINT = 0x00A3; 257 | pub const WM_NCRBUTTONDOWN: UINT = 0x00A4; 258 | pub const WM_NCRBUTTONUP: UINT = 0x00A5; 259 | pub const WM_NCRBUTTONDBLCLK: UINT = 0x00A6; 260 | pub const WM_NCMBUTTONDOWN: UINT = 0x00A7; 261 | pub const WM_NCMBUTTONUP: UINT = 0x00A8; 262 | pub const WM_NCMBUTTONDBLCLK: UINT = 0x00A9; 263 | pub const WM_NCXBUTTONDOWN: UINT = 0x00AB; 264 | pub const WM_NCXBUTTONUP: UINT = 0x00AC; 265 | pub const WM_NCXBUTTONDBLCLK: UINT = 0x00AD; 266 | pub const WM_INPUT_DEVICE_CHANGE: UINT = 0x00FE; 267 | pub const WM_INPUT: UINT = 0x00FF; 268 | pub const WM_KEYFIRST: UINT = 0x0100; 269 | pub const WM_KEYDOWN: UINT = 0x0100; 270 | pub const WM_KEYUP: UINT = 0x0101; 271 | pub const WM_CHAR: UINT = 0x0102; 272 | pub const WM_DEADCHAR: UINT = 0x0103; 273 | pub const WM_SYSKEYDOWN: UINT = 0x0104; 274 | pub const WM_SYSKEYUP: UINT = 0x0105; 275 | pub const WM_SYSCHAR: UINT = 0x0106; 276 | pub const WM_SYSDEADCHAR: UINT = 0x0107; 277 | pub const WM_UNICHAR: UINT = 0x0109; 278 | pub const WM_KEYLAST: UINT = 0x0109; 279 | pub const UNICODE_NOCHAR: UINT = 0xFFFF; 280 | pub const WM_IME_STARTCOMPOSITION: UINT = 0x010D; 281 | pub const WM_IME_ENDCOMPOSITION: UINT = 0x010E; 282 | pub const WM_IME_COMPOSITION: UINT = 0x010F; 283 | pub const WM_IME_KEYLAST: UINT = 0x010F; 284 | pub const WM_INITDIALOG: UINT = 0x0110; 285 | pub const WM_COMMAND: UINT = 0x0111; 286 | pub const WM_SYSCOMMAND: UINT = 0x0112; 287 | pub const WM_TIMER: UINT = 0x0113; 288 | pub const WM_HSCROLL: UINT = 0x0114; 289 | pub const WM_VSCROLL: UINT = 0x0115; 290 | pub const WM_INITMENU: UINT = 0x0116; 291 | pub const WM_INITMENUPOPUP: UINT = 0x0117; 292 | pub const WM_GESTURE: UINT = 0x0119; 293 | pub const WM_GESTURENOTIFY: UINT = 0x011A; 294 | pub const WM_MENUSELECT: UINT = 0x011F; 295 | pub const WM_MENUCHAR: UINT = 0x0120; 296 | pub const WM_ENTERIDLE: UINT = 0x0121; 297 | pub const WM_MENURBUTTONUP: UINT = 0x0122; 298 | pub const WM_MENUDRAG: UINT = 0x0123; 299 | pub const WM_MENUGETOBJECT: UINT = 0x0124; 300 | pub const WM_UNINITMENUPOPUP: UINT = 0x0125; 301 | pub const WM_MENUCOMMAND: UINT = 0x0126; 302 | pub const WM_CHANGEUISTATE: UINT = 0x0127; 303 | pub const WM_UPDATEUISTATE: UINT = 0x0128; 304 | pub const WM_QUERYUISTATE: UINT = 0x0129; 305 | pub const WM_CTLCOLORMSGBOX: UINT = 0x0132; 306 | pub const WM_CTLCOLOREDIT: UINT = 0x0133; 307 | pub const WM_CTLCOLORLISTBOX: UINT = 0x0134; 308 | pub const WM_CTLCOLORBTN: UINT = 0x0135; 309 | pub const WM_CTLCOLORDLG: UINT = 0x0136; 310 | pub const WM_CTLCOLORSCROLLBAR: UINT = 0x0137; 311 | pub const WM_CTLCOLORSTATIC: UINT = 0x0138; 312 | pub const MN_GETHMENU: UINT = 0x01E1; 313 | pub const WM_MOUSEMOVE: UINT = 0x0200; 314 | pub const WM_LBUTTONDOWN: UINT = 0x0201; 315 | pub const WM_LBUTTONUP: UINT = 0x0202; 316 | pub const WM_LBUTTONDBLCLK: UINT = 0x0203; 317 | pub const WM_RBUTTONDOWN: UINT = 0x0204; 318 | pub const WM_RBUTTONUP: UINT = 0x0205; 319 | pub const WM_RBUTTONDBLCLK: UINT = 0x0206; 320 | pub const WM_MBUTTONDOWN: UINT = 0x0207; 321 | pub const WM_MBUTTONUP: UINT = 0x0208; 322 | pub const WM_MBUTTONDBLCLK: UINT = 0x0209; 323 | pub const WM_MOUSEWHEEL: UINT = 0x020A; 324 | pub const WM_XBUTTONDOWN: UINT = 0x020B; 325 | pub const WM_XBUTTONUP: UINT = 0x020C; 326 | pub const WM_XBUTTONDBLCLK: UINT = 0x020D; 327 | pub const WM_MOUSEHWHEEL: UINT = 0x020E; 328 | pub const WM_MOUSELAST: UINT = 0x020E; 329 | pub const WM_PARENTNOTIFY: UINT = 0x0210; 330 | pub const WM_ENTERMENULOOP: UINT = 0x0211; 331 | pub const WM_EXITMENULOOP: UINT = 0x0212; 332 | pub const WM_NEXTMENU: UINT = 0x0213; 333 | pub const WM_SIZING: UINT = 0x0214; 334 | pub const WM_CAPTURECHANGED: UINT = 0x0215; 335 | pub const WM_MOVING: UINT = 0x0216; 336 | pub const WM_POWERBROADCAST: UINT = 0x0218; 337 | pub const WM_DEVICECHANGE: UINT = 0x0219; 338 | pub const WM_MDICREATE: UINT = 0x0220; 339 | pub const WM_MDIDESTROY: UINT = 0x0221; 340 | pub const WM_MDIACTIVATE: UINT = 0x0222; 341 | pub const WM_MDIRESTORE: UINT = 0x0223; 342 | pub const WM_MDINEXT: UINT = 0x0224; 343 | pub const WM_MDIMAXIMIZE: UINT = 0x0225; 344 | pub const WM_MDITILE: UINT = 0x0226; 345 | pub const WM_MDICASCADE: UINT = 0x0227; 346 | pub const WM_MDIICONARRANGE: UINT = 0x0228; 347 | pub const WM_MDIGETACTIVE: UINT = 0x0229; 348 | pub const WM_MDISETMENU: UINT = 0x0230; 349 | pub const WM_ENTERSIZEMOVE: UINT = 0x0231; 350 | pub const WM_EXITSIZEMOVE: UINT = 0x0232; 351 | pub const WM_DROPFILES: UINT = 0x0233; 352 | pub const WM_MDIREFRESHMENU: UINT = 0x0234; 353 | pub const WM_POINTERDEVICECHANGE: UINT = 0x238; 354 | pub const WM_POINTERDEVICEINRANGE: UINT = 0x239; 355 | pub const WM_POINTERDEVICEOUTOFRANGE: UINT = 0x23A; 356 | pub const WM_TOUCH: UINT = 0x0240; 357 | pub const WM_NCPOINTERUPDATE: UINT = 0x0241; 358 | pub const WM_NCPOINTERDOWN: UINT = 0x0242; 359 | pub const WM_NCPOINTERUP: UINT = 0x0243; 360 | pub const WM_POINTERUPDATE: UINT = 0x0245; 361 | pub const WM_POINTERDOWN: UINT = 0x0246; 362 | pub const WM_POINTERUP: UINT = 0x0247; 363 | pub const WM_POINTERENTER: UINT = 0x0249; 364 | pub const WM_POINTERLEAVE: UINT = 0x024A; 365 | pub const WM_POINTERACTIVATE: UINT = 0x024B; 366 | pub const WM_POINTERCAPTURECHANGED: UINT = 0x024C; 367 | pub const WM_TOUCHHITTESTING: UINT = 0x024D; 368 | pub const WM_POINTERWHEEL: UINT = 0x024E; 369 | pub const WM_POINTERHWHEEL: UINT = 0x024F; 370 | pub const WM_POINTERROUTEDTO: UINT = 0x0251; 371 | pub const WM_POINTERROUTEDAWAY: UINT = 0x0252; 372 | pub const WM_POINTERROUTEDRELEASED: UINT = 0x0253; 373 | pub const WM_IME_SETCONTEXT: UINT = 0x0281; 374 | pub const WM_IME_NOTIFY: UINT = 0x0282; 375 | pub const WM_IME_CONTROL: UINT = 0x0283; 376 | pub const WM_IME_COMPOSITIONFULL: UINT = 0x0284; 377 | pub const WM_IME_SELECT: UINT = 0x0285; 378 | pub const WM_IME_CHAR: UINT = 0x0286; 379 | pub const WM_IME_REQUEST: UINT = 0x0288; 380 | pub const WM_IME_KEYDOWN: UINT = 0x0290; 381 | pub const WM_IME_KEYUP: UINT = 0x0291; 382 | pub const WM_MOUSEHOVER: UINT = 0x02A1; 383 | pub const WM_MOUSELEAVE: UINT = 0x02A3; 384 | pub const WM_NCMOUSEHOVER: UINT = 0x02A0; 385 | pub const WM_NCMOUSELEAVE: UINT = 0x02A2; 386 | pub const WM_WTSSESSION_CHANGE: UINT = 0x02B1; 387 | pub const WM_TABLET_FIRST: UINT = 0x02c0; 388 | pub const WM_TABLET_LAST: UINT = 0x02df; 389 | pub const WM_DPICHANGED: UINT = 0x02E0; 390 | pub const WM_DPICHANGED_BEFOREPARENT: UINT = 0x02E2; 391 | pub const WM_DPICHANGED_AFTERPARENT: UINT = 0x02E3; 392 | pub const WM_GETDPISCALEDSIZE: UINT = 0x02E4; 393 | pub const WM_CUT: UINT = 0x0300; 394 | pub const WM_COPY: UINT = 0x0301; 395 | pub const WM_PASTE: UINT = 0x0302; 396 | pub const WM_CLEAR: UINT = 0x0303; 397 | pub const WM_UNDO: UINT = 0x0304; 398 | pub const WM_RENDERFORMAT: UINT = 0x0305; 399 | pub const WM_RENDERALLFORMATS: UINT = 0x0306; 400 | pub const WM_DESTROYCLIPBOARD: UINT = 0x0307; 401 | pub const WM_DRAWCLIPBOARD: UINT = 0x0308; 402 | pub const WM_PAINTCLIPBOARD: UINT = 0x0309; 403 | pub const WM_VSCROLLCLIPBOARD: UINT = 0x030A; 404 | pub const WM_SIZECLIPBOARD: UINT = 0x030B; 405 | pub const WM_ASKCBFORMATNAME: UINT = 0x030C; 406 | pub const WM_CHANGECBCHAIN: UINT = 0x030D; 407 | pub const WM_HSCROLLCLIPBOARD: UINT = 0x030E; 408 | pub const WM_QUERYNEWPALETTE: UINT = 0x030F; 409 | pub const WM_PALETTEISCHANGING: UINT = 0x0310; 410 | pub const WM_PALETTECHANGED: UINT = 0x0311; 411 | pub const WM_HOTKEY: UINT = 0x0312; 412 | pub const WM_PRINT: UINT = 0x0317; 413 | pub const WM_PRINTCLIENT: UINT = 0x0318; 414 | pub const WM_APPCOMMAND: UINT = 0x0319; 415 | pub const WM_THEMECHANGED: UINT = 0x031A; 416 | pub const WM_CLIPBOARDUPDATE: UINT = 0x031D; 417 | pub const WM_DWMCOMPOSITIONCHANGED: UINT = 0x031E; 418 | pub const WM_DWMNCRENDERINGCHANGED: UINT = 0x031F; 419 | pub const WM_DWMCOLORIZATIONCOLORCHANGED: UINT = 0x0320; 420 | pub const WM_DWMWINDOWMAXIMIZEDCHANGE: UINT = 0x0321; 421 | pub const WM_DWMSENDICONICTHUMBNAIL: UINT = 0x0323; 422 | pub const WM_DWMSENDICONICLIVEPREVIEWBITMAP: UINT = 0x0326; 423 | pub const WM_GETTITLEBARINFOEX: UINT = 0x033F; 424 | pub const WM_HANDHELDFIRST: UINT = 0x0358; 425 | pub const WM_HANDHELDLAST: UINT = 0x035F; 426 | pub const WM_AFXFIRST: UINT = 0x0360; 427 | pub const WM_AFXLAST: UINT = 0x037F; 428 | pub const WM_PENWINFIRST: UINT = 0x0380; 429 | pub const WM_PENWINLAST: UINT = 0x038F; 430 | pub const WM_APP: UINT = 0x8000; 431 | pub const WM_USER: UINT = 0x0400; 432 | //#endregion 433 | 434 | pub const TDN_CREATED: UINT = 0; 435 | pub const TDN_NAVIGATED: UINT = 1; 436 | pub const TDN_BUTTON_CLICKED: UINT = 2; 437 | pub const TDN_HYPERLINK_CLICKED: UINT = 3; 438 | pub const TDN_TIMER: UINT = 4; 439 | pub const TDN_DESTROYED: UINT = 5; 440 | pub const TDN_RADIO_BUTTON_CLICKED: UINT = 6; 441 | pub const TDN_DIALOG_CONSTRUCTED: UINT = 7; 442 | pub const TDN_VERIFICATION_CLICKED: UINT = 8; 443 | pub const TDN_HELP: UINT = 9; 444 | pub const TDN_EXPANDO_BUTTON_CLICKED: UINT = 10; 445 | 446 | pub const IDOK: u32 = 1; 447 | pub const IDCANCEL: u32 = 2; 448 | pub const IDABORT: u32 = 3; 449 | pub const IDRETRY: u32 = 4; 450 | pub const IDIGNORE: u32 = 5; 451 | pub const IDYES: u32 = 6; 452 | pub const IDNO: u32 = 7; 453 | pub const IDCLOSE: u32 = 8; 454 | pub const IDHELP: u32 = 9; 455 | pub const IDTRYAGAIN: u32 = 10; 456 | pub const IDCONTINUE: u32 = 11; 457 | pub const IDBUTTONINDEX0: u32 = 100; 458 | pub const IDTIMEOUT: u32 = 32000; 459 | 460 | pub const PFD_DRAW_TO_WINDOW: DWORD = 0x00000004; 461 | pub const PFD_DRAW_TO_BITMAP: DWORD = 0x00000008; 462 | pub const PFD_SUPPORT_GDI: DWORD = 0x00000010; 463 | pub const PFD_SUPPORT_OPENGL: DWORD = 0x00000020; 464 | pub const PFD_GENERIC_ACCELERATED: DWORD = 0x00001000; 465 | pub const PFD_GENERIC_FORMAT: DWORD = 0x00000040; 466 | pub const PFD_NEED_PALETTE: DWORD = 0x00000080; 467 | pub const PFD_NEED_SYSTEM_PALETTE: DWORD = 0x00000100; 468 | pub const PFD_DOUBLEBUFFER: DWORD = 0x00000001; 469 | pub const PFD_STEREO: DWORD = 0x00000002; 470 | pub const PFD_SWAP_LAYER_BUFFERS: DWORD = 0x00000800; 471 | pub const PFD_DEPTH_DONTCARE: DWORD = 0x20000000; 472 | pub const PFD_DOUBLEBUFFER_DONTCARE: DWORD = 0x40000000; 473 | pub const PFD_STEREO_DONTCARE: DWORD = 0x80000000; 474 | pub const PFD_SWAP_COPY: DWORD = 0x00000400; 475 | pub const PFD_SWAP_EXCHANGE: DWORD = 0x00000200; 476 | pub const PFD_TYPE_RGBA: BYTE = 0; 477 | pub const PFD_TYPE_COLORINDEX: BYTE = 1; 478 | 479 | pub const SW_HIDE: i32 = 0; 480 | pub const SW_SHOWNORMAL: i32 = 1; 481 | pub const SW_NORMAL: i32 = 1; 482 | pub const SW_SHOWMINIMIZED: i32 = 2; 483 | pub const SW_SHOWMAXIMIZED: i32 = 3; 484 | pub const SW_MAXIMIZE: i32 = 3; 485 | pub const SW_SHOWNOACTIVATE: i32 = 4; 486 | pub const SW_SHOW: i32 = 5; 487 | pub const SW_MINIMIZE: i32 = 6; 488 | pub const SW_SHOWMINNOACTIVE: i32 = 7; 489 | pub const SW_SHOWNA: i32 = 8; 490 | pub const SW_RESTORE: i32 = 9; 491 | pub const SW_SHOWDEFAULT: i32 = 0; 492 | pub const SW_FORCEMINIMIZE: i32 = 1; 493 | 494 | pub const WMSZ_BOTTOM: WPARAM = 6; 495 | pub const WMSZ_BOTTOMLEFT: WPARAM = 7; 496 | pub const WMSZ_BOTTOMRIGHT: WPARAM = 8; 497 | pub const WMSZ_LEFT: WPARAM = 1; 498 | pub const WMSZ_RIGHT: WPARAM = 2; 499 | pub const WMSZ_TOP: WPARAM = 3; 500 | pub const WMSZ_TOPLEFT: WPARAM = 4; 501 | pub const WMSZ_TOPRIGHT: WPARAM = 5; 502 | 503 | pub const HTBORDER: UINT = 18; 504 | pub const HTBOTTOM: UINT = 15; 505 | pub const HTBOTTOMLEFT: UINT = 16; 506 | pub const HTBOTTOMRIGHT: UINT = 17; 507 | pub const HTCAPTION: UINT = 2; 508 | pub const HTCLIENT: UINT = 1; 509 | pub const HTCLOSE: UINT = 20; 510 | pub const HTERROR: UINT = -2; 511 | pub const HTGROWBOX: UINT = 4; 512 | pub const HTHELP: UINT = 21; 513 | pub const HTHSCROLL: UINT = 6; 514 | pub const HTLEFT: UINT = 10; 515 | pub const HTMENU: UINT = 5; 516 | pub const HTMAXBUTTON: UINT = 9; 517 | pub const HTMINBUTTON: UINT = 8; 518 | pub const HTNOWHERE: UINT = 0; 519 | pub const HTREDUCE: UINT = 8; 520 | pub const HTRIGHT: UINT = 11; 521 | pub const HTSIZE: UINT = 4; 522 | pub const HTSYSMENU: UINT = 3; 523 | pub const HTTOP: UINT = 12; 524 | pub const HTTOPLEFT: UINT = 13; 525 | pub const HTTOPRIGHT: UINT = 14; 526 | pub const HTTRANSPARENT: UINT = 0xFFFFFFFF; 527 | pub const HTVSCROLL: UINT = 7; 528 | pub const HTZOOM: UINT = 9; 529 | 530 | pub const DBT_NO_DISK_SPACE: DWORD = 0x0047; 531 | pub const DBT_LOW_DISK_SPACE: DWORD = 0x0048; 532 | pub const DBT_CONFIGMGPRIVATE: DWORD = 0x7FFF; 533 | pub const DBT_DEVICEARRIVAL: DWORD = 0x8000; 534 | pub const DBT_DEVICEQUERYREMOVE: DWORD = 0x8001; 535 | pub const DBT_DEVICEQUERYREMOVEFAILED: DWORD = 0x8002; 536 | pub const DBT_DEVICEREMOVEPENDING: DWORD = 0x8003; 537 | pub const DBT_DEVICEREMOVECOMPLETE: DWORD = 0x8004; 538 | pub const DBT_DEVICETYPESPECIFIC: DWORD = 0x8005; 539 | pub const DBT_CUSTOMEVENT: DWORD = 0x8006; 540 | pub const DBT_DEVTYP_OEM: DWORD = 0x00000000; 541 | pub const DBT_DEVTYP_DEVNODE: DWORD = 0x00000001; 542 | pub const DBT_DEVTYP_VOLUME: DWORD = 0x00000002; 543 | pub const DBT_DEVTYP_PORT: DWORD = 0x00000003; 544 | pub const DBT_DEVTYP_NET: DWORD = 0x00000004; 545 | pub const DBT_DEVTYP_DEVICEINTERFACE: DWORD = 0x00000005; 546 | pub const DBT_DEVTYP_HANDLE: DWORD = 0x00000006; 547 | 548 | pub const DEVICE_NOTIFY_WINDOW_HANDLE: DWORD = 0x00000000; 549 | pub const DEVICE_NOTIFY_SERVICE_HANDLE: DWORD = 0x00000001; 550 | pub const DEVICE_NOTIFY_ALL_INTERFACE_CLASSES: DWORD = 0x00000004; 551 | 552 | pub const WGL_CONTEXT_MAJOR_VERSION_ARB: i32 = 0x2091; 553 | pub const WGL_CONTEXT_MINOR_VERSION_ARB: i32 = 0x2092; 554 | pub const WGL_CONTEXT_LAYER_PLANE_ARB: i32 = 0x2093; 555 | pub const WGL_CONTEXT_FLAGS_ARB: i32 = 0x2094; 556 | pub const WGL_CONTEXT_PROFILE_MASK_ARB: i32 = 0x9126; 557 | pub const WGL_CONTEXT_DEBUG_BIT_ARB: u32 = 0x0001; 558 | pub const WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB: u32 = 0x0002; 559 | pub const WGL_CONTEXT_CORE_PROFILE_BIT_ARB: u32 = 0x00000001; 560 | pub const WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB: u32 = 0x00000002; 561 | pub const ERROR_INVALID_VERSION_ARB: DWORD = 0x2095; 562 | pub const ERROR_INVALID_PROFILE_ARB: DWORD = 0x2096; 563 | pub const ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB: DWORD = 0x2054; 564 | 565 | pub const MAPVK_VK_TO_VSC: UINT = 0; 566 | pub const MAPVK_VSC_TO_VK: UINT = 1; 567 | pub const MAPVK_VK_TO_CHAR: UINT = 2; 568 | pub const MAPVK_VSC_TO_VK_EX: UINT = 3; 569 | 570 | pub const WGL_NUMBER_PIXEL_FORMATS_ARB: i32 = 0x2000; 571 | pub const WGL_DRAW_TO_WINDOW_ARB: i32 = 0x2001; 572 | pub const WGL_DRAW_TO_BITMAP_ARB: i32 = 0x2002; 573 | pub const WGL_ACCELERATION_ARB: i32 = 0x2003; 574 | pub const WGL_NEED_PALETTE_ARB: i32 = 0x2004; 575 | pub const WGL_NEED_SYSTEM_PALETTE_ARB: i32 = 0x2005; 576 | pub const WGL_SWAP_LAYER_BUFFERS_ARB: i32 = 0x2006; 577 | pub const WGL_SWAP_METHOD_ARB: i32 = 0x2007; 578 | pub const WGL_NUMBER_OVERLAYS_ARB: i32 = 0x2008; 579 | pub const WGL_NUMBER_UNDERLAYS_ARB: i32 = 0x2009; 580 | pub const WGL_TRANSPARENT_ARB: i32 = 0x200A; 581 | pub const WGL_TRANSPARENT_RED_VALUE_ARB: i32 = 0x2037; 582 | pub const WGL_TRANSPARENT_GREEN_VALUE_ARB: i32 = 0x2038; 583 | pub const WGL_TRANSPARENT_BLUE_VALUE_ARB: i32 = 0x2039; 584 | pub const WGL_TRANSPARENT_ALPHA_VALUE_ARB: i32 = 0x203A; 585 | pub const WGL_TRANSPARENT_INDEX_VALUE_ARB: i32 = 0x203B; 586 | pub const WGL_SHARE_DEPTH_ARB: i32 = 0x200C; 587 | pub const WGL_SHARE_STENCIL_ARB: i32 = 0x200D; 588 | pub const WGL_SHARE_ACCUM_ARB: i32 = 0x200E; 589 | pub const WGL_SUPPORT_GDI_ARB: i32 = 0x200F; 590 | pub const WGL_SUPPORT_OPENGL_ARB: i32 = 0x2010; 591 | pub const WGL_DOUBLE_BUFFER_ARB: i32 = 0x2011; 592 | pub const WGL_STEREO_ARB: i32 = 0x2012; 593 | pub const WGL_PIXEL_TYPE_ARB: i32 = 0x2013; 594 | pub const WGL_COLOR_BITS_ARB: i32 = 0x2014; 595 | pub const WGL_RED_BITS_ARB: i32 = 0x2015; 596 | pub const WGL_RED_SHIFT_ARB: i32 = 0x2016; 597 | pub const WGL_GREEN_BITS_ARB: i32 = 0x2017; 598 | pub const WGL_GREEN_SHIFT_ARB: i32 = 0x2018; 599 | pub const WGL_BLUE_BITS_ARB: i32 = 0x2019; 600 | pub const WGL_BLUE_SHIFT_ARB: i32 = 0x201A; 601 | pub const WGL_ALPHA_BITS_ARB: i32 = 0x201B; 602 | pub const WGL_ALPHA_SHIFT_ARB: i32 = 0x201C; 603 | pub const WGL_ACCUM_BITS_ARB: i32 = 0x201D; 604 | pub const WGL_ACCUM_RED_BITS_ARB: i32 = 0x201E; 605 | pub const WGL_ACCUM_GREEN_BITS_ARB: i32 = 0x201F; 606 | pub const WGL_ACCUM_BLUE_BITS_ARB: i32 = 0x2020; 607 | pub const WGL_ACCUM_ALPHA_BITS_ARB: i32 = 0x2021; 608 | pub const WGL_DEPTH_BITS_ARB: i32 = 0x2022; 609 | pub const WGL_STENCIL_BITS_ARB: i32 = 0x2023; 610 | pub const WGL_AUX_BUFFERS_ARB: i32 = 0x2024; 611 | pub const WGL_NO_ACCELERATION_ARB: i32 = 0x2025; 612 | pub const WGL_GENERIC_ACCELERATION_ARB: i32 = 0x2026; 613 | pub const WGL_FULL_ACCELERATION_ARB: i32 = 0x2027; 614 | pub const WGL_SWAP_EXCHANGE_ARB: i32 = 0x2028; 615 | pub const WGL_SWAP_COPY_ARB: i32 = 0x2029; 616 | pub const WGL_SWAP_UNDEFINED_ARB: i32 = 0x202A; 617 | pub const WGL_TYPE_RGBA_ARB: i32 = 0x202B; 618 | pub const WGL_TYPE_COLORINDEX_ARB: i32 = 0x202C; 619 | pub const WGL_SAMPLE_BUFFERS_ARB: i32 = 0x2041; 620 | pub const WGL_SAMPLES_ARB: i32 = 0x2042; 621 | 622 | pub const CP_USASCII: UINT = 1252; 623 | pub const CP_UNICODE: UINT = 1200; 624 | pub const CP_JAUTODETECT: UINT = 50932; 625 | pub const CP_KAUTODETECT: UINT = 50949; 626 | pub const CP_ISO2022JPESC: UINT = 50221; 627 | pub const CP_ISO2022JPSIO: UINT = 50222; 628 | pub const CP_UTF8: UINT = 65001; 629 | 630 | //#region Virtual Keys 631 | pub const VK_LBUTTON: UINT = 0x01; 632 | pub const VK_RBUTTON: UINT = 0x02; 633 | pub const VK_CANCEL: UINT = 0x03; 634 | pub const VK_MBUTTON: UINT = 0x04; 635 | pub const VK_XBUTTON1: UINT = 0x05; 636 | pub const VK_XBUTTON2: UINT = 0x06; 637 | pub const VK_BACK: UINT = 0x08; 638 | pub const VK_TAB: UINT = 0x09; 639 | pub const VK_CLEAR: UINT = 0x0C; 640 | pub const VK_RETURN: UINT = 0x0D; 641 | pub const VK_SHIFT: UINT = 0x10; 642 | pub const VK_CONTROL: UINT = 0x11; 643 | pub const VK_MENU: UINT = 0x12; 644 | pub const VK_PAUSE: UINT = 0x13; 645 | pub const VK_CAPITAL: UINT = 0x14; 646 | pub const VK_KANA: UINT = 0x15; 647 | pub const VK_HANGEUL: UINT = 0x15; 648 | pub const VK_HANGUL: UINT = 0x15; 649 | pub const VK_IME_ON: UINT = 0x16; 650 | pub const VK_JUNJA: UINT = 0x17; 651 | pub const VK_FINAL: UINT = 0x18; 652 | pub const VK_HANJA: UINT = 0x19; 653 | pub const VK_KANJI: UINT = 0x19; 654 | pub const VK_IME_OFF: UINT = 0x1A; 655 | pub const VK_ESCAPE: UINT = 0x1B; 656 | pub const VK_CONVERT: UINT = 0x1C; 657 | pub const VK_NONCONVERT: UINT = 0x1D; 658 | pub const VK_ACCEPT: UINT = 0x1E; 659 | pub const VK_MODECHANGE: UINT = 0x1F; 660 | pub const VK_SPACE: UINT = 0x20; 661 | pub const VK_PRIOR: UINT = 0x21; 662 | pub const VK_NEXT: UINT = 0x22; 663 | pub const VK_END: UINT = 0x23; 664 | pub const VK_HOME: UINT = 0x24; 665 | pub const VK_LEFT: UINT = 0x25; 666 | pub const VK_UP: UINT = 0x26; 667 | pub const VK_RIGHT: UINT = 0x27; 668 | pub const VK_DOWN: UINT = 0x28; 669 | pub const VK_SELECT: UINT = 0x29; 670 | pub const VK_PRINT: UINT = 0x2A; 671 | pub const VK_EXECUTE: UINT = 0x2B; 672 | pub const VK_SNAPSHOT: UINT = 0x2C; 673 | pub const VK_INSERT: UINT = 0x2D; 674 | pub const VK_DELETE: UINT = 0x2E; 675 | pub const VK_HELP: UINT = 0x2F; 676 | 677 | pub const VK_LWIN: UINT = 0x5B; 678 | pub const VK_RWIN: UINT = 0x5C; 679 | pub const VK_APPS: UINT = 0x5D; 680 | pub const VK_SLEEP: UINT = 0x5F; 681 | pub const VK_NUMPAD0: UINT = 0x60; 682 | pub const VK_NUMPAD1: UINT = 0x61; 683 | pub const VK_NUMPAD2: UINT = 0x62; 684 | pub const VK_NUMPAD3: UINT = 0x63; 685 | pub const VK_NUMPAD4: UINT = 0x64; 686 | pub const VK_NUMPAD5: UINT = 0x65; 687 | pub const VK_NUMPAD6: UINT = 0x66; 688 | pub const VK_NUMPAD7: UINT = 0x67; 689 | pub const VK_NUMPAD8: UINT = 0x68; 690 | pub const VK_NUMPAD9: UINT = 0x69; 691 | pub const VK_MULTIPLY: UINT = 0x6A; 692 | pub const VK_ADD: UINT = 0x6B; 693 | pub const VK_SEPARATOR: UINT = 0x6C; 694 | pub const VK_SUBTRACT: UINT = 0x6D; 695 | pub const VK_DECIMAL: UINT = 0x6E; 696 | pub const VK_DIVIDE: UINT = 0x6F; 697 | pub const VK_F1: UINT = 0x70; 698 | pub const VK_F2: UINT = 0x71; 699 | pub const VK_F3: UINT = 0x72; 700 | pub const VK_F4: UINT = 0x73; 701 | pub const VK_F5: UINT = 0x74; 702 | pub const VK_F6: UINT = 0x75; 703 | pub const VK_F7: UINT = 0x76; 704 | pub const VK_F8: UINT = 0x77; 705 | pub const VK_F9: UINT = 0x78; 706 | pub const VK_F10: UINT = 0x79; 707 | pub const VK_F11: UINT = 0x7A; 708 | pub const VK_F12: UINT = 0x7B; 709 | pub const VK_F13: UINT = 0x7C; 710 | pub const VK_F14: UINT = 0x7D; 711 | pub const VK_F15: UINT = 0x7E; 712 | pub const VK_F16: UINT = 0x7F; 713 | pub const VK_F17: UINT = 0x80; 714 | pub const VK_F18: UINT = 0x81; 715 | pub const VK_F19: UINT = 0x82; 716 | pub const VK_F20: UINT = 0x83; 717 | pub const VK_F21: UINT = 0x84; 718 | pub const VK_F22: UINT = 0x85; 719 | pub const VK_F23: UINT = 0x86; 720 | pub const VK_F24: UINT = 0x87; 721 | pub const VK_NUMLOCK: UINT = 0x90; 722 | pub const VK_SCROLL: UINT = 0x91; 723 | pub const VK_OEM_NEC_EQUAL: UINT = 0x92; 724 | pub const VK_OEM_FJ_JISHO: UINT = 0x92; 725 | pub const VK_OEM_FJ_MASSHOU: UINT = 0x93; 726 | pub const VK_OEM_FJ_TOUROKU: UINT = 0x94; 727 | pub const VK_OEM_FJ_LOYA: UINT = 0x95; 728 | pub const VK_OEM_FJ_ROYA: UINT = 0x96; 729 | pub const VK_LSHIFT: UINT = 0xA0; 730 | pub const VK_RSHIFT: UINT = 0xA1; 731 | pub const VK_LCONTROL: UINT = 0xA2; 732 | pub const VK_RCONTROL: UINT = 0xA3; 733 | pub const VK_LMENU: UINT = 0xA4; 734 | pub const VK_RMENU: UINT = 0xA5; 735 | pub const VK_BROWSER_BACK: UINT = 0xA6; 736 | pub const VK_BROWSER_FORWARD: UINT = 0xA7; 737 | pub const VK_BROWSER_REFRESH: UINT = 0xA8; 738 | pub const VK_BROWSER_STOP: UINT = 0xA9; 739 | pub const VK_BROWSER_SEARCH: UINT = 0xAA; 740 | pub const VK_BROWSER_FAVORITES: UINT = 0xAB; 741 | pub const VK_BROWSER_HOME: UINT = 0xAC; 742 | pub const VK_VOLUME_MUTE: UINT = 0xAD; 743 | pub const VK_VOLUME_DOWN: UINT = 0xAE; 744 | pub const VK_VOLUME_UP: UINT = 0xAF; 745 | pub const VK_MEDIA_NEXT_TRACK: UINT = 0xB0; 746 | pub const VK_MEDIA_PREV_TRACK: UINT = 0xB1; 747 | pub const VK_MEDIA_STOP: UINT = 0xB2; 748 | pub const VK_MEDIA_PLAY_PAUSE: UINT = 0xB3; 749 | pub const VK_LAUNCH_MAIL: UINT = 0xB4; 750 | pub const VK_LAUNCH_MEDIA_SELECT: UINT = 0xB5; 751 | pub const VK_LAUNCH_APP1: UINT = 0xB6; 752 | pub const VK_LAUNCH_APP2: UINT = 0xB7; 753 | pub const VK_OEM_1: UINT = 0xBA; 754 | pub const VK_OEM_PLUS: UINT = 0xBB; 755 | pub const VK_OEM_COMMA: UINT = 0xBC; 756 | pub const VK_OEM_MINUS: UINT = 0xBD; 757 | pub const VK_OEM_PERIOD: UINT = 0xBE; 758 | pub const VK_OEM_2: UINT = 0xBF; 759 | pub const VK_OEM_3: UINT = 0xC0; 760 | pub const VK_OEM_4: UINT = 0xDB; 761 | pub const VK_OEM_5: UINT = 0xDC; 762 | pub const VK_OEM_6: UINT = 0xDD; 763 | pub const VK_OEM_7: UINT = 0xDE; 764 | pub const VK_OEM_8: UINT = 0xDF; 765 | pub const VK_OEM_AX: UINT = 0xE1; 766 | pub const VK_OEM_102: UINT = 0xE2; 767 | pub const VK_ICO_HELP: UINT = 0xE3; 768 | pub const VK_ICO_00: UINT = 0xE4; 769 | pub const VK_PROCESSKEY: UINT = 0xE5; 770 | pub const VK_ICO_CLEAR: UINT = 0xE6; 771 | pub const VK_PACKET: UINT = 0xE7; 772 | pub const VK_OEM_RESET: UINT = 0xE9; 773 | pub const VK_OEM_JUMP: UINT = 0xEA; 774 | pub const VK_OEM_PA1: UINT = 0xEB; 775 | pub const VK_OEM_PA2: UINT = 0xEC; 776 | pub const VK_OEM_PA3: UINT = 0xED; 777 | pub const VK_OEM_WSCTRL: UINT = 0xEE; 778 | pub const VK_OEM_CUSEL: UINT = 0xEF; 779 | pub const VK_OEM_ATTN: UINT = 0xF0; 780 | pub const VK_OEM_FINISH: UINT = 0xF1; 781 | pub const VK_OEM_COPY: UINT = 0xF2; 782 | pub const VK_OEM_AUTO: UINT = 0xF3; 783 | pub const VK_OEM_ENLW: UINT = 0xF4; 784 | pub const VK_OEM_BACKTAB: UINT = 0xF5; 785 | pub const VK_ATTN: UINT = 0xF6; 786 | pub const VK_CRSEL: UINT = 0xF7; 787 | pub const VK_EXSEL: UINT = 0xF8; 788 | pub const VK_EREOF: UINT = 0xF9; 789 | pub const VK_PLAY: UINT = 0xFA; 790 | pub const VK_ZOOM: UINT = 0xFB; 791 | pub const VK_NONAME: UINT = 0xFC; 792 | pub const VK_PA1: UINT = 0xFD; 793 | pub const VK_OEM_CLEAR: UINT = 0xFE; 794 | //#endregion 795 | 796 | //#region System metrics 797 | pub const SM_ARRANGE: i32 = 56; 798 | pub const SM_CLEANBOOT: i32 = 67; 799 | pub const SM_CMONITORS: i32 = 80; 800 | pub const SM_CMOUSEBUTTONS: i32 = 43; 801 | pub const SM_CONVERTIBLESLATEMODE: i32 = 0x2003; 802 | pub const SM_CXBORDER: i32 = 5; 803 | pub const SM_CXCURSOR: i32 = 13; 804 | pub const SM_CXDLGFRAME: i32 = 7; 805 | pub const SM_CXDOUBLECLK: i32 = 36; 806 | pub const SM_CXDRAG: i32 = 68; 807 | pub const SM_CXEDGE: i32 = 45; 808 | pub const SM_CXFIXEDFRAME: i32 = 7; 809 | pub const SM_CXFOCUSBORDER: i32 = 83; 810 | pub const SM_CXFRAME: i32 = 32; 811 | pub const SM_CXFULLSCREEN: i32 = 16; 812 | pub const SM_CXHSCROLL: i32 = 21; 813 | pub const SM_CXHTHUMB: i32 = 10; 814 | pub const SM_CXICON: i32 = 11; 815 | pub const SM_CXICONSPACING: i32 = 38; 816 | pub const SM_CXMAXIMIZED: i32 = 61; 817 | pub const SM_CXMAXTRACK: i32 = 59; 818 | pub const SM_CXMENUCHECK: i32 = 71; 819 | pub const SM_CXMENUSIZE: i32 = 54; 820 | pub const SM_CXMIN: i32 = 28; 821 | pub const SM_CXMINIMIZED: i32 = 57; 822 | pub const SM_CXMINSPACING: i32 = 47; 823 | pub const SM_CXMINTRACK: i32 = 34; 824 | pub const SM_CXPADDEDBORDER: i32 = 92; 825 | pub const SM_CXSCREEN: i32 = 0; 826 | pub const SM_CXSIZE: i32 = 30; 827 | pub const SM_CXSIZEFRAME: i32 = 32; 828 | pub const SM_CXSMICON: i32 = 49; 829 | pub const SM_CXSMSIZE: i32 = 52; 830 | pub const SM_CXVIRTUALSCREEN: i32 = 78; 831 | pub const SM_CXVSCROLL: i32 = 2; 832 | pub const SM_CYBORDER: i32 = 6; 833 | pub const SM_CYCAPTION: i32 = 4; 834 | pub const SM_CYCURSOR: i32 = 14; 835 | pub const SM_CYDLGFRAME: i32 = 8; 836 | pub const SM_CYDOUBLECLK: i32 = 37; 837 | pub const SM_CYDRAG: i32 = 69; 838 | pub const SM_CYEDGE: i32 = 46; 839 | pub const SM_CYFIXEDFRAME: i32 = 8; 840 | pub const SM_CYFOCUSBORDER: i32 = 84; 841 | pub const SM_CYFRAME: i32 = 33; 842 | pub const SM_CYFULLSCREEN: i32 = 17; 843 | pub const SM_CYHSCROLL: i32 = 3; 844 | pub const SM_CYICON: i32 = 12; 845 | pub const SM_CYICONSPACING: i32 = 39; 846 | pub const SM_CYKANJIWINDOW: i32 = 18; 847 | pub const SM_CYMAXIMIZED: i32 = 62; 848 | pub const SM_CYMAXTRACK: i32 = 60; 849 | pub const SM_CYMENU: i32 = 15; 850 | pub const SM_CYMENUCHECK: i32 = 72; 851 | pub const SM_CYMENUSIZE: i32 = 55; 852 | pub const SM_CYMIN: i32 = 29; 853 | pub const SM_CYMINIMIZED: i32 = 58; 854 | pub const SM_CYMINSPACING: i32 = 48; 855 | pub const SM_CYMINTRACK: i32 = 35; 856 | pub const SM_CYSCREEN: i32 = 1; 857 | pub const SM_CYSIZE: i32 = 31; 858 | pub const SM_CYSIZEFRAME: i32 = 33; 859 | pub const SM_CYSMCAPTION: i32 = 51; 860 | pub const SM_CYSMICON: i32 = 50; 861 | pub const SM_CYSMSIZE: i32 = 53; 862 | pub const SM_CYVIRTUALSCREEN: i32 = 79; 863 | pub const SM_CYVSCROLL: i32 = 20; 864 | pub const SM_CYVTHUMB: i32 = 9; 865 | pub const SM_DBCSENABLED: i32 = 42; 866 | pub const SM_DEBUG: i32 = 22; 867 | pub const SM_DIGITIZER: i32 = 94; 868 | pub const SM_IMMENABLED: i32 = 82; 869 | pub const SM_MAXIMUMTOUCHES: i32 = 95; 870 | pub const SM_MEDIACENTER: i32 = 87; 871 | pub const SM_MENUDROPALIGNMENT: i32 = 40; 872 | pub const SM_MIDEASTENABLED: i32 = 74; 873 | pub const SM_MOUSEPRESENT: i32 = 19; 874 | pub const SM_MOUSEHORIZONTALWHEELPRESENT: i32 = 91; 875 | pub const SM_MOUSEWHEELPRESENT: i32 = 75; 876 | pub const SM_NETWORK: i32 = 63; 877 | pub const SM_PENWINDOWS: i32 = 41; 878 | pub const SM_REMOTECONTROL: i32 = 0x2001; 879 | pub const SM_REMOTESESSION: i32 = 0x1000; 880 | pub const SM_SAMEDISPLAYFORMAT: i32 = 81; 881 | pub const SM_SECURE: i32 = 44; 882 | pub const SM_SERVERR2: i32 = 89; 883 | pub const SM_SHOWSOUNDS: i32 = 70; 884 | pub const SM_SHUTTINGDOWN: i32 = 0x2000; 885 | pub const SM_SLOWMACHINE: i32 = 73; 886 | pub const SM_STARTER: i32 = 88; 887 | pub const SM_SWAPBUTTON: i32 = 23; 888 | pub const SM_SYSTEMDOCKED: i32 = 0x2004; 889 | pub const SM_TABLETPC: i32 = 86; 890 | pub const SM_XVIRTUALSCREEN: i32 = 76; 891 | pub const SM_YVIRTUALSCREEN: i32 = 77; 892 | //#endregion 893 | 894 | pub const WNDCLASSEXW = extern struct { 895 | cbSize: UINT = @sizeOf(WNDCLASSEXW), 896 | style: UINT, 897 | lpfnWndProc: WNDPROC, 898 | cbClsExtra: i32 = 0, 899 | cbWndExtra: i32 = 0, 900 | hInstance: ?HINSTANCE = null, 901 | hIcon: ?HICON = null, 902 | hCursor: ?HCURSOR = null, 903 | hbrBackground: ?HBRUSH = null, 904 | lpszMenuName: ?LPCWSTR = null, 905 | lpszClassName: LPCWSTR, 906 | hIconSm: ?HICON = null, 907 | }; 908 | pub const POINT = extern struct { 909 | x: LONG = 0, 910 | y: LONG = 0, 911 | }; 912 | pub const RECT = extern struct { 913 | left: LONG = 0, 914 | top: LONG = 0, 915 | right: LONG = 0, 916 | bottom: LONG = 0, 917 | }; 918 | pub const MSG = extern struct { 919 | hwnd: ?HWND, 920 | message: UINT, 921 | wParam: WPARAM, 922 | lParam: LPARAM, 923 | time: DWORD, 924 | pt: POINT, 925 | }; 926 | pub const TASKDIALOGCONFIG = extern struct { 927 | cbSize: UINT = @sizeOf(TASKDIALOGCONFIG), 928 | hwndParent: ?HWND, 929 | hInstance: ?HINSTANCE, 930 | dwFlags: TASKDIALOG_FLAGS = .{}, 931 | dwCommonButtons: TASKDIALOG_COMMON_BUTTON_FLAGS = .{}, 932 | pszWindowTitle: LPCWSTR, 933 | DUMMYUNIONNAME: extern union { 934 | hMainIcon: ?HICON, 935 | pszMainIcon: ?LPCWSTR, 936 | } = .{ .hMainIcon = null }, 937 | pszMainInstruction: ?LPCWSTR = null, 938 | pszContent: LPCWSTR, 939 | cButtons: UINT, 940 | pButtons: [*]const TASKDIALOG_BUTTON, 941 | nDefaultButton: u32 = 0, 942 | cRadioButtons: UINT = 0, 943 | pRadioButtons: ?[*]const TASKDIALOG_BUTTON = null, 944 | nDefaultRadioButton: u32 = 0, 945 | pszVerificationText: ?LPCWSTR = null, 946 | pszExpandedInformation: ?LPCWSTR = null, 947 | pszExpandedControlText: ?LPCWSTR = null, 948 | pszCollapsedControlText: ?LPCWSTR = null, 949 | DUMMYUNIONNAME2: extern union { 950 | hFooterIcon: ?HICON, 951 | pszFooterIcon: ?LPCWSTR, 952 | } = .{ .hFooterIcon = null }, 953 | pszFooter: ?LPCWSTR = null, 954 | pfCallback: ?PFTASKDIALOGCALLBACK = null, 955 | lpCallbackData: LONG_PTR = 0, 956 | cxWidth: UINT = 0, 957 | }; 958 | pub const TASKDIALOG_FLAGS = packed struct { 959 | ENABLE_HYPERLINKS: bool = false, 960 | USE_HICON_MAIN: bool = false, 961 | USE_HICON_FOOTER: bool = false, 962 | ALLOW_DIALOG_CANCELLATION: bool = false, 963 | USE_COMMAND_LINKS: bool = false, 964 | USE_COMMAND_LINKS_NO_ICON: bool = false, 965 | EXPAND_FOOTER_AREA: bool = false, 966 | EXPANDED_BY_DEFAULT: bool = false, 967 | VERIFICATION_FLAG_CHECKED: bool = false, 968 | SHOW_PROGRESS_BAR: bool = false, 969 | SHOW_MARQUEE_PROGRESS_BAR: bool = false, 970 | CALLBACK_TIMER: bool = false, 971 | POSITION_RELATIVE_TO_WINDOW: bool = false, 972 | RTL_LAYOUT: bool = false, 973 | NO_DEFAULT_RADIO_BUTTON: bool = false, 974 | CAN_BE_MINIMIZED: bool = false, 975 | NO_SET_FOREGROUND: bool = false, 976 | SIZE_TO_CONTENT: bool = false, 977 | _padding: u14 = 0, 978 | }; 979 | pub const TASKDIALOG_COMMON_BUTTON_FLAGS = packed struct { 980 | OK_BUTTON: bool = false, 981 | YES_BUTTON: bool = false, 982 | NO_BUTTON: bool = false, 983 | CANCEL_BUTTON: bool = false, 984 | RETRY_BUTTON: bool = false, 985 | CLOSE_BUTTON: bool = false, 986 | _padding: u26 = 0, 987 | }; 988 | pub const TASKDIALOG_BUTTON = extern struct { 989 | nButtonID: u32, 990 | pszButtonText: LPCWSTR, 991 | }; 992 | pub const PIXELFORMATDESCRIPTOR = extern struct { 993 | nSize: WORD = @sizeOf(PIXELFORMATDESCRIPTOR), 994 | nVersion: WORD = 0, 995 | dwFlags: DWORD = 0, 996 | iPixelType: BYTE = 0, 997 | cColorBits: BYTE = 0, 998 | cRedBits: BYTE = 0, 999 | cRedShift: BYTE = 0, 1000 | cGreenBits: BYTE = 0, 1001 | cGreenShift: BYTE = 0, 1002 | cBlueBits: BYTE = 0, 1003 | cBlueShift: BYTE = 0, 1004 | cAlphaBits: BYTE = 0, 1005 | cAlphaShift: BYTE = 0, 1006 | cAccumBits: BYTE = 0, 1007 | cAccumRedBits: BYTE = 0, 1008 | cAccumGreenBits: BYTE = 0, 1009 | cAccumBlueBits: BYTE = 0, 1010 | cAccumAlphaBits: BYTE = 0, 1011 | cDepthBits: BYTE = 0, 1012 | cStencilBits: BYTE = 0, 1013 | cAuxBuffers: BYTE = 0, 1014 | iLayerType: BYTE = 0, 1015 | bReserved: BYTE = 0, 1016 | dwLayerMask: DWORD = 0, 1017 | dwVisibleMask: DWORD = 0, 1018 | dwDamageMask: DWORD = 0, 1019 | }; 1020 | pub const MINMAXINFO = extern struct { 1021 | ptReserved: POINT, 1022 | ptMaxSize: POINT, 1023 | ptMaxPosition: POINT, 1024 | ptMinTrackSize: POINT, 1025 | ptMaxTrackSize: POINT, 1026 | }; 1027 | pub const DEV_BROADCAST_DEVICEINTERFACE_W = extern struct { 1028 | dbcc_size: DWORD, 1029 | dbcc_devicetype: DWORD, 1030 | dbcc_reserved: DWORD, 1031 | dbcc_classguid: GUID, 1032 | dbcc_name: [1]u16, 1033 | }; 1034 | pub const GUID = extern struct { 1035 | Data1: u32, 1036 | Data2: u16, 1037 | Data3: u16, 1038 | Data4: [8]u8, 1039 | }; 1040 | 1041 | pub const HRESULT = i32; 1042 | pub inline fn SUCCEEDED(hr: HRESULT) bool { 1043 | return hr >= 0; 1044 | } 1045 | pub inline fn FAILED(hr: HRESULT) bool { 1046 | return hr < 0; 1047 | } 1048 | 1049 | //#region Kernel32 1050 | pub extern "Kernel32" fn GetModuleHandleW(lpModuleName: ?LPCWSTR) callconv(WINAPI) HMODULE; 1051 | pub extern "Kernel32" fn GetLastError() callconv(WINAPI) DWORD; 1052 | pub extern "Kernel32" fn SetConsoleOutputCP(wCodePageID: UINT) callconv(WINAPI) BOOL; 1053 | //#endregion 1054 | 1055 | //#region User32 1056 | pub extern "User32" fn GetSystemMetrics(nIndex: i32) callconv(WINAPI) i32; 1057 | pub extern "User32" fn CreateWindowExW(dwExtStyle: DWORD, lpClassName: ?LPCWSTR, lpWindowName: ?LPCWSTR, dwStyle: DWORD, x: i32, y: i32, nWidth: i32, nHeight: i32, hWndParent: ?HWND, hWndMenu: ?HWND, hInstance: ?HINSTANCE, lpParam: ?LPVOID) callconv(WINAPI) ?HWND; 1058 | pub extern "User32" fn DestroyWindow(hWnd: HWND) callconv(WINAPI) BOOL; 1059 | pub extern "User32" fn DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(WINAPI) LRESULT; 1060 | pub extern "User32" fn RegisterClassExW(class: *const WNDCLASSEXW) callconv(WINAPI) ATOM; 1061 | pub extern "User32" fn UnregisterClassW(lpClassName: LPCWSTR, hInstance: ?HINSTANCE) callconv(WINAPI) BOOL; 1062 | pub extern "User32" fn LoadCursorW(hInstance: ?HINSTANCE, lpCursorName: LPCWSTR) callconv(WINAPI) ?HCURSOR; 1063 | pub extern "User32" fn GetPropW(hWnd: HWND, lpString: LPCWSTR) callconv(WINAPI) ?HANDLE; 1064 | pub extern "User32" fn SetPropW(hWnd: HWND, lpString: LPCWSTR, hData: HANDLE) callconv(WINAPI) BOOL; 1065 | pub extern "User32" fn GetActiveWindow() callconv(WINAPI) ?HWND; 1066 | pub extern "User32" fn SetActiveWindow(hWnd: HWND) callconv(WINAPI) ?HWND; 1067 | pub extern "User32" fn SetFocus(hWnd: ?HWND) callconv(WINAPI) ?HWND; 1068 | pub extern "User32" fn PeekMessageW(lpMsg: *MSG, hWnd: ?HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) callconv(WINAPI) BOOL; 1069 | pub extern "User32" fn TranslateMessage(lpMsg: *const MSG) callconv(WINAPI) BOOL; 1070 | pub extern "User32" fn DispatchMessageW(lpMsg: *const MSG) callconv(WINAPI) LRESULT; 1071 | pub extern "User32" fn ClientToScreen(hWnd: HWND, lpPoint: *POINT) callconv(WINAPI) BOOL; 1072 | pub extern "User32" fn AdjustWindowRectEx(lpRect: *RECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD) BOOL; 1073 | pub extern "User32" fn GetClientRect(hWnd: HWND, lprect: *RECT) callconv(WINAPI) BOOL; 1074 | pub extern "User32" fn SetWindowPos(hWnd: HWND, hWndInsertAfter: ?HWND, X: i32, Y: i32, cx: i32, cy: i32, uFlags: UINT) callconv(WINAPI) BOOL; 1075 | pub extern "User32" fn GetDC(hWnd: HWND) callconv(WINAPI) ?HDC; 1076 | pub extern "User32" fn ReleaseDC(hWnd: HWND, dc: HDC) callconv(WINAPI) BOOL; 1077 | pub extern "User32" fn ShowWindow(hWnd: HWND, nCmdShow: i32) callconv(WINAPI) BOOL; 1078 | pub extern "User32" fn SetWindowTextW(hWnd: HWND, lpString: ?LPCWSTR) callconv(WINAPI) BOOL; 1079 | pub extern "User32" fn GetWindowTextLengthW(hWnd: HWND) callconv(WINAPI) i32; 1080 | pub extern "User32" fn GetWindowTextW(hWnd: HWND, lpString: LPWSTR, nMaxCount: i32) callconv(WINAPI) i32; 1081 | pub extern "User32" fn GetWindowRect(hWnd: HWND, lpRect: *RECT) callconv(WINAPI) BOOL; 1082 | pub extern "User32" fn MoveWindow(hWnd: HWND, x: i32, y: i32, nWidth: i32, nHeight: i32, bRepaint: BOOL) callconv(WINAPI) BOOL; 1083 | pub extern "User32" fn GetCursorPos(lpPoint: *POINT) callconv(WINAPI) BOOL; 1084 | pub extern "User32" fn SetCursorPos(x: i32, y: i32) callconv(WINAPI) BOOL; 1085 | pub extern "User32" fn ScreenToClient(hWnd: HWND, lpPoint: *POINT) callconv(WINAPI) BOOL; 1086 | pub extern "User32" fn SetCursor(hCurser: ?HCURSOR) callconv(WINAPI) HCURSOR; 1087 | pub extern "User32" fn ClipCursor(lpRect: ?*const RECT) callconv(WINAPI) BOOL; 1088 | pub extern "User32" fn WindowFromPoint(Point: POINT) callconv(WINAPI) ?HWND; 1089 | pub extern "User32" fn PtInRect(lprc: *const RECT, Point: POINT) callconv(WINAPI) BOOL; 1090 | pub extern "User32" fn ShowCursor(bShow: BOOL) callconv(WINAPI) i32; 1091 | pub extern "User32" fn GetKeyState(nVirtKey: i32) callconv(WINAPI) SHORT; 1092 | pub extern "User32" fn MapVirtualKeyW(uCode: UINT, uMapType: UINT) callconv(WINAPI) UINT; 1093 | pub extern "User32" fn GetMessageTime() callconv(WINAPI) LONG; 1094 | pub extern "User32" fn MessageBoxW(hWnd: ?HWND, lpText: ?LPCWSTR, lpCaption: ?LPCWSTR, uType: UINT) callconv(WINAPI) i32; 1095 | pub extern "User32" fn ToUnicode(wVirtKey: UINT, wScanCode: UINT, lpKeyState: ?*const [256]BYTE, pwszBuff: LPWSTR, cchBuff: i32, wFlags: UINT) callconv(WINAPI) i32; 1096 | pub extern "User32" fn SendMessage(hWnd: HWND, msg: UINT, wParam: WPARAM, lParam: LPARAM) callconv(WINAPI) LRESULT; 1097 | //#endregion 1098 | 1099 | //#region Comctl32 1100 | pub extern "Comctl32" fn TaskDialogIndirect(pTaskConfig: *const TASKDIALOGCONFIG, pnButton: ?*i32, pnRadioButton: ?*i32, pfVerificationFlagChecked: ?*BOOL) callconv(WINAPI) HRESULT; 1101 | //#endregion 1102 | 1103 | //#region Opengl32 1104 | pub extern "Opengl32" fn wglCreateContext(hdc: HDC) callconv(WINAPI) ?HGLRC; 1105 | pub extern "Opengl32" fn wglDeleteContext(hglrc: HGLRC) callconv(WINAPI) BOOL; 1106 | pub extern "Opengl32" fn wglMakeCurrent(hdc: HDC, hglrc: ?HGLRC) callconv(WINAPI) BOOL; 1107 | pub extern "Opengl32" fn wglGetProcAddress(name: [*:0]const u8) callconv(WINAPI) ?*const anyopaque; 1108 | pub extern "Opengl32" fn wglShareLists(hglrc1: HGLRC, hglrc2: HGLRC) callconv(WINAPI) BOOL; 1109 | //#endregion 1110 | 1111 | //#region Gdi32 1112 | pub extern "Gdi32" fn SetPixelFormat(hdc: HDC, format: i32, ppfd: *const PIXELFORMATDESCRIPTOR) callconv(WINAPI) BOOL; 1113 | pub extern "Gdi32" fn ChoosePixelFormat(hdc: HDC, ppfd: *const PIXELFORMATDESCRIPTOR) callconv(WINAPI) i32; 1114 | pub extern "Gdi32" fn SwapBuffers(hdc: HDC) callconv(WINAPI) BOOL; 1115 | //#endregion 1116 | --------------------------------------------------------------------------------