242 lines
6.0 KiB
C++
242 lines
6.0 KiB
C++
#include "pch.h"
|
|
|
|
#include "platform_windows/windows_runtime_shell.h"
|
|
|
|
#include "app.h"
|
|
#include "log.h"
|
|
#include "platform_windows/windows_bootstrap_helpers.h"
|
|
#include "platform_windows/windows_lifecycle_shell.h"
|
|
#include "platform_windows/windows_main_window_session.h"
|
|
#include "platform_windows/windows_platform_services.h"
|
|
#include "platform_windows/windows_stylus_input.h"
|
|
#include "platform_windows/windows_window_shell.h"
|
|
#include "wacom.h"
|
|
#include "../resource.h"
|
|
|
|
namespace pp::platform::windows {
|
|
|
|
namespace {
|
|
|
|
struct RetainedWindowsRuntimeState final {
|
|
std::unique_ptr<App> owned_app;
|
|
WacomTablet tablet;
|
|
};
|
|
|
|
[[nodiscard]] RetainedWindowsRuntimeState& retained_runtime_state()
|
|
{
|
|
static RetainedWindowsRuntimeState state;
|
|
return state;
|
|
}
|
|
|
|
void register_touch_window(HWND hWnd)
|
|
{
|
|
// link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow
|
|
if (RegisterTouchWindow(hWnd, 0) == 0)
|
|
{
|
|
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str());
|
|
}
|
|
}
|
|
|
|
void initialize_runtime_threads()
|
|
{
|
|
auto* app = bound_app();
|
|
mark_lifecycle_running();
|
|
app->runtime().render_thread_start(*app);
|
|
app->runtime().ui_thread_start(*app);
|
|
}
|
|
|
|
void install_debug_gl_callbacks()
|
|
{
|
|
#ifdef _DEBUG
|
|
glad_set_pre_callback(_pre_call_callback);
|
|
glad_set_post_callback(_post_call_callback);
|
|
#endif
|
|
}
|
|
|
|
void initialize_wintab(HWND hWnd, bool sandboxed)
|
|
{
|
|
auto* tablet = bound_wacom_tablet();
|
|
if (!sandboxed)
|
|
{
|
|
LOG("init WinTab");
|
|
tablet->init(hWnd);
|
|
}
|
|
else
|
|
{
|
|
LOG("SKIP init WinTab");
|
|
}
|
|
}
|
|
|
|
void set_main_window_icon(HWND hWnd)
|
|
{
|
|
LOG("change icon");
|
|
SendMessage(
|
|
hWnd,
|
|
WM_SETICON,
|
|
ICON_SMALL,
|
|
(LPARAM)LoadIcon(GetModuleHandle(0), MAKEINTRESOURCE(IDI_ICON1)));
|
|
}
|
|
|
|
void restore_window_placement(HWND hWnd, int show_command)
|
|
{
|
|
WINDOWPLACEMENT wp;
|
|
GetWindowPlacement(hWnd, &wp);
|
|
wp.showCmd = show_command;
|
|
SetWindowPlacement(hWnd, &wp);
|
|
}
|
|
|
|
void run_main_message_loop()
|
|
{
|
|
MSG msg;
|
|
auto* app = bound_app();
|
|
LOG("start main loop");
|
|
while (lifecycle_is_running())
|
|
{
|
|
auto present = app->animate || app->redraw ?
|
|
PeekMessage(&msg, 0, 0, 0, PM_REMOVE) : GetMessage(&msg, 0, 0, 0);
|
|
|
|
if (msg.message == WM_QUIT)
|
|
mark_lifecycle_stopped();
|
|
|
|
if (present)
|
|
{
|
|
DispatchMessage(&msg);
|
|
TranslateMessage(&msg);
|
|
}
|
|
|
|
drain_main_thread_tasks();
|
|
}
|
|
}
|
|
|
|
void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTANCE hInst)
|
|
{
|
|
retained_runtime_state().tablet.terminate();
|
|
UnregisterClass(startup.window_class.lpszClassName, hInst);
|
|
LogRemote::I.stop();
|
|
}
|
|
|
|
}
|
|
|
|
void bind_app(App* app) noexcept
|
|
{
|
|
App::I = app;
|
|
}
|
|
|
|
App* bound_app() noexcept
|
|
{
|
|
return App::I;
|
|
}
|
|
|
|
void release_bound_app() noexcept
|
|
{
|
|
bind_app(nullptr);
|
|
retained_runtime_state().owned_app.reset();
|
|
}
|
|
|
|
WacomTablet* bound_wacom_tablet() noexcept
|
|
{
|
|
return &retained_runtime_state().tablet;
|
|
}
|
|
|
|
int run_main_application(int argc, char** argv)
|
|
{
|
|
const auto instance = GetModuleHandle(NULL);
|
|
|
|
auto& runtime_state = retained_runtime_state();
|
|
runtime_state.owned_app = std::make_unique<App>();
|
|
auto* app = runtime_state.owned_app.get();
|
|
bind_app(app);
|
|
app->set_platform_services(&pp::platform::windows::platform_services());
|
|
app->initLog();
|
|
|
|
pp::platform::windows::init_shcore_API();
|
|
pp::platform::windows::initialize_stylus_input();
|
|
|
|
if (pp::platform::windows::SetProcessDpiAwareness_fn)
|
|
pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
|
|
|
|
pp::platform::windows::ensure_runtime_data_directory();
|
|
|
|
pp::platform::windows::SplashScreen splash(instance);
|
|
|
|
pp::platform::windows::initialize_retained_input_state();
|
|
|
|
pp::platform::windows::setup_exception_handler(*app);
|
|
|
|
pp::platform::windows::read_WMI_info();
|
|
|
|
app->create();
|
|
|
|
auto startup = pp::platform::windows::initialize_main_window_startup_state(*app);
|
|
auto context = pp::platform::windows::OpenGlWindowContext {};
|
|
switch (pp::platform::windows::initialize_main_window_and_gl(
|
|
startup,
|
|
retained_main_window_handle_ref(),
|
|
instance,
|
|
retained_main_window_title_buffer(),
|
|
context))
|
|
{
|
|
case pp::platform::windows::MainStartupResult::Ok:
|
|
break;
|
|
case pp::platform::windows::MainStartupResult::GladLoadFailure:
|
|
release_bound_app();
|
|
return 0;
|
|
case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
|
|
release_bound_app();
|
|
return -1;
|
|
}
|
|
|
|
//wglSwapIntervalEXT(1);
|
|
|
|
bool start_in_vr = false;
|
|
if (argc > 1)
|
|
{
|
|
switch (const_hash(argv[1]))
|
|
{
|
|
case const_hash("convert"):
|
|
app->initShaders();
|
|
app->cmd_convert(argv[2], argv[3]);
|
|
release_bound_app();
|
|
return 0;
|
|
case const_hash("-vrmode"):
|
|
start_in_vr = true;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
pp::platform::windows::run_main_window_runtime(startup, start_in_vr, instance, splash);
|
|
release_bound_app();
|
|
return 0;
|
|
}
|
|
|
|
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, HINSTANCE instance, SplashScreen& splash)
|
|
{
|
|
auto* app = bound_app();
|
|
register_touch_window(retained_main_window_handle_ref());
|
|
|
|
wglMakeCurrent(NULL, NULL);
|
|
|
|
initialize_runtime_threads();
|
|
install_debug_gl_callbacks();
|
|
initialize_wintab(retained_main_window_handle_ref(), retained_main_window_sandboxed());
|
|
set_main_window_icon(retained_main_window_handle_ref());
|
|
|
|
app->ui_sync();
|
|
restore_window_placement(retained_main_window_handle_ref(), startup.show_command);
|
|
|
|
if (start_in_vr)
|
|
app->vr_start();
|
|
|
|
LOG("show main window");
|
|
SetForegroundWindow(retained_main_window_handle_ref());
|
|
|
|
splash.dismiss();
|
|
|
|
run_main_message_loop();
|
|
shutdown_main_window_runtime(startup, instance);
|
|
}
|
|
|
|
}
|