From e79de5b2b3ba48ee62268a9dfc8fa0921c09f2db Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 2 Jun 2021 13:46:00 +0200 Subject: [PATCH] Added dynamic resolution patch Provided in https://github.com/FreeRDP/FreeRDP/issues/7072 by @277hz --- client/Windows/wf_channels.c | 8 +++++ client/Windows/wf_channels.h | 1 + client/Windows/wf_client.c | 7 +++- client/Windows/wf_client.h | 2 ++ client/Windows/wf_event.c | 70 ++++++++++++++++++++++++++++++++++-- 5 files changed, 85 insertions(+), 3 deletions(-) diff --git a/client/Windows/wf_channels.c b/client/Windows/wf_channels.c index 3afd52dbb..a07f64e01 100644 --- a/client/Windows/wf_channels.c +++ b/client/Windows/wf_channels.c @@ -57,6 +57,10 @@ void wf_OnChannelConnectedEventHandler(void* context, ChannelConnectedEventArgs* else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0) { } + else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) + { + wfc->disp = (DispClientContext*)e->pInterface; + } } void wf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEventArgs* e) @@ -82,4 +86,8 @@ void wf_OnChannelDisconnectedEventHandler(void* context, ChannelDisconnectedEven else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0) { } + else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0) + { + wfc->disp = NULL; + } } diff --git a/client/Windows/wf_channels.h b/client/Windows/wf_channels.h index 5e4ca52e3..64a408ac6 100644 --- a/client/Windows/wf_channels.h +++ b/client/Windows/wf_channels.h @@ -25,6 +25,7 @@ #include #include #include +#include #include "wf_client.h" diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index ef7d4abee..4bf563c16 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -276,6 +276,11 @@ static void wf_add_system_menu(wfContext* wfc) return; } + if (wfc->context.settings->DynamicResolutionUpdate) + { + return; + } + hMenu = GetSystemMenu(wfc->hwnd, FALSE); ZeroMemory(&item_info, sizeof(MENUITEMINFO)); item_info.fMask = MIIM_CHECKMARKS | MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_DATA; @@ -899,7 +904,7 @@ void wf_size_scrollbars(wfContext* wfc, UINT32 client_width, UINT32 client_heigh // prevent infinite message loop wfc->disablewindowtracking = TRUE; - if (wfc->context.settings->SmartSizing) + if (wfc->context.settings->SmartSizing || wfc->context.settings->DynamicResolutionUpdate) { wfc->xCurrentScroll = 0; wfc->yCurrentScroll = 0; diff --git a/client/Windows/wf_client.h b/client/Windows/wf_client.h index 29f194a8e..1850fa78f 100644 --- a/client/Windows/wf_client.h +++ b/client/Windows/wf_client.h @@ -134,6 +134,8 @@ extern "C" RailClientContext* rail; wHashTable* railWindows; BOOL isConsole; + + DispClientContext* disp; }; /** diff --git a/client/Windows/wf_event.c b/client/Windows/wf_event.c index d1ded4c13..e26c1cfd7 100644 --- a/client/Windows/wf_event.c +++ b/client/Windows/wf_event.c @@ -39,6 +39,10 @@ static HWND g_focus_hWnd; #define X_POS(lParam) ((UINT16)(lParam & 0xFFFF)) #define Y_POS(lParam) ((UINT16)((lParam >> 16) & 0xFFFF)) +#define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */ +static UINT64 lastSentDate; +static BOOL wasMaximized; + static BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); static BOOL wf_scale_mouse_event(wfContext* wfc, rdpInput* input, UINT16 flags, UINT16 x, UINT16 y); @@ -221,7 +225,8 @@ static void wf_sizing(wfContext* wfc, WPARAM wParam, LPARAM lParam) // Holding the CTRL key down while resizing the window will force the desktop aspect ratio. LPRECT rect; - if (settings->SmartSizing && (GetAsyncKeyState(VK_CONTROL) & 0x8000)) + if ((settings->SmartSizing || settings->DynamicResolutionUpdate) && + (GetAsyncKeyState(VK_CONTROL) & 0x8000)) { rect = (LPRECT)wParam; @@ -253,6 +258,51 @@ static void wf_sizing(wfContext* wfc, WPARAM wParam, LPARAM lParam) } } +void wf_send_resize(wfContext* wfc) +{ + RECT windowRect; + DISPLAY_CONTROL_MONITOR_LAYOUT* layout; + int targetWidth = wfc->client_width; + int targetHeight = wfc->client_height; + rdpSettings* settings = wfc->context.settings; + + if (settings->DynamicResolutionUpdate && wfc->disp != NULL) + { + if (GetTickCount64() - lastSentDate > RESIZE_MIN_DELAY) + { + if (wfc->fullscreen) + { + GetWindowRect(wfc->hwnd, &windowRect); + targetWidth = windowRect.right - windowRect.left; + targetHeight = windowRect.bottom - windowRect.top; + } + if (settings->SmartSizingWidth != targetWidth || + settings->SmartSizingHeight != targetHeight) + { + layout = calloc(1, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT)); + layout->Flags = DISPLAY_CONTROL_MONITOR_PRIMARY; + layout->Top = layout->Left = 0; + layout->Width = targetWidth; + layout->Height = targetHeight; + layout->Orientation = settings->DesktopOrientation; + layout->DesktopScaleFactor = settings->DesktopScaleFactor; + layout->DeviceScaleFactor = settings->DeviceScaleFactor; + layout->PhysicalWidth = targetWidth; + layout->PhysicalHeight = targetHeight; + if (IFCALLRESULT(CHANNEL_RC_OK, wfc->disp->SendMonitorLayout, wfc->disp, 1, + layout) != CHANNEL_RC_OK) + { + WLog_ERR("", "SendMonitorLayout failed."); + } + free(layout); + settings->SmartSizingWidth = targetWidth; + settings->SmartSizingHeight = targetHeight; + } + lastSentDate = GetTickCount64(); + } + } +} + LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { HDC hdc; @@ -287,7 +337,8 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam break; case WM_GETMINMAXINFO: - if (wfc->context.settings->SmartSizing) + if (wfc->context.settings->SmartSizing || + wfc->context.settings->DynamicResolutionUpdate) { processed = FALSE; } @@ -324,6 +375,11 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam wfc->client_x = windowRect.left; wfc->client_y = windowRect.top; } + else + { + wasMaximized = TRUE; + wf_send_resize(wfc); + } if (wfc->client_width && wfc->client_height) { @@ -332,15 +388,25 @@ LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam // Workaround: when the window is maximized, the call to "ShowScrollBars" // returns TRUE but has no effect. if (wParam == SIZE_MAXIMIZED && !wfc->fullscreen) + { SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_NOMOVE | SWP_FRAMECHANGED); + wasMaximized = TRUE; + wf_send_resize(wfc); + } + else if (wParam == SIZE_RESTORED && !wfc->fullscreen && wasMaximized) + { + wasMaximized = FALSE; + wf_send_resize(wfc); + } } break; case WM_EXITSIZEMOVE: wf_size_scrollbars(wfc, wfc->client_width, wfc->client_height); + wf_send_resize(wfc); break; case WM_ERASEBKGND: