Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify borderless code and improve resizing behavior and style #367

Merged
merged 2 commits into from
Dec 1, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 86 additions & 109 deletions src/os/gfx/win32/os_gfx_win32.c
Original file line number Diff line number Diff line change
Expand Up @@ -643,36 +643,22 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if(os_w32_new_window_custom_border || (window && window->custom_border))
{
DWORD window_style = GetWindowLong(hwnd, GWL_STYLE);
B32 window_is_fullscreen = !(window_style & WS_OVERLAPPEDWINDOW);
if(IsZoomed(hwnd) && !window_is_fullscreen)
{
F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f;
S32 title_bar_size = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYCAPTION, dpi) : 0;
S32 border_lr_size = 0;//w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : 0;
S32 border_b_size = 0;//w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : 0;
if(wParam == 1)
{
NCCALCSIZE_PARAMS *pncsp = (NCCALCSIZE_PARAMS *)lParam;
pncsp->rgrc[0].top -= title_bar_size;
pncsp->rgrc[0].left += border_lr_size;
pncsp->rgrc[0].right -= border_lr_size;
pncsp->rgrc[0].bottom -= border_b_size;
}
else
{
RECT *rect = (RECT *)lParam;
rect->top -= title_bar_size;
rect->left += border_lr_size;
rect->right -= border_lr_size;
rect->bottom -= border_b_size;
}
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
}
else if(wParam == 1)
F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f;
S32 frame_x = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXFRAME, dpi) : GetSystemMetrics(SM_CXFRAME);
S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);

RECT* rect = wParam == 0 ? (RECT*)lParam : ((NCCALCSIZE_PARAMS*)lParam)->rgrc;
rect->right -= frame_x + padding;
rect->left += frame_x + padding;
rect->bottom -= frame_y + padding;

