mirror of https://github.com/OpenVPN/openvpn-gui
Add a progress dialog during Connect()
- The dialog supports retry and cancel and shows a progress marquee Signed-off-by: Selva Nair <selva.nair@gmail.compull/529/head
parent
e64b18074f
commit
ed0ceeb95b
|
@ -50,6 +50,8 @@ struct OpenVPNConnection
|
|||
#define ISDISCONNECTED(c) (ConnectionState(c) == state_disconnected)
|
||||
#define ISONHOLD(c) (ConnectionState(c) == state_onhold)
|
||||
|
||||
extern DWORD status_menu_id;
|
||||
|
||||
/* Methods in IConnectableCredentialProviderCredential that we need to define */
|
||||
|
||||
/* IUnknown */
|
||||
|
@ -528,6 +530,64 @@ NotifyEvents(OpenVPNConnection *oc, const wchar_t *status)
|
|||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
ProgressCallback(HWND hwnd, UINT msg, WPARAM wParam, UNUSED LPARAM lParam, LONG_PTR ref_data)
|
||||
{
|
||||
assert(ref_data);
|
||||
|
||||
OpenVPNConnection *oc = (OpenVPNConnection *) ref_data;
|
||||
connection_t *c = oc->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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue