Partially merged from MohitSethi99/glfw with modifications

- Still some problems and not super happy with this partially decorated frame
- Tested on Win 10 and 11, client area top + resize handle is not perfect
- Also client area seems to be different on frame 0
This commit is contained in:
TheCherno 2023-07-16 14:29:50 +10:00
commit c186bef662
2 changed files with 116 additions and 74 deletions

View File

@ -2,6 +2,7 @@ project "GLFW"
kind "StaticLib" kind "StaticLib"
language "C" language "C"
staticruntime "off" staticruntime "off"
warnings "off"
targetdir ("bin/" .. outputdir .. "/%{prj.name}") targetdir ("bin/" .. outputdir .. "/%{prj.name}")
objdir ("bin-int/" .. outputdir .. "/%{prj.name}") objdir ("bin-int/" .. outputdir .. "/%{prj.name}")
@ -37,6 +38,7 @@ project "GLFW"
"src/x11_monitor.c", "src/x11_monitor.c",
"src/x11_window.c", "src/x11_window.c",
"src/xkb_unicode.c", "src/xkb_unicode.c",
"src/posix_module.c",
"src/posix_time.c", "src/posix_time.c",
"src/posix_thread.c", "src/posix_thread.c",
"src/posix_module.c", "src/posix_module.c",
@ -102,9 +104,9 @@ project "GLFW"
filter "configurations:Release" filter "configurations:Release"
runtime "Release" runtime "Release"
optimize "on" optimize "speed"
filter "configurations:Dist" filter "configurations:Dist"
runtime "Release" runtime "Release"
optimize "on" optimize "speed"
symbols "off" symbols "off"

View File

