summaryrefslogtreecommitdiff
path: root/Source/Core/WinUpdater/WinUI.cpp
diff options
context:
space:
mode:
authorspycrab <spycrab@users.noreply.github.com>2019-04-10 10:46:49 +0200
committerspycrab <spycrab@users.noreply.github.com>2019-04-10 10:46:49 +0200
commitd73987e466b734a837253b50c5d650322ec02662 (patch)
tree41e1681a11a311e59d2e033ac81ac55c7f6af734 /Source/Core/WinUpdater/WinUI.cpp
parent1f6c67a6fb26c873a72c5d33367d9be14f7c028e (diff)
Move Updater to WinUpdater
Diffstat (limited to 'Source/Core/WinUpdater/WinUI.cpp')
-rw-r--r--Source/Core/WinUpdater/WinUI.cpp271
1 files changed, 271 insertions, 0 deletions
diff --git a/Source/Core/WinUpdater/WinUI.cpp b/Source/Core/WinUpdater/WinUI.cpp
new file mode 100644
index 0000000000..7f9a951bef
--- /dev/null
+++ b/Source/Core/WinUpdater/WinUI.cpp
@@ -0,0 +1,271 @@
+// Copyright 2018 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "UpdaterCommon/UI.h"
+
+#include <string>
+#include <thread>
+
+#include <Windows.h>
+#include <CommCtrl.h>
+#include <ShObjIdl.h>
+#include <shellapi.h>
+
+#include "Common/Flag.h"
+#include "Common/StringUtil.h"
+
+namespace
+{
+HWND window_handle = nullptr;
+HWND label_handle = nullptr;
+HWND total_progressbar_handle = nullptr;
+HWND current_progressbar_handle = nullptr;
+ITaskbarList3* taskbar_list = nullptr;
+
+Common::Flag running;
+Common::Flag request_stop;
+
+int GetWindowHeight(HWND hwnd)
+{
+ RECT rect;
+ GetWindowRect(hwnd, &rect);
+
+ return rect.bottom - rect.top;
+}
+}; // namespace
+
+constexpr int PROGRESSBAR_FLAGS = WS_VISIBLE | WS_CHILD | PBS_SMOOTH | PBS_SMOOTHREVERSE;
+constexpr int WINDOW_FLAGS = WS_VISIBLE | WS_CLIPCHILDREN;
+constexpr int PADDING_HEIGHT = 5;
+
+namespace UI
+{
+bool InitWindow()
+{
+ InitCommonControls();
+
+ WNDCLASS wndcl = {};
+ wndcl.lpfnWndProc = DefWindowProcW;
+ wndcl.hbrBackground = GetSysColorBrush(COLOR_MENU);
+ wndcl.lpszClassName = L"UPDATER";
+
+ if (!RegisterClass(&wndcl))
+ return false;
+
+ window_handle =
+ CreateWindow(L"UPDATER", L"Dolphin Updater", WINDOW_FLAGS, CW_USEDEFAULT, CW_USEDEFAULT, 500,
+ 100, nullptr, nullptr, GetModuleHandle(nullptr), 0);
+
+ if (!window_handle)
+ return false;
+
+ if (FAILED(CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&taskbar_list))))
+ {
+ taskbar_list = nullptr;
+ }
+ if (taskbar_list && FAILED(taskbar_list->HrInit()))
+ {
+ taskbar_list->Release();
+ taskbar_list = nullptr;
+ }
+
+ int y = PADDING_HEIGHT;
+
+ label_handle = CreateWindow(L"STATIC", NULL, WS_VISIBLE | WS_CHILD, 5, y, 500, 25, window_handle,
+ nullptr, nullptr, 0);
+
+ if (!label_handle)
+ return false;
+
+ // Get the default system font
+ NONCLIENTMETRICS metrics = {};
+ metrics.cbSize = sizeof(NONCLIENTMETRICS);
+
+ if (!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(metrics), &metrics, 0))
+ return false;
+
+ SendMessage(label_handle, WM_SETFONT,
+ reinterpret_cast<WPARAM>(CreateFontIndirect(&metrics.lfMessageFont)), 0);
+
+ y += GetWindowHeight(label_handle) + PADDING_HEIGHT;
+
+ total_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25,
+ window_handle, nullptr, nullptr, 0);
+
+ y += GetWindowHeight(total_progressbar_handle) + PADDING_HEIGHT;
+
+ if (!total_progressbar_handle)
+ return false;
+
+ current_progressbar_handle = CreateWindow(PROGRESS_CLASS, NULL, PROGRESSBAR_FLAGS, 5, y, 470, 25,
+ window_handle, nullptr, nullptr, 0);
+
+ y += GetWindowHeight(current_progressbar_handle) + PADDING_HEIGHT;
+
+ if (!current_progressbar_handle)
+ return false;
+
+ RECT rect;
+ GetWindowRect(window_handle, &rect);
+
+ // Account for the title bar
+ y += GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYCAPTION) +
+ GetSystemMetrics(SM_CXPADDEDBORDER);
+ // ...and window border
+ y += GetSystemMetrics(SM_CYBORDER);
+
+ // Add some padding for good measure
+ y += PADDING_HEIGHT * 3;
+
+ SetWindowPos(window_handle, HWND_TOPMOST, 0, 0, rect.right - rect.left, y, SWP_NOMOVE);
+
+ return true;
+}
+
+void Destroy()
+{
+ DestroyWindow(window_handle);
+ DestroyWindow(label_handle);
+ DestroyWindow(total_progressbar_handle);
+ DestroyWindow(current_progressbar_handle);
+}
+
+void SetTotalMarquee(bool marquee)
+{
+ SetWindowLong(total_progressbar_handle, GWL_STYLE,
+ PROGRESSBAR_FLAGS | (marquee ? PBS_MARQUEE : 0));
+ SendMessage(total_progressbar_handle, PBM_SETMARQUEE, marquee, 0);
+ if (taskbar_list)
+ {
+ taskbar_list->SetProgressState(window_handle, marquee ? TBPF_INDETERMINATE : TBPF_NORMAL);
+ }
+}
+
+void ResetTotalProgress()
+{
+ SendMessage(total_progressbar_handle, PBM_SETPOS, 0, 0);
+ SetCurrentMarquee(true);
+}
+
+void SetTotalProgress(int current, int total)
+{
+ SendMessage(total_progressbar_handle, PBM_SETRANGE32, 0, total);
+ SendMessage(total_progressbar_handle, PBM_SETPOS, current, 0);
+ if (taskbar_list)
+ {
+ taskbar_list->SetProgressValue(window_handle, current, total);
+ }
+}
+
+void SetCurrentMarquee(bool marquee)
+{
+ SetWindowLong(current_progressbar_handle, GWL_STYLE,
+ PROGRESSBAR_FLAGS | (marquee ? PBS_MARQUEE : 0));
+ SendMessage(current_progressbar_handle, PBM_SETMARQUEE, marquee, 0);
+}
+
+void ResetCurrentProgress()
+{
+ SendMessage(current_progressbar_handle, PBM_SETPOS, 0, 0);
+ SetCurrentMarquee(true);
+}
+
+void Error(const std::string& text)
+{
+ auto wide_text = UTF8ToUTF16(text);
+
+ MessageBox(nullptr,
+ (L"A fatal error occured and the updater cannot continue:\n " + wide_text).c_str(),
+ L"Error", MB_ICONERROR);
+
+ if (taskbar_list)
+ {
+ taskbar_list->SetProgressState(window_handle, TBPF_ERROR);
+ }
+}
+
+void SetCurrentProgress(int current, int total)
+{
+ SendMessage(current_progressbar_handle, PBM_SETRANGE32, 0, total);
+ SendMessage(current_progressbar_handle, PBM_SETPOS, current, 0);
+}
+
+void SetDescription(const std::string& text)
+{
+ SetWindowText(label_handle, UTF8ToUTF16(text).c_str());
+}
+
+void MessageLoop()
+{
+ request_stop.Clear();
+ running.Set();
+
+ if (!InitWindow())
+ {
+ running.Clear();
+ MessageBox(nullptr, L"Window init failed!", L"", MB_ICONERROR);
+ }
+
+ SetTotalMarquee(true);
+ SetCurrentMarquee(true);
+
+ while (!request_stop.IsSet())
+ {
+ MSG msg;
+ while (PeekMessage(&msg, window_handle, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+
+ running.Clear();
+
+ Destroy();
+}
+
+void Init()
+{
+ std::thread thread(MessageLoop);
+ thread.detach();
+}
+
+void Stop()
+{
+ if (!running.IsSet())
+ return;
+
+ request_stop.Set();
+
+ while (running.IsSet())
+ {
+ }
+}
+
+void LaunchApplication(std::string path)
+{
+ // Hack: Launching the updater over the explorer ensures that admin priviliges are dropped. Why?
+ // Ask Microsoft.
+ ShellExecuteW(nullptr, nullptr, L"explorer.exe", UTF8ToUTF16(path).c_str(), nullptr, SW_SHOW);
+}
+
+void Sleep(int sleep)
+{
+ ::Sleep(sleep * 1000);
+}
+
+void WaitForPID(u32 pid)
+{
+ HANDLE parent_handle = OpenProcess(SYNCHRONIZE, FALSE, static_cast<DWORD>(pid));
+ WaitForSingleObject(parent_handle, INFINITE);
+ CloseHandle(parent_handle);
+}
+
+void SetVisible(bool visible)
+{
+ ShowWindow(window_handle, visible ? SW_SHOW : SW_HIDE);
+}
+
+}; // namespace UI