aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/platform/gui/win/CMakeLists.txt2
-rw-r--r--src/platform/gui/win/Clipboard.cpp8
-rw-r--r--src/platform/gui/win/GodWindow.cpp61
-rw-r--r--src/platform/gui/win/TimerManager.cpp95
-rw-r--r--src/platform/gui/win/TimerManager.h53
-rw-r--r--src/platform/gui/win/UiApplication.cpp47
-rw-r--r--src/platform/gui/win/Window.cpp3
-rw-r--r--src/ui/DeleteLater.cpp7
-rw-r--r--src/ui/controls/Control.cpp5
-rw-r--r--src/ui/controls/TextHostControlService.cpp6
10 files changed, 42 insertions, 245 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();
}
diff --git a/src/ui/DeleteLater.cpp b/src/ui/DeleteLater.cpp
index 499b9b34..27ec2155 100644
--- a/src/ui/DeleteLater.cpp
+++ b/src/ui/DeleteLater.cpp
@@ -1,16 +1,21 @@
#include "cru/ui/DeleteLater.h"
#include "Helper.h"
+#include "cru/base/log/Logger.h"
#include "cru/platform/gui/UiApplication.h"
namespace cru::ui {
DeleteLaterImpl::DeleteLaterImpl() : delete_later_scheduled_(false) {}
-DeleteLaterImpl::~DeleteLaterImpl() {}
+DeleteLaterImpl::~DeleteLaterImpl() {
+ CRU_LOG_TAG_DEBUG("Delete later object being deleted {}.",
+ static_cast<void*>(this));
+}
void DeleteLaterImpl::DeleteLater() {
if (!delete_later_scheduled_) {
+ CRU_LOG_TAG_DEBUG("Schedule delete later {}.", static_cast<void*>(this));
GetUiApplication()->SetImmediate([this] { delete this; });
delete_later_scheduled_ = true;
}
diff --git a/src/ui/controls/Control.cpp b/src/ui/controls/Control.cpp
index 3218f185..14397fa7 100644
--- a/src/ui/controls/Control.cpp
+++ b/src/ui/controls/Control.cpp
@@ -1,10 +1,8 @@
#include "cru/ui/controls/Control.h"
-#include "cru/base/log/Logger.h"
#include "cru/platform/gui/Cursor.h"
#include "cru/platform/gui/UiApplication.h"
#include "cru/ui/host/WindowHost.h"
-#include "cru/ui/render/RenderObject.h"
#include "cru/ui/style/StyleRuleSet.h"
namespace cru::ui::controls {
@@ -30,8 +28,7 @@ Control::Control() {
Control::~Control() {
if (host::WindowHost::IsInEventHandling()) {
- CRU_LOG_TAG_ERROR(
- "Control destroyed during event handling. Please use DeleteLater.");
+ std::terminate();
}
in_destruction_ = true;
diff --git a/src/ui/controls/TextHostControlService.cpp b/src/ui/controls/TextHostControlService.cpp
index 235e6e6a..f581d3c9 100644
--- a/src/ui/controls/TextHostControlService.cpp
+++ b/src/ui/controls/TextHostControlService.cpp
@@ -12,7 +12,6 @@
#include "cru/platform/gui/Window.h"
#include "cru/ui/Base.h"
#include "cru/ui/DebugFlags.h"
-#include "cru/ui/DeleteLater.h"
#include "cru/ui/components/Menu.h"
#include "cru/ui/helper/ShortcutHub.h"
#include "cru/ui/host/WindowHost.h"
@@ -149,7 +148,8 @@ std::vector<TextControlMovePattern> TextControlMovePattern::kDefaultPatterns = {
TextHostControlService::TextHostControlService(Control* control)
: control_(control),
- text_host_control_(dynamic_cast<ITextHostControl*>(control)) {
+ text_host_control_(dynamic_cast<ITextHostControl*>(control)),
+ context_menu_(new components::PopupMenu()) {
SetUpShortcuts();
SetupOneHandler(&Control::MouseMoveEvent,
@@ -699,7 +699,7 @@ void TextHostControlService::SetUpShortcuts() {
void TextHostControlService::OpenContextMenu(const Point& position,
ContextMenuItem items) {
- context_menu_ = MakeDeleteLater<components::PopupMenu>();
+ CRU_LOG_TAG_DEBUG("Open context menu.");
auto menu = context_menu_->GetMenu();
if (items & ContextMenuItem::kSelectAll) {
menu->AddTextItem("Select All", [this] { this->SelectAll(); });