From ed0ceeb95bd1c763479387685a4fd6110315ad3b Mon Sep 17 00:00:00 2001 From: Selva Nair Date: Sat, 6 Aug 2022 18:05:43 -0400 Subject: [PATCH] Add a progress dialog during Connect() - The dialog supports retry and cancel and shows a progress marquee Signed-off-by: Selva Nair c; + IQueryContinueWithStatus *qc = oc->qc; + + assert(qc); + + HRESULT hr = S_FALSE; + WCHAR status[256] = L""; + + if (msg == TDN_BUTTON_CLICKED && wParam == IDCANCEL) + { + dmsg(L"wParam=IDCANCEL -- returning S_OK"); + hr = S_OK; /* this will cause the progress dialog to close */ + } + else if (ISCONNECTED(c) || ISDISCONNECTED(c) || (qc->lpVtbl->QueryContinue(qc) != S_OK)) + { + /* this will trigger IDCANCEL */ + PostMessageW(hwnd, WM_CLOSE, 0, 0); + dmsg(L"profile = %ls, closing progress dialog", oc->display_name); + hr = S_OK; + } + else if (ISONHOLD(c)) /* Try to connect again */ + { + ConnectHelper(c); + } + else if (!ISCONNECTED(c) && msg == TDN_BUTTON_CLICKED && wParam == status_menu_id) + { + dmsg(L"wParam = status_menu_id -- showing status window"); + ShowStatusWindow(c, TRUE); + } + else if (!ISCONNECTED(c) && msg == TDN_BUTTON_CLICKED && wParam == IDRETRY) + { + dmsg(L"wParam = IDRETRY -- closing progress dialog for restart"); + hr = S_OK; + } + + if (msg == TDN_CREATED) + { + dmsg(L"starting progress bar marquee"); + PostMessageW(hwnd, TDM_SET_PROGRESS_BAR_MARQUEE, 1, 0); + } + + if (msg == TDN_TIMER) + { + GetConnectionStatusText(c, status, _countof(status)); + NotifyEvents(oc, status); + SendMessageW(hwnd, TDM_UPDATE_ELEMENT_TEXT, TDE_CONTENT, (LPARAM) status); + dmsg(L"Connection status <%ls>", status); + } + + return hr; +} + static HRESULT WINAPI Connect(ICCPC *this, IQueryContinueWithStatus *qc) { @@ -538,33 +598,41 @@ Connect(ICCPC *this, IQueryContinueWithStatus *qc) oc->qc = qc; NotifyEvents(oc, L""); - oc->connect_cancelled = FALSE; - SetActiveProfile(oc->c); +again: + oc->connect_cancelled = FALSE; + SetActiveProfile(oc->c); /* This enables UI dialogs to be shown for c */ ConnectHelper(oc->c); Sleep(100); - while (!ISCONNECTED(oc->c) && !ISDISCONNECTED(oc->c)) + /* if not immediately connected, show a progress dialog with + * service state changes and retry/cancel options. Progress dialog + * returns on error, cancel or when connected. + */ + if (!ISCONNECTED(oc->c) && !ISDISCONNECTED(oc->c)) { - ShowStatusWindow(oc->c, TRUE); - GetConnectionStatusText(oc->c, status, _countof(status)); - NotifyEvents(oc, status); - if (qc->lpVtbl->QueryContinue(qc) != S_OK) + dmsg(L"Runninng progress dialog"); + int res = RunProgressDialog(oc->c, ProgressCallback, (LONG_PTR) oc); + dmsg(L"Out of progress dialog with res = %d", res); + + if (res == IDRETRY && !ISCONNECTED(oc->c)) + { + wcsncpy_s(status, _countof(status), L"Current State: Retrying", _TRUNCATE); + NotifyEvents(oc, status); + + DisconnectHelper(oc->c); + goto again; + } + else if (res == IDCANCEL && !ISCONNECTED(oc->c) && !ISDISCONNECTED(oc->c)) { - /* user wants to cancel */ wcsncpy_s(status, _countof(status), L"Current State: Cancelling", _TRUNCATE); NotifyEvents(oc, status); - oc->connect_cancelled = TRUE; + DisconnectHelper(oc->c); - break; + oc->connect_cancelled = TRUE; } - else if (ISONHOLD(oc->c)) - { - ConnectHelper(oc->c); - } - Sleep(100); } GetConnectionStatusText(oc->c, status, _countof(status)); diff --git a/plap/ui_glue.c b/plap/ui_glue.c index a5b3004..244875b 100644 --- a/plap/ui_glue.c +++ b/plap/ui_glue.c @@ -39,6 +39,7 @@ #include "openvpn-gui-res.h" #include "localization.h" #include "misc.h" +#include "tray.h" /* Global options structure */ options_t o; @@ -47,6 +48,7 @@ int state_connected = connected, state_disconnected = disconnected, state_onhold = onhold; static connection_t *active_profile; +DWORD status_menu_id = IDM_STATUSMENU; /* Override management handlers that generate user dialogs * and pass them on only for currently active profile. @@ -477,3 +479,41 @@ SetActiveProfile(connection_t *c) { active_profile = c; } + +int +RunProgressDialog(connection_t *c, PFTASKDIALOGCALLBACK cb_fn, LONG_PTR cb_data) +{ + dmsg(L"Entry with profile = <%ls>", c->config_name); + + const TASKDIALOG_FLAGS flags = TDF_SHOW_MARQUEE_PROGRESS_BAR|TDF_CALLBACK_TIMER|TDF_USE_HICON_MAIN; + wchar_t main_text[256]; + wchar_t details_btn_text[256]; + + _sntprintf_0(main_text, L"%ls %ls", LoadLocalizedString(IDS_MENU_CONNECT), c->config_name); + LoadLocalizedStringBuf(details_btn_text, _countof(main_text), IDS_MENU_STATUS); + + const TASKDIALOG_BUTTON extra_buttons[] = { + {status_menu_id, details_btn_text}, + }; + + const TASKDIALOGCONFIG taskcfg = { + .cbSize = sizeof(taskcfg), + .hwndParent = o.hWnd, + .hInstance = o.hInstance, + .dwFlags = flags, + .hMainIcon = LoadLocalizedIcon(ID_ICO_APP), + .cButtons = _countof(extra_buttons), + .pButtons = extra_buttons, + .dwCommonButtons = TDCBF_CANCEL_BUTTON|TDCBF_RETRY_BUTTON, + .pszWindowTitle = L""PACKAGE_NAME" PLAP", + .pszMainInstruction = main_text, + .pszContent = L"Starting", /* replaced on create */ + .pfCallback = cb_fn, + .lpCallbackData = cb_data, + }; + + int button_clicked = 0; + dmsg(L"calling taskdialogindirect"); + TaskDialogIndirect(&taskcfg, &button_clicked, NULL, NULL); + return button_clicked; +} diff --git a/plap/ui_glue.h b/plap/ui_glue.h index 7dcde7b..291aa12 100644 --- a/plap/ui_glue.h +++ b/plap/ui_glue.h @@ -107,6 +107,15 @@ void DisconnectHelper(connection_t *c); */ void SetActiveProfile(connection_t *c); +/** + * A helper function to run a dialog showing progress of a connection process. + * + * @param c Connection to monitor + * @param cb_fn A callback function that is called back every 200 msec + * @param cb_data Data passed to the callback function + */ +int RunProgressDialog(connection_t *c, PFTASKDIALOGCALLBACK cb_fn, LONG_PTR cb_data); + #ifdef __cplusplus } #endif