@ -490,7 +490,8 @@ static void releaseMonitor(_GLFWwindow* window)
static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam) WPARAM wParam, LPARAM lParam)
{ {
static RECT border_thickness; static RECT border_thickness = { 4, 4, 4, 4 };
BOOL hasThickFrame = GetWindowLongPtr(hWnd, GWL_STYLE) & WS_THICKFRAME;
_GLFWwindow* window = GetPropW(hWnd, L"GLFW"); _GLFWwindow* window = GetPropW(hWnd, L"GLFW");
if (!window) if (!window)
@ -548,22 +549,21 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (_glfw.hints.window.titlebar) if (_glfw.hints.window.titlebar)
break; break;
//find border thickness if (hasThickFrame)
SetRectEmpty(&border_thickness);
if (GetWindowLongPtr(hWnd, GWL_STYLE) & WS_THICKFRAME)
{ {
AdjustWindowRectEx(&border_thickness, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION, FALSE, 0); RECT size_rect;
border_thickness.left *= -1; GetWindowRect(hWnd, &size_rect);
border_thickness.top *= -1;
}
else// if (GetWindowLongPtr(hWnd, GWL_STYLE) & WS_BORDER)
{
SetRect(&border_thickness, 4, 4, 4, 4);
}
MARGINS margins = { 0 }; // Inform the application of the frame change to force redrawing with the new
DwmExtendFrameIntoClientArea(hWnd, &margins); // client area that is extended into the title bar
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED); SetWindowPos(
hWnd, NULL,
size_rect.left, size_rect.top,
size_rect.right - size_rect.left, size_rect.bottom - size_rect.top,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE
);
break;
}
break; break;
} }
@ -573,15 +573,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (_glfw.hints.window.titlebar) if (_glfw.hints.window.titlebar)
break; break;
// Extend the frame into the client area. RECT title_bar_rect = {0};
MARGINS margins = { 0 }; InvalidateRect(hWnd, &title_bar_rect, FALSE);
auto hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
if (!SUCCEEDED(hr))
{
// Handle the error.
}
break; break;
} }
} }
@ -1013,16 +1006,48 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
break; break;
} }
case WM_NCCALCSIZE: case WM_NCCALCSIZE:
{ {
if (_glfw.hints.window.titlebar) if (_glfw.hints.window.titlebar || !hasThickFrame || !wParam)
break; break;
if (lParam) // For custom frames
return 0;
// Shrink client area by border thickness so we can
// resize window and see borders
const int resizeBorderX = GetSystemMetrics(SM_CXFRAME);
const int resizeBorderY = GetSystemMetrics(SM_CYFRAME);
NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)lParam;
RECT* requestedClientRect = params->rgrc;
requestedClientRect->right -= resizeBorderX;
requestedClientRect->left += resizeBorderX;
requestedClientRect->bottom -= resizeBorderY;
//
// NOTE(Yan):
//
// Top borders seem to be handled differently.
//
// Contracting by 1 on Win 11 seems to give a small area
// for resizing whilst not showing a white border.
//
// But this doesn't seem to work on Win 10, instead showing
// a general white titlebar on top of the custom one...
// to be continued.
//
// Not changing the top (i.e. 0) means we don't see the
// mouse icon change to a resize handle, but resizing still
// works once you click and drag. This works on both
// Windows 10 & 11, so we'll keep that for now.
requestedClientRect->top += 0;
// NOTE(Yan): seems to make no difference what we return here,
// was originally 0
return WVR_ALIGNTOP | WVR_ALIGNLEFT;
}
break;
}
case WM_SIZE: case WM_SIZE:
{ {
const int width = LOWORD(lParam); const int width = LOWORD(lParam);
@ -1063,6 +1088,18 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
window->win32.iconified = iconified; window->win32.iconified = iconified;
window->win32.maximized = maximized; window->win32.maximized = maximized;
RECT size_rect;
GetWindowRect(hWnd, &size_rect);
// Inform the application of the frame change to force redrawing with the new
// client area that is extended into the title bar
SetWindowPos(
hWnd, NULL,
size_rect.left, size_rect.top,
size_rect.right - size_rect.left, size_rect.bottom - size_rect.top,
SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE
);
return 0; return 0;
} }
@ -1271,54 +1308,57 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
if (_glfw.hints.window.titlebar) if (_glfw.hints.window.titlebar)
break; break;
// Extend the frame into the client area. RECT title_bar_rect = { 0 };
MARGINS margins = { 0 }; InvalidateRect(hWnd, &title_bar_rect, FALSE);
auto hr = DwmExtendFrameIntoClientArea(hWnd, &margins);
if (!SUCCEEDED(hr))
{
// Handle the error.
}
break;
} }
case WM_NCHITTEST: case WM_NCHITTEST:
{ {
if (_glfw.hints.window.titlebar) if (_glfw.hints.window.titlebar || !hasThickFrame)
break; break;
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; //
ScreenToClient(hWnd, &pt); // Hit test for custom frames
RECT rc; //
GetClientRect(hWnd, &rc); POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
ScreenToClient(hWnd, &pt);
int titlebarHittest = 0; // Check borders first
_glfwInputTitleBarHitTest(window, pt.x, pt.y, &titlebarHittest); if (!window->win32.maximized)
{
RECT rc;
GetClientRect(hWnd, &rc);
if (titlebarHittest) const int verticalBorderSize = GetSystemMetrics(SM_CYFRAME);
{
return HTCAPTION;
}
else
{
enum { left = 1, top = 2, right = 4, bottom = 8 };
int hit = 0;
if (pt.x < border_thickness.left) hit |= left;
if (pt.x > rc.right - border_thickness.right) hit |= right;
if (pt.y < border_thickness.top) hit |= top;
if (pt.y > rc.bottom - border_thickness.bottom) hit |= bottom;
if (hit & top && hit & left) return HTTOPLEFT; enum { left = 1, top = 2, right = 4, bottom = 8 };
if (hit & top && hit & right) return HTTOPRIGHT; int hit = 0;
if (hit & bottom && hit & left) return HTBOTTOMLEFT; if (pt.x <= border_thickness.left)
if (hit & bottom && hit & right) return HTBOTTOMRIGHT; hit |= left;
if (hit & left) return HTLEFT; if (pt.x >= rc.right - border_thickness.right)
hit |= right;
if (pt.y <= border_thickness.top || pt.y < verticalBorderSize)
hit |= top;
if (pt.y >= rc.bottom - border_thickness.bottom)
hit |= bottom;
if (hit & top && hit & left) return HTTOPLEFT;
if (hit & top && hit & right) return HTTOPRIGHT;
if (hit & bottom && hit & left) return HTBOTTOMLEFT;
if (hit & bottom && hit & right) return HTBOTTOMRIGHT;
if (hit & left) return HTLEFT;
if (hit & top) return HTTOP; if (hit & top) return HTTOP;
if (hit & right) return HTRIGHT; if (hit & right) return HTRIGHT;
if (hit & bottom) return HTBOTTOM; if (hit & bottom) return HTBOTTOM;
}
return HTCLIENT; // Then do client-side test which should determine titlebar bounds
} int titlebarHittest = 0;
_glfwInputTitleBarHitTest(window, pt.x, pt.y, &titlebarHittest);
if (titlebarHittest)
return HTCAPTION;
// In client area
return HTCLIENT;
} }
} }