Simplify DisplayServerWindows pos/size message handling

Replace WM_MOVE and WM_SIZE message handling with WM_POSCHANGED instead.
This is for multiple reasons:
1) Microsoft suggest using WM_POSCHANGED is more efficient
2) RectChanged callback is only called once for most window operations
3) Simplifies message handling code
This commit is contained in:
SeleckyErik 2021-11-05 21:36:13 +01:00
parent 2c85f2a8f6
commit d14165dae9
2 changed files with 49 additions and 76 deletions

View File

@ -2646,98 +2646,72 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
}
} break;
case WM_MOVE: {
if (!IsIconic(windows[window_id].hWnd)) {
int x = int16_t(LOWORD(lParam));
int y = int16_t(HIWORD(lParam));
windows[window_id].last_pos = Point2(x, y);
if (!windows[window_id].rect_changed_callback.is_null()) {
Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height);
Variant *sizep = &size;
Variant ret;
Callable::CallError ce;
windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
}
case WM_WINDOWPOSCHANGED: {
Rect2i window_client_rect;
{
RECT rect;
GetClientRect(hWnd, &rect);
ClientToScreen(hWnd, (POINT *)&rect.left);
ClientToScreen(hWnd, (POINT *)&rect.right);
window_client_rect = Rect2i(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
}
} break;
case WM_SIZE: {
// Ignore window size change when a SIZE_MINIMIZED event is triggered.
if (wParam != SIZE_MINIMIZED) {
// The new width and height of the client area.
int window_w = LOWORD(lParam);
int window_h = HIWORD(lParam);
// Set new value to the size if it isn't preserved.
if (window_w > 0 && window_h > 0 && !windows[window_id].preserve_window_size) {
windows[window_id].width = window_w;
windows[window_id].height = window_h;
WINDOWPOS *window_pos_params = (WINDOWPOS *)lParam;
WindowData &window = windows[window_id];
bool rect_changed = false;
if (!(window_pos_params->flags & SWP_NOSIZE) || window_pos_params->flags & SWP_FRAMECHANGED) {
int screen_id = window_get_current_screen(window_id);
Size2i screen_size = screen_get_size(screen_id);
Point2i screen_position = screen_get_position(screen_id);
window.maximized = false;
window.minimized = false;
window.fullscreen = false;
if (IsIconic(hWnd)) {
window.minimized = true;
} else if (IsZoomed(hWnd)) {
window.maximized = true;
} else if (window_client_rect.position == screen_position && window_client_rect.size == screen_size) {
window.fullscreen = true;
}
if (!window.minimized) {
window.width = window_client_rect.size.width;
window.height = window_client_rect.size.height;
#if defined(VULKAN_ENABLED)
if (context_vulkan && window_created) {
context_vulkan->window_resize(window_id, windows[window_id].width, windows[window_id].height);
context_vulkan->window_resize(window_id, window.width, window.height);
}
#endif
} else { // If the size is preserved.
windows[window_id].preserve_window_size = false;
// Restore the old size.
window_set_size(Size2(windows[window_id].width, windows[window_id].height), window_id);
rect_changed = true;
}
} else { // When the window has been minimized, preserve its size.
windows[window_id].preserve_window_size = true;
}
// Call windows rect change callback.
if (!windows[window_id].rect_changed_callback.is_null()) {
Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height);
Variant *size_ptr = &size;
Variant ret;
Callable::CallError ce;
windows[window_id].rect_changed_callback.call((const Variant **)&size_ptr, 1, ret, ce);
if (!window.minimized && (!(window_pos_params->flags & SWP_NOMOVE) || window_pos_params->flags & SWP_FRAMECHANGED)) {
window.last_pos = window_client_rect.position;
rect_changed = true;
}
// The window has been maximized.
if (wParam == SIZE_MAXIMIZED) {
windows[window_id].maximized = true;
windows[window_id].minimized = false;
if (rect_changed) {
if (!window.rect_changed_callback.is_null()) {
Variant size = Rect2i(window.last_pos.x, window.last_pos.y, window.width, window.height);
const Variant *args[] = { &size };
Variant ret;
Callable::CallError ce;
window.rect_changed_callback.call(args, 1, ret, ce);
}
}
// The window has been minimized.
else if (wParam == SIZE_MINIMIZED) {
windows[window_id].maximized = false;
windows[window_id].minimized = true;
windows[window_id].preserve_window_size = false;
}
// The window has been resized, but neither the SIZE_MINIMIZED nor SIZE_MAXIMIZED value applies.
else if (wParam == SIZE_RESTORED) {
windows[window_id].maximized = false;
windows[window_id].minimized = false;
}
#if 0
if (is_layered_allowed() && layered_window) {
DeleteObject(hBitmap);
RECT r;
GetWindowRect(hWnd, &r);
dib_size = Size2i(r.right - r.left, r.bottom - r.top);
// Return here to prevent WM_MOVE and WM_SIZE from being sent
// See: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged#remarks
return 0;
BITMAPINFO bmi;
ZeroMemory(&bmi, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = dib_size.x;
bmi.bmiHeader.biHeight = dib_size.y;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4;
hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, nullptr, 0x0);
SelectObject(hDC_dib, hBitmap);
ZeroMemory(dib_data, dib_size.x * dib_size.y * 4);
}
#endif
} break;
case WM_ENTERSIZEMOVE: {
Input::get_singleton()->release_pressed_events();
windows[window_id].move_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);

View File

@ -326,7 +326,6 @@ class DisplayServerWindows : public DisplayServer {
Vector<Vector2> mpath;
bool preserve_window_size = false;
bool pre_fs_valid = false;
RECT pre_fs_rect;
bool maximized = false;