summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2026-04-13 16:24:21 -0400
committerAndrew Opalach <andrew@akon.city> 2026-04-13 16:39:12 -0400
commit0d027c466c199f9857b0872ed76ebab2ed501e43 (patch)
tree17a88480e7dac721902d21611e2d2834f2344c27
parentcbad92b78cb9901314dd3304d61bcee3b56312eb (diff)
downloadstela-0d027c466c199f9857b0872ed76ebab2ed501e43.tar.gz
stela-0d027c466c199f9857b0872ed76ebab2ed501e43.tar.bz2
stela-0d027c466c199f9857b0872ed76ebab2ed501e43.zip
Lots of win32 window tweaks, partially unfinished
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--src/window_win32.c226
-rw-r--r--src/window_win32.h6
2 files changed, 160 insertions, 72 deletions
diff --git a/src/window_win32.c b/src/window_win32.c
index 46835e2..d97f51b 100644
--- a/src/window_win32.c
+++ b/src/window_win32.c
@@ -5,6 +5,12 @@
#include "common.h"
#include "keys.h"
+// All extra Windows headers come after <nnwt/windows.h>.
+#include <windowsx.h>
+#ifndef NAUNET_WIN32_COMPAT_MODE
+#include <dwmapi.h>
+#endif
+
#if defined STELA_API_VULKAN
#include "vk_common.h"
#elif defined STELA_API_OPENGL
@@ -100,12 +106,14 @@ static LRESULT CALLBACK ServiceWndProc(HWND Window, UINT Message, WPARAM WParam,
Baby->lpParam);
break;
}
- case DESTROY_DANGEROUS_WINDOW:
- if (!DestroyWindow((HWND)WParam)) {
+ case DESTROY_DANGEROUS_WINDOW: {
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)WParam;
+ if (!w32->Closed && !DestroyWindow(w32->Window)) {
log_error("Failed to destroy window (0x%lx).", GetLastError());
}
UnregisterClassW(DangerousClass, Global.ModuleHandle);
break;
+ }
case EXIT_PROCESS:
PostQuitMessage(WParam);
break;
@@ -370,7 +378,7 @@ void stl_global_close(void)
static void *GetAnyGLFuncAddress(const char *Name)
{
void *p = (void *)wglGetProcAddress(Name);
- if (p == 0 || (p == (void *)0x1) || (p == (void *)0x2) || (p == (void *)0x3) || (p == (void *)-1)) {
+ if (p == 0 || p == (void *)0x1 || p == (void *)0x2 || p == (void *)0x3 || p == (void *)-1) {
HMODULE GLModule = LoadLibraryA("opengl32.dll");
p = (void *)GetProcAddress(GLModule, Name);
}
@@ -669,6 +677,10 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
// Special case with Window as WParam.
PostThreadMessageW(MainThreadID, Message, (WPARAM)Window, LParam);
break;
+ /*
+ case WM_ERASEBKGND:
+ return TRUE;
+ */
case WM_MOUSEACTIVATE: {
LRESULT HitTest = LOWORD(LParam);
UINT MouseButton = HIWORD(LParam);
@@ -677,17 +689,19 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
}
break;
}
- case WM_LBUTTONDOWN: {
+ case WM_LBUTTONDOWN:
// https://learn.microsoft.com/en-us/windows/win32/learnwin32/mouse-movement
- SetCapture(w32->Window);
+ w32->DragCapture = TRUE;
+ if (!GetCapture()) {
+ SetCapture(w32->Window);
+ }
goto intercept;
- }
- case WM_LBUTTONUP: {
+ case WM_LBUTTONUP:
+ w32->DragCapture = FALSE;
ReleaseCapture();
goto intercept;
- }
case WM_RBUTTONDOWN:
- case WM_NCRBUTTONDOWN: {
+ case WM_NCRBUTTONDOWN:
#ifdef STELA_MOUSE2_DRAG
if (!Global.IsWine) {
POINT Pos;
@@ -699,7 +713,10 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
w32->LastMousePos.x = Pos.x;
w32->LastMousePos.y = Pos.y;
w32->WindowMoving = TRUE;
- SetCapture(w32->Window);
+ // DragCapture is a higher priority.
+ if (!w32->DragCapture) {
+ SetCapture(w32->Window);
+ }
return Result;
} else {
/*
@@ -716,49 +733,51 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
#else
goto intercept;
#endif
- }
case WM_RBUTTONUP:
- case WM_NCRBUTTONUP: {
+ case WM_NCRBUTTONUP:
#ifdef STELA_MOUSE2_DRAG
if (!Global.IsWine) {
w32->WindowMoving = FALSE;
- ReleaseCapture();
+ if (!w32->DragCapture) {
+ ReleaseCapture();
+ }
return Result;
}
break;
#else
goto intercept;
#endif
- }
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
goto intercept;
case WM_MOUSELEAVE:
goto intercept;
case WM_MOUSEMOVE:
- case WM_NCMOUSEMOVE: {
+ case WM_NCMOUSEMOVE:
if ((WParam & MK_RBUTTON) && w32->WindowMoving) {
- POINT Current;
- GetCursorPos(&Current);
+ POINT Pos;
+ Pos.x = GET_X_LPARAM(LParam);
+ Pos.y = GET_Y_LPARAM(LParam);
+ if (Message == WM_MOUSEMOVE) {
+ ClientToScreen(w32->Window, &Pos);
+ }
RECT Window;
GetWindowRect(w32->Window, &Window);
SetWindowPos(w32->Window, NULL,
- Window.left + (Current.x - w32->LastMousePos.x),
- Window.top + (Current.y - w32->LastMousePos.y),
+ Window.left + (Pos.x - w32->LastMousePos.x),
+ Window.top + (Pos.y - w32->LastMousePos.y),
0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
- w32->LastMousePos.x = Current.x;
- w32->LastMousePos.y = Current.y;
+ w32->LastMousePos.x = Pos.x;
+ w32->LastMousePos.y = Pos.y;
return Result;
}
goto intercept;
- }
case WM_MOUSEWHEEL:
goto intercept;
- case WM_ACTIVATE: {
- // Do not use Wine behavior as a reference, it's too broken.
+ case WM_ACTIVATE: // Don't use Wine behavior as a reference, it's too broken.
switch (LOWORD(WParam)) {
case WA_ACTIVE:
- case WA_CLICKACTIVE: {
+ case WA_CLICKACTIVE:
LParam = STELA_MOD_LCONTROL * ASYNC_KEY_IS_DOWN(VK_LCONTROL) |
STELA_MOD_RCONTROL * ASYNC_KEY_IS_DOWN(VK_RCONTROL) |
STELA_MOD_LSHIFT * ASYNC_KEY_IS_DOWN(VK_LSHIFT) |
@@ -766,13 +785,10 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
STELA_MOD_LALT * ASYNC_KEY_IS_DOWN(VK_LMENU) |
STELA_MOD_RALT * ASYNC_KEY_IS_DOWN(VK_RMENU);
break;
- }
- case WA_INACTIVE: {
+ case WA_INACTIVE:
break;
}
- }
goto intercept;
- }
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
@@ -780,8 +796,8 @@ static LRESULT CALLBACK DisplayWndProc(HWND Window, UINT Message, WPARAM WParam,
// https://learn.microsoft.com/en-us/windows/win32/inputdev/about-keyboard-input
WORD Flags = HIWORD(LParam);
bool PreviouslyDown = (Flags & KF_REPEAT) == KF_REPEAT;
- if (((Message == WM_KEYDOWN || Message == WM_SYSKEYDOWN) && PreviouslyDown) ||
- ((Message == WM_KEYUP || Message == WM_SYSKEYUP) && !PreviouslyDown)) {
+ if (((Message == WM_KEYDOWN || Message == WM_SYSKEYDOWN) && PreviouslyDown) ||
+ ((Message == WM_KEYUP || Message == WM_SYSKEYUP) && !PreviouslyDown)) {
break; // Repeat.
}
WORD Scancode = LOBYTE(Flags);
@@ -835,20 +851,20 @@ static bool CreateWGLContext(struct stl_window_win32 *w32)
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_DEPTH_DONTCARE,
#endif
PFD_TYPE_RGBA,
- 32, // Colordepth of the framebuffer.
+ 32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
#ifdef STELA_INCLUDE_DEPTH_BUFFER
- 24, // Bits for the depthbuffer.
- 8, // Bits for the stencilbuffer.
+ 24, // Bits for the depthbuffer.
+ 8, // Bits for the stencilbuffer.
#else
0,
0,
#endif
- 0, // Number of "Aux" buffers.
+ 0, // Number of "Aux" buffers.
PFD_MAIN_PLANE,
0,
0, 0, 0
@@ -924,38 +940,46 @@ static bool CreateWGLContext(struct stl_window_win32 *w32)
}
#endif
-static bool window_win32_create_window(struct stl_window *window, u32 width, u32 height,
- const char *monitor, const char *name, u32 flags)
+static bool window_win32_create_window(struct stl_window *window, u32 width, u32 height, u32 flags,
+ const char *monitor, const char *name, const char *app_id)
{
struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
(void)monitor;
+ (void)app_id;
WNDCLASSEXW WindowClass = { 0 };
WindowClass.cbSize = sizeof(WindowClass);
WindowClass.lpfnWndProc = &DisplayWndProc;
WindowClass.hInstance = Global.ModuleHandle;
- WindowClass.hIcon = LoadIconA(NULL, IDI_APPLICATION);
+ HANDLE Icon = LoadImageW(Global.ModuleHandle,
+ L"CMV_ICON", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);
+ if (!Icon) Icon = LoadIconA(NULL, IDI_APPLICATION);
+ WindowClass.hIcon = Icon;
WindowClass.hCursor = LoadCursorA(NULL, IDC_ARROW);
WindowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
WindowClass.lpszClassName = DangerousClass;
// https://learn.microsoft.com/en-us/windows/win32/winmsg/window-class-styles
- WindowClass.style = CS_OWNDC;
+ // On CS_HREDRAW | CS_VREDRAW: The idea is as long as we are equally as notified of
+ // window resizes, let us decide when to redraw.
+ WindowClass.style = 0;
RegisterClassExW(&WindowClass);
// Add in window decorations so width and height reference the client area.
- RECT Over = { 0, 0, width, height };
- AdjustWindowRect(&Over, WS_OVERLAPPEDWINDOW, FALSE);
+ RECT Overlap = { 0, 0, width, height };
+ AdjustWindowRect(&Overlap, WS_OVERLAPPEDWINDOW, FALSE);
struct the_baby Baby = { 0 };
- Baby.dwExStyle = 0;
Baby.lpClassName = WindowClass.lpszClassName;
al_wstr_from_cstr(&w32->WindowName, (char *)name);
Baby.lpWindowName = w32->WindowName.data;
+ // https://learn.microsoft.com/en-us/windows/win32/winmsg/window-styles
+ // https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles
Baby.dwStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
+ Baby.dwExStyle = 0;
Baby.X = CW_USEDEFAULT;
Baby.Y = CW_USEDEFAULT;
- Baby.nWidth = Over.right - Over.left;
- Baby.nHeight = Over.bottom - Over.top;
+ Baby.nWidth = Overlap.right - Overlap.left;
+ Baby.nHeight = Overlap.bottom - Overlap.top;
Baby.hInstance = WindowClass.hInstance;
Baby.lpParam = w32;
w32->Window = (HWND)SendMessageW(Global.ServiceWindow, CREATE_DANGEROUS_WINDOW, (WPARAM)&Baby, 0);
@@ -966,9 +990,12 @@ static bool window_win32_create_window(struct stl_window *window, u32 width, u32
stl_window_created(&w32->w, width, height, flags);
+ w32->Closed = FALSE;
w32->Decorated = TRUE;
w32->UserDecorated = TRUE;
w32->Prev.Style = GetWindowLong(w32->Window, GWL_STYLE);
+ w32->Prev.ExStyle = GetWindowLong(w32->Window, GWL_EXSTYLE);
+ w32->DragCapture = TRUE;
w32->WindowMoving = FALSE;
w32->MouseButtonMask = 0;
@@ -991,9 +1018,15 @@ static void window_win32_resize_internal(struct stl_window *window, u32 width, u
static void window_win32_resize(struct stl_window *window, u32 width, u32 height)
{
- (void)window;
- (void)width;
- (void)height;
+ struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
+ if (!w32->w.fullscreen) {
+ ShowWindow(w32->Window, SW_SHOWNOACTIVATE);
+ RECT Overlap = { 0, 0, width, height };
+ AdjustWindowRect(&Overlap, WS_OVERLAPPEDWINDOW, FALSE);
+ SetWindowPos(w32->Window, HWND_NOTOPMOST, 0, 0,
+ Overlap.right - Overlap.left, Overlap.bottom - Overlap.top,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ }
}
static struct stl_monitor_win32 *get_monitor_from_handle(HMONITOR Handle)
@@ -1007,18 +1040,55 @@ static struct stl_monitor_win32 *get_monitor_from_handle(HMONITOR Handle)
return NULL;
}
+// @TODO:
+// - Separate decorations and transparent background.
+// - Fix jump on toggle.
static void set_decorations(struct stl_window_win32 *w32, bool enabled)
{
- if (!enabled && w32->Decorated) {
+ if (!enabled && w32->Decorated) { // Voodoo...
// https://stackoverflow.com/a/2400467
LONG Style = GetWindowLong(w32->Window, GWL_STYLE);
+ LONG ExStyle = GetWindowLong(w32->Window, GWL_EXSTYLE);
w32->Prev.Style = Style;
+ w32->Prev.ExStyle = ExStyle;
Style &= ~(WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU);
+ //ExStyle |= WS_EX_LAYERED;
SetWindowLong(w32->Window, GWL_STYLE, Style);
+ //SetWindowLong(w32->Window, GWL_EXSTYLE, ExStyle);
+ //SetLayeredWindowAttributes(w32->Window, 0, 255, LWA_ALPHA);
+ //SetLayeredWindowAttributes(w32->Window, RGB(0, 0, 0), 0, LWA_COLORKEY);
+ /*
+ SetLayeredWindowAttributes(w32->Window, 0, 0, LWA_ALPHA);
+ BLENDFUNCTION blend = { 0 };
+ blend.BlendOp = AC_SRC_OVER;
+ blend.SourceConstantAlpha = 0;
+ blend.AlphaFormat = AC_SRC_ALPHA;
+ POINT ptLocation = { 0, 0 };
+ SIZE szWnd = { w32->w.width, w32->w.height };
+ POINT ptSrc = { 0, 0 };
+ UpdateLayeredWindow(w32->Window, NULL, &ptLocation, &szWnd, NULL, &ptSrc, 0, &blend, ULW_ALPHA);
+ */
+ // https://github.com/mpv-player/mpv/blob/dbd7a905b6ed47dd8f0acd09a1f4cc9a08e854a6/video/out/w32_common.c#L2575C1-L2575C30
+#ifndef NAUNET_WIN32_COMPAT_MODE
+ DWM_BLURBEHIND dbb = { 0 };
+ HRGN Region = CreateRectRgn(0, 0, -1, -1);
+ dbb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
+ dbb.hRgnBlur = Region;
+ dbb.fEnable = TRUE;
+ DwmEnableBlurBehindWindow(w32->Window, &dbb);
+ DeleteObject(Region);
+#endif
w32->Decorated = FALSE;
} else if (enabled && !w32->Decorated) {
al_assert(w32->Prev.Style != 0);
SetWindowLong(w32->Window, GWL_STYLE, w32->Prev.Style);
+ SetWindowLong(w32->Window, GWL_EXSTYLE, w32->Prev.ExStyle);
+#ifndef NAUNET_WIN32_COMPAT_MODE
+ DWM_BLURBEHIND dbb = { 0 };
+ dbb.dwFlags = DWM_BB_ENABLE;
+ dbb.fEnable = FALSE;
+ DwmEnableBlurBehindWindow(w32->Window, &dbb);
+#endif
w32->Decorated = TRUE;
}
}
@@ -1056,9 +1126,35 @@ static void window_win32_set_decorations(struct stl_window *window, bool enabled
struct stl_window_win32 *w32 = (struct stl_window_win32 *)window;
w32->UserDecorated = enabled;
if (!w32->w.fullscreen) {
+ s32 cx, cy, dx = 0, dy = 0;
+ if (!enabled) {
+ RECT Prev;
+ GetWindowRect(w32->Window, &Prev);
+ w32->Prev.X = Prev.left;
+ w32->Prev.Y = Prev.top;
+ w32->Prev.Width = Prev.right - Prev.left;
+ w32->Prev.Height = Prev.bottom - Prev.top;
+ //RECT Over = { 0, 0, w32->w.width, w32->w.height };
+ //AdjustWindowRect(&Over, WS_OVERLAPPEDWINDOW, FALSE);
+ cx = w32->w.width;
+ cy = w32->w.height;
+ // @TODO: What is 8?
+ dx = ((Prev.right - Prev.left) - cx) - 8;
+ dy = ((Prev.bottom - Prev.top) - cy) - 8;
+ dx = Prev.left + dx;
+ dy = Prev.top + dy;
+ } else {
+ RECT Over = { 0, 0, w32->w.width, w32->w.height };
+ AdjustWindowRect(&Over, WS_OVERLAPPEDWINDOW, FALSE);
+ cx = w32->Prev.Width;
+ cy = w32->Prev.Height;
+ dx = w32->Prev.X;
+ dy = w32->Prev.Y;
+ }
set_decorations(w32, enabled);
- UINT Flags = SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
- SetWindowPos(w32->Window, 0, 0, 0, 0, 0, Flags);
+ //UINT Flags = SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
+ UINT Flags = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSENDCHANGING | SWP_NOACTIVATE;
+ SetWindowPos(w32->Window, 0, dx, dy, cx, cy, Flags);
}
}
@@ -1079,6 +1175,7 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
case WM_CREATE:
break;
case WM_CLOSE:
+ w32->Closed = TRUE;
#ifdef STELA_API_OPENGL
wglDeleteContext(w32->GLContext); // Makes context not current.
#endif
@@ -1110,27 +1207,23 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_RELEASED, STELA_MOUSE1);
break;
}
- case WM_RBUTTONDOWN: {
+ case WM_RBUTTONDOWN:
w32->MouseButtonMask |= STELA_MOUSE2;
stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_PRESSED, STELA_MOUSE2);
break;
- }
- case WM_RBUTTONUP: {
+ case WM_RBUTTONUP:
w32->MouseButtonMask &= ~STELA_MOUSE2;
stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_RELEASED, STELA_MOUSE2);
break;
- }
- case WM_MBUTTONDOWN: {
+ case WM_MBUTTONDOWN:
w32->MouseButtonMask |= STELA_MOUSE3;
stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_PRESSED, STELA_MOUSE3);
break;
- }
- case WM_MBUTTONUP: {
+ case WM_MBUTTONUP:
w32->MouseButtonMask &= ~STELA_MOUSE3;
stl_window_send_mouse_button_event(&w32->w, STELA_BUTTON_RELEASED, STELA_MOUSE3);
break;
- }
- case WM_MOUSELEAVE: {
+ case WM_MOUSELEAVE:
/*
if (w32->MouseButtonMask & STELA_MOUSE1) {
w32->MouseButtonMask &= ~STELA_MOUSE1;
@@ -1138,17 +1231,14 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
}
*/
break;
- }
case WM_MOUSEMOVE:
case WM_NCMOUSEMOVE: {
POINT Pos;
Pos.x = GET_X_LPARAM(Message->lParam);
Pos.y = GET_Y_LPARAM(Message->lParam);
- /*
- if (!(w32->MouseButtonMask & STELA_MOUSE1)) {
+ if (Message->message == WM_NCMOUSEMOVE) {
ScreenToClient(w32->Window, &Pos);
}
- */
stl_window_send_pointer_pos_event(&w32->w, (f64)Pos.x, (f64)Pos.y);
break;
}
@@ -1159,7 +1249,7 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
stl_window_send_scroll_event(&w32->w, Bits);
break;
}
- case WM_ACTIVATE: {
+ case WM_ACTIVATE:
switch (LOWORD(Message->wParam)) {
case WA_ACTIVE:
case WA_CLICKACTIVE: {
@@ -1172,20 +1262,18 @@ static void win32_handle_message(struct stl_window_win32 *w32, MSG *Message)
}
break;
}
- case WA_INACTIVE: {
+ case WA_INACTIVE:
stl_window_drop_modifiers(&w32->w);
break;
}
- }
break;
- }
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
stl_window_send_key_event(&w32->w, MESSAGE_TO_KEY_STATE(Message->message), Global.keycodes[Message->wParam]);
break;
- case WM_SIZE:
+ case WM_SIZE: // Gives the size of the client area.
w32->w.width = LOWORD(Message->lParam);
w32->w.height = HIWORD(Message->lParam);
stl_window_send_resize_event(&w32->w, w32->w.width, w32->w.height);
@@ -1243,7 +1331,7 @@ static bool window_win32_should_refresh(struct stl_window *window)
static void window_win32_free(struct stl_window **window)
{
struct stl_window_win32 *w32 = (struct stl_window_win32 *)*window;
- SendMessageW(Global.ServiceWindow, DESTROY_DANGEROUS_WINDOW, (WPARAM)w32->Window, 0);
+ SendMessageW(Global.ServiceWindow, DESTROY_DANGEROUS_WINDOW, (WPARAM)w32, 0);
al_wstr_free(&w32->WindowName);
al_free(w32);
*window = NULL;
diff --git a/src/window_win32.h b/src/window_win32.h
index 317916e..7e639f0 100644
--- a/src/window_win32.h
+++ b/src/window_win32.h
@@ -3,9 +3,6 @@
#include <al/wstr.h>
#include <al/array.h>
#include <nnwt/windows.h>
-// All extra Windows headers come after <nnwt/windows.h>.
-#include <windowsx.h>
-#include <winuser.h>
#include "window.h"
@@ -45,9 +42,12 @@ struct stl_window_win32 {
s32 Width;
s32 Height;
LONG Style;
+ LONG ExStyle;
} Prev;
+ BOOL Closed;
BOOL Decorated;
BOOL UserDecorated;
+ BOOL DragCapture;
BOOL WindowMoving;
POINTS LastMousePos;
u32 MouseButtonMask;