From 697529028a95a09e2fc9bd17fcfb12e357b96905 Mon Sep 17 00:00:00 2001 From: Wouter Date: Fri, 24 Apr 2020 18:10:14 +0200 Subject: [PATCH 1/4] Support per-monitor DPI scaling. - Mark application as PerMonitorV2 aware in manifest file. - Replace old SHBrowseForFolder folder picker with newer IFileOpenDialog API, which scales better - Handle WM_DPICHANGED messages to update options.dpi_scale. This is then used to re-layout the status window. For this, dpi_setscale() was moved to options.h so it could be accessed by openvpn.c --- main.c | 16 +------ openvpn.c | 7 +++ options.c | 96 ++++++++++++++++++++++++++++++---------- options.h | 1 + res/openvpn-gui.manifest | 9 +++- 5 files changed, 89 insertions(+), 40 deletions(-) diff --git a/main.c b/main.c index c877ea6..0436cb1 100644 --- a/main.c +++ b/main.c @@ -384,20 +384,6 @@ ResumeConnections() } } -/* - * Set scale factor of windows in pixels. Scale = 100% for dpi = 96 - */ -static void -dpi_setscale(UINT dpix) -{ - /* scale factor in percentage compared to the reference dpi of 96 */ - if (dpix != 0) - o.dpi_scale = MulDiv(dpix, 100, 96); - else - o.dpi_scale = 100; - PrintDebug(L"DPI scale set to %u", o.dpi_scale); -} - /* * Get dpi of the system and set the scale factor. * The system dpi may be different from the per monitor dpi on @@ -423,7 +409,7 @@ dpi_initialize(void) dpix = 96; } - dpi_setscale(dpix); + DpiSetScale(&o, dpix); } static int diff --git a/openvpn.c b/openvpn.c index f0c4c8b..d01a99f 100644 --- a/openvpn.c +++ b/openvpn.c @@ -1656,6 +1656,13 @@ StatusDialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) SetFocus(hLogWnd); return FALSE; + case WM_DPICHANGED: + DpiSetScale(&o, HIWORD(wParam)); + RECT dlgRect; + GetClientRect(hwndDlg, &dlgRect); + RenderStatusWindow(hwndDlg, dlgRect.right, dlgRect.bottom); + return FALSE; + case WM_SIZE: RenderStatusWindow(hwndDlg, LOWORD(lParam), HIWORD(lParam)); InvalidateRect(hwndDlg, NULL, TRUE); diff --git a/options.c b/options.c index addd2dc..02cb19a 100644 --- a/options.c +++ b/options.c @@ -34,8 +34,12 @@ #include #include #include +#include #include "options.h" + +#include + #include "main.h" #include "openvpn-gui-res.h" #include "localization.h" @@ -400,6 +404,19 @@ ProcessCommandLine(options_t *options, TCHAR *command_line) ExpandOptions (); } +/* + * Set scale factor of windows in pixels. Scale = 100% for dpi = 96 + */ +void +DpiSetScale(options_t * options, UINT dpix) +{ + /* scale factor in percentage compared to the reference dpi of 96 */ + if (dpix != 0) + o.dpi_scale = MulDiv(dpix, 100, 96); + else + o.dpi_scale = 100; + PrintDebug(L"DPI scale set to %u", o.dpi_scale); +} /* Return num of connections with state = check */ int @@ -441,37 +458,68 @@ GetConnByName(const WCHAR *name) return NULL; } -/* callback to set the initial value of folder browse selection */ -static int CALLBACK -BrowseCallback (HWND h, UINT msg, UNUSED LPARAM l, LPARAM data) -{ - if (msg == BFFM_INITIALIZED) - SendMessage (h, BFFM_SETSELECTION, TRUE, data); - - return 0; -} - static BOOL -BrowseFolder (const WCHAR *initial_path, WCHAR *selected_path) +BrowseFolder (const WCHAR* initial_path, WCHAR* selected_path) { - BOOL ret = false; - BROWSEINFO bi; + IFileOpenDialog* pfd; + HRESULT initResult, result, dialogResult; - CLEAR(bi); - bi.lpszTitle = L"Select folder..."; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; - bi.lpfn = BrowseCallback; - bi.lParam = (LPARAM) initial_path; + // Create dialog + initResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + assert(SUCCEEDED(initResult)); + + result = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, &pfd); + assert(SUCCEEDED(result)); - PIDLIST_ABSOLUTE idlist = SHBrowseForFolder (&bi); - - if (idlist) + // Select folders, not files { - ret = SHGetPathFromIDList (idlist, selected_path); - CoTaskMemFree (idlist); + DWORD dwOptions; + result = pfd->lpVtbl->GetOptions(pfd, &dwOptions); + assert(SUCCEEDED(result)); + dwOptions |= FOS_PICKFOLDERS; + result = pfd->lpVtbl->SetOptions(pfd, dwOptions); + assert(SUCCEEDED(result)); } - return ret; + // Set initial path + { + IShellItem* psi; + result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, &psi); + if (SUCCEEDED(result)) + { + pfd->lpVtbl->SetDefaultFolder(pfd, psi); + psi->lpVtbl->Release(psi); + } + } + + // Show dialog and copy the selected file path if the user didn't cancel + dialogResult = pfd->lpVtbl->Show(pfd, NULL); + if (SUCCEEDED(dialogResult)) + { + IShellItem* psi; + LPOLESTR path = NULL; + + assert(SUCCEEDED(pfd->lpVtbl->GetResult(pfd, &psi))); + + assert(SUCCEEDED(psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &path))); + + wcsncpy_s(selected_path, MAX_PATH, path, MAX_PATH); + selected_path[MAX_PATH - 1] = 0; + + CoTaskMemFree(path); + + psi->lpVtbl->Release(psi); + } + + // Cleanup + pfd->lpVtbl->Release(pfd); + + if (initResult != RPC_E_CHANGED_MODE && SUCCEEDED(initResult)) + { + CoUninitialize(); //All successful CoInitializeEx calls must be balanced by a corresponding CoUninitialize + } + + return SUCCEEDED(dialogResult); } static BOOL diff --git a/options.h b/options.h index c523f6f..79e3855 100644 --- a/options.h +++ b/options.h @@ -225,6 +225,7 @@ typedef struct { void InitOptions(options_t *); void ProcessCommandLine(options_t *, TCHAR *); +void DpiSetScale(options_t *, UINT dpix); int CountConnState(conn_state_t); connection_t* GetConnByManagement(SOCKET); connection_t* GetConnByName(const WCHAR *config_name); diff --git a/res/openvpn-gui.manifest b/res/openvpn-gui.manifest index a8f9a97..5509c03 100644 --- a/res/openvpn-gui.manifest +++ b/res/openvpn-gui.manifest @@ -43,7 +43,14 @@ - true + + true/PM + + + PerMonitorV2, PerMonitor From 5f152906f84d8448a2d6b518403a51db314b2e2b Mon Sep 17 00:00:00 2001 From: Wouter Date: Fri, 24 Apr 2020 23:30:27 +0200 Subject: [PATCH 2/4] Define WM_DPICHANGED if the compiler doesn't support it yet. --- openvpn.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openvpn.c b/openvpn.c index d01a99f..533befd 100644 --- a/openvpn.c +++ b/openvpn.c @@ -35,6 +35,10 @@ #include #include +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#endif + #include "tray.h" #include "main.h" #include "openvpn.h" From c7a47aa3e41354b190650bec2c158acb78f48690 Mon Sep 17 00:00:00 2001 From: Wouter Date: Wed, 27 May 2020 00:40:01 +0200 Subject: [PATCH 3/4] Replace assertions --- options.c | 100 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/options.c b/options.c index 02cb19a..651fa1d 100644 --- a/options.c +++ b/options.c @@ -37,9 +37,6 @@ #include #include "options.h" - -#include - #include "main.h" #include "openvpn-gui-res.h" #include "localization.h" @@ -466,54 +463,67 @@ BrowseFolder (const WCHAR* initial_path, WCHAR* selected_path) // Create dialog initResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - assert(SUCCEEDED(initResult)); - + if (FAILED(initResult)) + { + return false; + } + result = CoCreateInstance(&CLSID_FileOpenDialog, NULL, CLSCTX_ALL, &IID_IFileOpenDialog, &pfd); - assert(SUCCEEDED(result)); - - // Select folders, not files + if (SUCCEEDED(result)) { - DWORD dwOptions; - result = pfd->lpVtbl->GetOptions(pfd, &dwOptions); - assert(SUCCEEDED(result)); - dwOptions |= FOS_PICKFOLDERS; - result = pfd->lpVtbl->SetOptions(pfd, dwOptions); - assert(SUCCEEDED(result)); - } - - // Set initial path - { - IShellItem* psi; - result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, &psi); - if (SUCCEEDED(result)) + // Select folders, not files { - pfd->lpVtbl->SetDefaultFolder(pfd, psi); - psi->lpVtbl->Release(psi); + DWORD dwOptions; + result = pfd->lpVtbl->GetOptions(pfd, &dwOptions); + if(SUCCEEDED(result)) + { + dwOptions |= FOS_PICKFOLDERS; + result = pfd->lpVtbl->SetOptions(pfd, dwOptions); + } } + + // Set initial path + { + IShellItem* psi; + result = SHCreateItemFromParsingName(initial_path, NULL, &IID_IShellItem, &psi); + if (SUCCEEDED(result)) + { + pfd->lpVtbl->SetDefaultFolder(pfd, psi); + psi->lpVtbl->Release(psi); + } + } + + // Show dialog and copy the selected file path if the user didn't cancel + dialogResult = pfd->lpVtbl->Show(pfd, NULL); + if (SUCCEEDED(dialogResult)) + { + IShellItem* psi; + LPOLESTR path = NULL; + + result = pfd->lpVtbl->GetResult(pfd, &psi); + if(SUCCEEDED(result)) + { + result = psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &path); + } + + if (SUCCEEDED(result)) + { + wcsncpy_s(selected_path, MAX_PATH, path, MAX_PATH); + selected_path[MAX_PATH - 1] = 0; + + CoTaskMemFree(path); + + psi->lpVtbl->Release(psi); + }else + { + dialogResult = E_FAIL; + } + } + + // Cleanup + pfd->lpVtbl->Release(pfd); } - // Show dialog and copy the selected file path if the user didn't cancel - dialogResult = pfd->lpVtbl->Show(pfd, NULL); - if (SUCCEEDED(dialogResult)) - { - IShellItem* psi; - LPOLESTR path = NULL; - - assert(SUCCEEDED(pfd->lpVtbl->GetResult(pfd, &psi))); - - assert(SUCCEEDED(psi->lpVtbl->GetDisplayName(psi, SIGDN_FILESYSPATH, &path))); - - wcsncpy_s(selected_path, MAX_PATH, path, MAX_PATH); - selected_path[MAX_PATH - 1] = 0; - - CoTaskMemFree(path); - - psi->lpVtbl->Release(psi); - } - - // Cleanup - pfd->lpVtbl->Release(pfd); - if (initResult != RPC_E_CHANGED_MODE && SUCCEEDED(initResult)) { CoUninitialize(); //All successful CoInitializeEx calls must be balanced by a corresponding CoUninitialize From 6b02bb9cbecd9cef9642966aafc12a5c7ccf436a Mon Sep 17 00:00:00 2001 From: Wouter Date: Mon, 7 Sep 2020 19:47:37 +0200 Subject: [PATCH 4/4] Fix mingw compilation issue --- options.c | 1 + 1 file changed, 1 insertion(+) diff --git a/options.c b/options.c index 651fa1d..f45ca75 100644 --- a/options.c +++ b/options.c @@ -27,6 +27,7 @@ #endif #include +#include #include #include #include