diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/gui/win/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/platform/gui/win/Clipboard.cpp | 8 | ||||
| -rw-r--r-- | src/platform/gui/win/GodWindow.cpp | 61 | ||||
| -rw-r--r-- | src/platform/gui/win/TimerManager.cpp | 95 | ||||
| -rw-r--r-- | src/platform/gui/win/TimerManager.h | 53 | ||||
| -rw-r--r-- | src/platform/gui/win/UiApplication.cpp | 47 | ||||
| -rw-r--r-- | src/platform/gui/win/Window.cpp | 3 |
7 files changed, 32 insertions, 237 deletions
diff --git a/src/platform/gui/win/CMakeLists.txt b/src/platform/gui/win/CMakeLists.txt index d5ac6851..8c0dd2a4 100644 --- a/src/platform/gui/win/CMakeLists.txt +++ b/src/platform/gui/win/CMakeLists.txt @@ -2,10 +2,8 @@ add_library(CruPlatformGuiWin Base.cpp Clipboard.cpp Cursor.cpp - GodWindow.cpp InputMethod.cpp Keyboard.cpp - TimerManager.cpp UiApplication.cpp Window.cpp WindowClass.cpp diff --git a/src/platform/gui/win/Clipboard.cpp b/src/platform/gui/win/Clipboard.cpp index f5d2513a..7062f160 100644 --- a/src/platform/gui/win/Clipboard.cpp +++ b/src/platform/gui/win/Clipboard.cpp @@ -1,7 +1,6 @@ #include "cru/platform/gui/win/Clipboard.h" #include "cru/base/StringUtil.h" #include "cru/base/log/Logger.h" -#include "cru/platform/gui/win/GodWindow.h" #include "cru/platform/gui/win/UiApplication.h" namespace cru::platform::gui::win { @@ -11,9 +10,7 @@ WinClipboard::WinClipboard(WinUiApplication* application) WinClipboard::~WinClipboard() {} std::string WinClipboard::GetText() { - auto god_window = application_->GetGodWindow(); - - if (!::OpenClipboard(god_window->GetHandle())) { + if (!::OpenClipboard(nullptr)) { CRU_LOG_TAG_WARN("Failed to open clipboard."); return {}; } @@ -47,9 +44,8 @@ std::string WinClipboard::GetText() { void WinClipboard::SetText(std::string utf8_text) { auto text = string::ToUtf16(utf8_text); - auto god_window = application_->GetGodWindow(); - if (!::OpenClipboard(god_window->GetHandle())) { + if (!::OpenClipboard(nullptr)) { CRU_LOG_TAG_WARN("Failed to open clipboard."); return; } diff --git a/src/platform/gui/win/GodWindow.cpp b/src/platform/gui/win/GodWindow.cpp deleted file mode 100644 index 7cdf229c..00000000 --- a/src/platform/gui/win/GodWindow.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "cru/platform/gui/win/GodWindow.h" -#include "cru/base/log/Logger.h" -#include "cru/platform/gui/win/UiApplication.h" -#include "cru/platform/gui/win/WindowClass.h" - -namespace cru::platform::gui::win { -constexpr auto god_window_class_name = L"GodWindowClass"; - -LRESULT CALLBACK GodWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, - LPARAM lParam) { - const auto app = WinUiApplication::GetInstance(); - - if (app) { - LRESULT result; - auto god_window = app->GetGodWindow(); - if (god_window != nullptr) { - const auto handled = god_window->HandleGodWindowMessage( - hWnd, uMsg, wParam, lParam, &result); - if (handled) return result; - } - } - return DefWindowProcW(hWnd, uMsg, wParam, lParam); -} - -GodWindow::GodWindow(WinUiApplication* application) { - application_ = application; - - const auto h_instance = application->GetInstanceHandle(); - - god_window_class_ = std::make_unique<WindowClass>(god_window_class_name, - GodWndProc, h_instance); - - hwnd_ = CreateWindowEx(0, god_window_class_name, L"", 0, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - HWND_MESSAGE, nullptr, h_instance, nullptr); - - if (hwnd_ == nullptr) - throw Win32Error(::GetLastError(), "Failed to create god window."); -} - -GodWindow::~GodWindow() { - if (!::DestroyWindow(hwnd_)) { - // Although this could be "safely" ignore. - CRU_LOG_TAG_WARN("Failed to destroy god window."); - } -} - -bool GodWindow::HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, - LPARAM l_param, LRESULT* result) { - WindowNativeMessageEventArgs args( - WindowNativeMessage{hwnd, msg, w_param, l_param}); - message_event_.Raise(args); - - if (args.IsHandled()) { - *result = args.GetResult(); - return true; - } - - return false; -} -} // namespace cru::platform::gui::win diff --git a/src/platform/gui/win/TimerManager.cpp b/src/platform/gui/win/TimerManager.cpp deleted file mode 100644 index 794e714c..00000000 --- a/src/platform/gui/win/TimerManager.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include "TimerManager.h" - -#include <functional> - -namespace cru::platform::gui::win { -constexpr int kSetImmediateWindowMessageId = WM_USER + 2000; - -TimerManager::TimerManager(GodWindow* god_window) { - god_window_ = god_window; - event_guard_ += god_window->MessageEvent()->AddHandler(std::bind( - &TimerManager::HandleGodWindowMessage, this, std::placeholders::_1)); -} - -long long TimerManager::SetTimer(TimerType type, int period, - std::function<void()> action) { - auto id = next_id_++; - TimerInfo timer_info{id, type, type == TimerType::Immediate ? 0 : period, - std::move(action)}; - if (type == TimerType::Immediate) { - if (!::PostMessageW(god_window_->GetHandle(), kSetImmediateWindowMessageId, - static_cast<UINT_PTR>(id), 0)) { - throw Win32Error( - ::GetLastError(), - "Failed to post window message to god window for set immediate."); - } - } else { - CreateNativeTimer(&timer_info); - } - - info_map_.emplace(id, std::move(timer_info)); - return id; -} - -void TimerManager::CancelTimer(long long id) { - if (id <= 0) return; - auto find_result = this->info_map_.find(id); - if (find_result != info_map_.cend()) { - auto& info = find_result->second; - KillNativeTimer(&info); - this->info_map_.erase(find_result); - } -} - -void TimerManager::CreateNativeTimer(TimerInfo* info) { - info->native_timer_id = static_cast<UINT_PTR>(info->id); - ::SetTimer(god_window_->GetHandle(), info->native_timer_id, info->period, - nullptr); -} - -void TimerManager::KillNativeTimer(TimerInfo* info) { - if (info->native_timer_id == 0) return; - ::KillTimer(god_window_->GetHandle(), info->native_timer_id); - info->native_timer_id = 0; -} - -void TimerManager::HandleGodWindowMessage(WindowNativeMessageEventArgs& args) { - const auto& message = args.GetWindowMessage(); - - switch (message.msg) { - case kSetImmediateWindowMessageId: { - auto find_result = - this->info_map_.find(static_cast<long long>(message.w_param)); - if (find_result != info_map_.cend()) { - auto& info = find_result->second; - info.action(); - info_map_.erase(find_result); - } - args.SetResult(0); - args.SetHandled(true); - return; - } - case WM_TIMER: { - auto find_result = - this->info_map_.find(static_cast<long long>(message.w_param)); - if (find_result != info_map_.cend()) { - auto& info = find_result->second; - if (info.type == TimerType::Interval) { - info.action(); - args.SetResult(0); - args.SetHandled(true); - } else if (info.type == TimerType::Timeout) { - info.action(); - KillNativeTimer(&info); - info_map_.erase(find_result); - args.SetResult(0); - args.SetHandled(true); - } - } - return; - } - default: - return; - } -} -} // namespace cru::platform::gui::win diff --git a/src/platform/gui/win/TimerManager.h b/src/platform/gui/win/TimerManager.h deleted file mode 100644 index b35ef1fc..00000000 --- a/src/platform/gui/win/TimerManager.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include "cru/base/Base.h" -#include "cru/base/Event.h" -#include "cru/platform/gui/win/GodWindow.h" -#include "cru/platform/gui/win/WindowNativeMessageEventArgs.h" - -#include <functional> -#include <unordered_map> - -namespace cru::platform::gui::win { -enum class TimerType { Immediate, Timeout, Interval }; - -struct TimerInfo { - TimerInfo(long long id, TimerType type, int period, - std::function<void()> action, UINT_PTR native_timer_id = 0) - : id(id), - type(type), - period(period), - action(std::move(action)), - native_timer_id(native_timer_id) {} - - long long id; - TimerType type; - int period; // in milliseconds - std::function<void()> action; - UINT_PTR native_timer_id; -}; - -class TimerManager : public Object { - public: - TimerManager(GodWindow* god_window); - ~TimerManager() override = default; - - // Period is in milliseconds. When type is immediate, it is not checked and - // used. - long long SetTimer(TimerType type, int period, std::function<void()> action); - void CancelTimer(long long id); - - private: - void HandleGodWindowMessage(WindowNativeMessageEventArgs& args); - - void CreateNativeTimer(TimerInfo* info); - void KillNativeTimer(TimerInfo* info); - - private: - GodWindow* god_window_; - - EventHandlerRevokerListGuard event_guard_; - - long long next_id_ = 1; - std::unordered_map<long long, TimerInfo> info_map_; -}; -} // namespace cru::platform::gui::win diff --git a/src/platform/gui/win/UiApplication.cpp b/src/platform/gui/win/UiApplication.cpp index 0de79675..12a74bc6 100644 --- a/src/platform/gui/win/UiApplication.cpp +++ b/src/platform/gui/win/UiApplication.cpp @@ -1,14 +1,14 @@ #include "cru/platform/gui/win/UiApplication.h" -#include "TimerManager.h" #include "WindowManager.h" #include "cru/platform/graphics/direct2d/Factory.h" #include "cru/platform/gui/win/Base.h" #include "cru/platform/gui/win/Clipboard.h" #include "cru/platform/gui/win/Cursor.h" -#include "cru/platform/gui/win/GodWindow.h" #include "cru/platform/gui/win/Window.h" +#include <chrono> + namespace cru::platform::gui { std::unique_ptr<IUiApplication> CreateUiApplication() { return std::make_unique<win::WinUiApplication>(); @@ -30,8 +30,6 @@ WinUiApplication::WinUiApplication() { graph_factory_ = std::make_unique< cru::platform::graphics::direct2d::DirectGraphicsFactory>(); - god_window_ = std::make_unique<GodWindow>(this); - timer_manager_ = std::make_unique<TimerManager>(god_window_.get()); window_manager_ = std::make_unique<WindowManager>(this); cursor_manager_ = std::make_unique<WinCursorManager>(); clipboard_ = std::make_unique<WinClipboard>(this); @@ -41,9 +39,28 @@ WinUiApplication::~WinUiApplication() { instance = nullptr; } int WinUiApplication::Run() { MSG msg; - while (GetMessageW(&msg, nullptr, 0, 0)) { - TranslateMessage(&msg); - DispatchMessageW(&msg); + bool exit = false; + + while (!exit) { + if (auto result = timers_.Update(std::chrono::steady_clock::now())) { + result->data(); + continue; + } + + auto timeout = timers_.NextTimeout(std::chrono::steady_clock::now()); + + ::MsgWaitForMultipleObjects( + 0, nullptr, FALSE, timeout ? timeout->count() : INFINITE, QS_ALLINPUT); + + while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessageW(&msg); + + if (msg.message == WM_QUIT) { + exit = true; + break; + } + } } for (const auto& handler : quit_handlers_) handler(); @@ -60,27 +77,21 @@ void WinUiApplication::AddOnQuitHandler(std::function<void()> handler) { } long long WinUiApplication::SetImmediate(std::function<void()> action) { - return this->timer_manager_->SetTimer(TimerType::Immediate, 0, - std::move(action)); + return timers_.Add(std::move(action), std::chrono::milliseconds::zero(), + false); } long long WinUiApplication::SetTimeout(std::chrono::milliseconds milliseconds, std::function<void()> action) { - return this->timer_manager_->SetTimer(TimerType::Timeout, - static_cast<int>(milliseconds.count()), - std::move(action)); + return timers_.Add(std::move(action), milliseconds, false); } long long WinUiApplication::SetInterval(std::chrono::milliseconds milliseconds, std::function<void()> action) { - return this->timer_manager_->SetTimer(TimerType::Interval, - static_cast<int>(milliseconds.count()), - std::move(action)); + return timers_.Add(std::move(action), milliseconds, true); } -void WinUiApplication::CancelTimer(long long id) { - timer_manager_->CancelTimer(id); -} +void WinUiApplication::CancelTimer(long long id) { timers_.Remove(id); } std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { const auto&& windows = window_manager_->GetAllWindows(); diff --git a/src/platform/gui/win/Window.cpp b/src/platform/gui/win/Window.cpp index 2acd4c75..af308768 100644 --- a/src/platform/gui/win/Window.cpp +++ b/src/platform/gui/win/Window.cpp @@ -68,7 +68,7 @@ Rect CalcClientRectFromWindow(const Rect& rect, WindowStyleFlag style_flag, WinNativeWindow::WinNativeWindow(WinUiApplication* application) : application_(application) { - Expects(application); // application can't be null. + input_method_context_ = std::make_unique<WinInputMethodContext>(this); } WinNativeWindow::~WinNativeWindow() { Close(); } @@ -490,7 +490,6 @@ void WinNativeWindow::RecreateWindow() { application_->GetDirectFactory(), hwnd_); window_render_target_->SetDpi(dpi_, dpi_); - input_method_context_ = std::make_unique<WinInputMethodContext>(this); input_method_context_->DisableIME(); } |