if (IsMaximized(hwnd))
{
NCCALCSIZE_PARAMS *pncsp = (NCCALCSIZE_PARAMS *)lParam;
pncsp->rgrc[0].right += 1;
rect->top += frame_y + padding;
// If we do not do this hidden taskbar can not be unhidden on mouse hover
// Unfortunately it can create an ugly bottom border when maximized...
rect->bottom -= 1;
}
}
else
Expand All @@ -692,100 +678,91 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
}
else
{
POINT pos_monitor;
pos_monitor.x = GET_X_LPARAM(lParam);
pos_monitor.y = GET_Y_LPARAM(lParam);
POINT pos_client = pos_monitor;
ScreenToClient(hwnd, &pos_client);
B32 is_default_handled = 0;

//- rjf: check against window boundaries
RECT frame_rect;
GetWindowRect(hwnd, &frame_rect);
B32 is_over_window = (frame_rect.left <= pos_monitor.x && pos_monitor.x < frame_rect.right &&
frame_rect.top <= pos_monitor.y && pos_monitor.y < frame_rect.bottom);
// Let the default procedure handle resizing areas
result = DefWindowProc(hwnd, uMsg, wParam, lParam);
switch (result)
{
case HTNOWHERE:
case HTRIGHT:
case HTLEFT:
case HTTOPLEFT:
case HTTOPRIGHT:
case HTBOTTOMRIGHT:
case HTBOTTOM:
case HTBOTTOMLEFT:
{
is_default_handled = 1;
} break;
}

//- rjf: check against borders
B32 is_over_left = 0;
B32 is_over_right = 0;
B32 is_over_top = 0;
B32 is_over_bottom = 0;
if (!is_default_handled)
{
RECT rect;
GetClientRect(hwnd, &rect);
if(!IsZoomed(hwnd))
POINT pos_monitor;
pos_monitor.x = GET_X_LPARAM(lParam);
pos_monitor.y = GET_Y_LPARAM(lParam);
POINT pos_client = pos_monitor;
ScreenToClient(hwnd, &pos_client);

// Adjustments happening in NCCALCSIZE are messing with the detection
// of the top hit area so manually checking that.
F32 dpi = w32_GetDpiForWindow_func ? (F32)w32_GetDpiForWindow_func(hwnd) : 96.f;
S32 frame_y = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
S32 padding = w32_GetSystemMetricsForDpi_func ? w32_GetSystemMetricsForDpi_func(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER);

B32 is_over_top_resize = pos_client.y >= 0 && pos_client.y < frame_y + padding;
B32 is_over_title_bar = pos_client.y >= 0 && pos_client.y < window->custom_border_title_thickness;

//- rjf: check against title bar client areas
B32 is_over_title_bar_client_area = 0;
for(OS_W32_TitleBarClientArea *area = window->first_title_bar_client_area;
area != 0;
area = area->next)
{
if(rect.left <= pos_client.x && pos_client.x < rect.left + window->custom_border_edge_thickness)
Rng2F32 rect = area->rect;
if(rect.x0 <= pos_client.x && pos_client.x < rect.x1 &&
rect.y0 <= pos_client.y && pos_client.y < rect.y1)
{
is_over_left = 1;
is_over_title_bar_client_area = 1;
break;
}
if(rect.right - window->custom_border_edge_thickness <= pos_client.x && pos_client.x < rect.right)
}

if (IsMaximized(hwnd))
{
if (is_over_title_bar_client_area)
{
is_over_right = 1;
result = HTCLIENT;
}
if(rect.bottom - window->custom_border_edge_thickness <= pos_client.y && pos_client.y < rect.bottom)
else if (is_over_title_bar)
{
is_over_bottom = 1;
result = HTCAPTION;
}
if(rect.top <= pos_client.y && pos_client.y < rect.top + window->custom_border_edge_thickness)
else
{
is_over_top = 1;
result = HTCLIENT;
}
}
}

//- rjf: check against title bar
B32 is_over_title_bar = 0;
{
RECT rect;
GetClientRect(hwnd, &rect);
is_over_title_bar = (rect.left <= pos_client.x && pos_client.x < rect.right &&
rect.top <= pos_client.y && pos_client.y < rect.top + window->custom_border_title_thickness);
}

//- rjf: check against title bar client areas
B32 is_over_title_bar_client_area = 0;
for(OS_W32_TitleBarClientArea *area = window->first_title_bar_client_area;
area != 0;
area = area->next)
{
Rng2F32 rect = area->rect;
if(rect.x0 <= pos_client.x && pos_client.x < rect.x1 &&
rect.y0 <= pos_client.y && pos_client.y < rect.y1)
{
is_over_title_bar_client_area = 1;
break;
}
}

//- rjf: resolve hovering to result
result = HTNOWHERE;
if(is_over_window)
{
// rjf: default to client area
result = HTCLIENT;

// rjf: title bar
if(is_over_title_bar)
{
result = HTCAPTION;
}

// rjf: normal edges
if(is_over_left) { result = HTLEFT; }
if(is_over_right) { result = HTRIGHT; }
if(is_over_top) { result = HTTOP; }
if(is_over_bottom) { result = HTBOTTOM; }

// rjf: corners
if(is_over_left && is_over_top) { result = HTTOPLEFT; }
if(is_over_left && is_over_bottom) { result = HTBOTTOMLEFT; }
if(is_over_right && is_over_top) { result = HTTOPRIGHT; }
if(is_over_right && is_over_bottom) { result = HTBOTTOMRIGHT; }

// rjf: title bar client area
if(is_over_title_bar_client_area)
else
{
result = HTCLIENT;
//Swap the first two conditions to choose if hovering the top border
//should prioritize resize or title bar buttons.
if (is_over_title_bar_client_area)
{
result = HTCLIENT;
}
else if (is_over_top_resize)
{
result = HTTOP;
}
else if (is_over_title_bar)
{
result = HTCAPTION;
}
else {
result = HTCLIENT;
}
}
}
}
Expand Down