diff options
author | crupest <crupest@outlook.com> | 2021-03-24 19:14:19 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2021-03-24 19:14:19 +0800 |
commit | 7f15a1ff9a2007e119798053083a0a87d042990a (patch) | |
tree | cb35c01a7eaee867376d959b96c9bbd15df939e5 /src/win/native | |
parent | 74956951ee663012df0c3fe4ebe29799cb2f7732 (diff) | |
parent | 7703063a5816b089483e78ccd74bb9902ccfbea8 (diff) | |
download | cru-7f15a1ff9a2007e119798053083a0a87d042990a.tar.gz cru-7f15a1ff9a2007e119798053083a0a87d042990a.tar.bz2 cru-7f15a1ff9a2007e119798053083a0a87d042990a.zip |
Merge branch 'master' of https://github.com/crupest/CruUI
Diffstat (limited to 'src/win/native')
-rw-r--r-- | src/win/native/CMakeLists.txt | 37 | ||||
-rw-r--r-- | src/win/native/Cursor.cpp | 51 | ||||
-rw-r--r-- | src/win/native/DpiUtil.hpp | 46 | ||||
-rw-r--r-- | src/win/native/GodWindow.cpp | 82 | ||||
-rw-r--r-- | src/win/native/GodWindowMessage.hpp | 6 | ||||
-rw-r--r-- | src/win/native/InputMethod.cpp | 312 | ||||
-rw-r--r-- | src/win/native/Keyboard.cpp | 74 | ||||
-rw-r--r-- | src/win/native/Timer.cpp | 28 | ||||
-rw-r--r-- | src/win/native/Timer.hpp | 34 | ||||
-rw-r--r-- | src/win/native/UiApplication.cpp | 124 | ||||
-rw-r--r-- | src/win/native/Window.cpp | 442 | ||||
-rw-r--r-- | src/win/native/WindowClass.cpp | 28 | ||||
-rw-r--r-- | src/win/native/WindowD2DPainter.cpp | 22 | ||||
-rw-r--r-- | src/win/native/WindowD2DPainter.hpp | 21 | ||||
-rw-r--r-- | src/win/native/WindowManager.cpp | 56 | ||||
-rw-r--r-- | src/win/native/WindowManager.hpp | 51 | ||||
-rw-r--r-- | src/win/native/WindowRenderTarget.cpp | 78 |
17 files changed, 0 insertions, 1492 deletions
diff --git a/src/win/native/CMakeLists.txt b/src/win/native/CMakeLists.txt deleted file mode 100644 index f1b167d2..00000000 --- a/src/win/native/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -set(CRU_WIN_NATIVE_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/win/native) - -add_library(cru_win_native STATIC - DpiUtil.hpp - GodWindowMessage.hpp - Timer.hpp - WindowD2DPainter.hpp - WindowManager.hpp - - Cursor.cpp - GodWindow.cpp - InputMethod.cpp - Keyboard.cpp - Timer.cpp - UiApplication.cpp - Window.cpp - WindowClass.cpp - WindowD2DPainter.cpp - WindowManager.cpp - WindowRenderTarget.cpp -) -target_sources(cru_win_native PUBLIC - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Cursor.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Exception.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Base.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/GodWindow.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/InputMethod.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Keyboard.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Resource.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/UiApplication.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/Window.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowClass.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowNativeMessageEventArgs.hpp - ${CRU_WIN_NATIVE_INCLUDE_DIR}/WindowRenderTarget.hpp -) -target_link_libraries(cru_win_native PUBLIC imm32) -target_link_libraries(cru_win_native PUBLIC cru_win_graph_direct cru_platform_native) diff --git a/src/win/native/Cursor.cpp b/src/win/native/Cursor.cpp deleted file mode 100644 index 429f6e7c..00000000 --- a/src/win/native/Cursor.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "cru/win/native/Cursor.hpp" - -#include "cru/common/Logger.hpp" -#include "cru/win/native/Exception.hpp" - -#include <stdexcept> - -namespace cru::platform::native::win { -WinCursor::WinCursor(HCURSOR handle, bool auto_destroy) { - handle_ = handle; - auto_destroy_ = auto_destroy; -} - -WinCursor::~WinCursor() { - if (auto_destroy_) { - if (!::DestroyCursor(handle_)) { - // This is not a fetal error but might still need notice because it may - // cause leak. - log::TagWarn(log_tag, u"Failed to destroy a cursor. Last error code: {}", - ::GetLastError()); - } - } -} - -namespace { -WinCursor* LoadWinCursor(const wchar_t* name) { - const auto handle = static_cast<HCURSOR>(::LoadImageW( - NULL, name, IMAGE_CURSOR, SM_CYCURSOR, SM_CYCURSOR, LR_SHARED)); - if (handle == NULL) { - throw Win32Error(::GetLastError(), "Failed to load system cursor."); - } - return new WinCursor(handle, false); -} -} // namespace - -WinCursorManager::WinCursorManager() - : sys_arrow_(LoadWinCursor(IDC_ARROW)), - sys_hand_(LoadWinCursor(IDC_HAND)) {} - -std::shared_ptr<WinCursor> WinCursorManager::GetSystemWinCursor( - SystemCursorType type) { - switch (type) { - case SystemCursorType::Arrow: - return sys_arrow_; - case SystemCursorType::Hand: - return sys_hand_; - default: - throw std::runtime_error("Unknown system cursor value."); - } -} -} // namespace cru::platform::native::win diff --git a/src/win/native/DpiUtil.hpp b/src/win/native/DpiUtil.hpp deleted file mode 100644 index 16ffda25..00000000 --- a/src/win/native/DpiUtil.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include "cru/platform/native/Base.hpp" - -// The dpi awareness needs to be implemented in the future. Currently we use 96 -// as default. - -namespace cru::platform::native::win { -inline platform::native::Dpi GetDpi() { - return platform::native::Dpi{96.0f, 96.0f}; -} - -inline int DipToPixelInternal(const float dip, const float dpi) { - return static_cast<int>(dip * dpi / 96.0f); -} - -inline int DipToPixelX(const float dip_x) { - return DipToPixelInternal(dip_x, GetDpi().x); -} - -inline int DipToPixelY(const float dip_y) { - return DipToPixelInternal(dip_y, GetDpi().y); -} - -inline float DipToPixelInternal(const int pixel, const float dpi) { - return static_cast<float>(pixel) * 96.0f / dpi; -} - -inline float PixelToDipX(const int pixel_x) { - return DipToPixelInternal(pixel_x, GetDpi().x); -} - -inline float PixelToDipY(const int pixel_y) { - return DipToPixelInternal(pixel_y, GetDpi().y); -} - -inline Point PiToDip(const POINT& pi_point) { - return Point(PixelToDipX(pi_point.x), PixelToDipY(pi_point.y)); -} - -inline POINT DipToPi(const Point& dip_point) { - POINT result; - result.x = DipToPixelX(dip_point.x); - result.y = DipToPixelY(dip_point.y); - return result; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/GodWindow.cpp b/src/win/native/GodWindow.cpp deleted file mode 100644 index b1e7275e..00000000 --- a/src/win/native/GodWindow.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include "cru/win/native/GodWindow.hpp" - -#include "GodWindowMessage.hpp" -#include "Timer.hpp" -#include "cru/common/Logger.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/WindowClass.hpp" - -namespace cru::platform::native::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; - const auto handled = app->GetGodWindow()->HandleGodWindowMessage( - hWnd, uMsg, wParam, lParam, &result); - if (handled) - return result; - else - return DefWindowProcW(hWnd, uMsg, wParam, lParam); - } else - 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. - log::TagWarn(log_tag, u"Failed to destroy god window."); - } -} - -bool GodWindow::HandleGodWindowMessage(HWND hwnd, UINT msg, WPARAM w_param, - LPARAM l_param, LRESULT* result) { - CRU_UNUSED(hwnd) - CRU_UNUSED(l_param) - - switch (msg) { - case invoke_later_message_id: { - const auto p_action = reinterpret_cast<std::function<void()>*>(w_param); - (*p_action)(); - delete p_action; - *result = 0; - return true; - } - case WM_TIMER: { - const auto id = static_cast<UINT_PTR>(w_param); - const auto action = application_->GetTimerManager()->GetAction(id); - if (action.has_value()) { - (action.value().second)(); - if (!action.value().first) - application_->GetTimerManager()->KillTimer(id); - result = 0; - return true; - } - break; - } - default: - return false; - } - return false; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/GodWindowMessage.hpp b/src/win/native/GodWindowMessage.hpp deleted file mode 100644 index 9063cb4d..00000000 --- a/src/win/native/GodWindowMessage.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once -#include "cru/win/WinPreConfig.hpp" - -namespace cru::platform::native::win { -constexpr int invoke_later_message_id = WM_USER + 2000; -} diff --git a/src/win/native/InputMethod.cpp b/src/win/native/InputMethod.cpp deleted file mode 100644 index 21681de2..00000000 --- a/src/win/native/InputMethod.cpp +++ /dev/null @@ -1,312 +0,0 @@ -#include "cru/win/native/InputMethod.hpp" - -#include "DpiUtil.hpp" -#include "cru/common/Logger.hpp" -#include "cru/common/StringUtil.hpp" -#include "cru/platform/Check.hpp" -#include "cru/win/Exception.hpp" -#include "cru/win/native/Window.hpp" - -#include <vector> - -namespace cru::platform::native::win { -AutoHIMC::AutoHIMC(HWND hwnd) : hwnd_(hwnd) { - Expects(hwnd); - handle_ = ::ImmGetContext(hwnd); -} - -AutoHIMC::AutoHIMC(AutoHIMC&& other) - : hwnd_(other.hwnd_), handle_(other.handle_) { - other.hwnd_ = nullptr; - other.handle_ = nullptr; -} - -AutoHIMC& AutoHIMC::operator=(AutoHIMC&& other) { - if (this != &other) { - Object::operator=(std::move(other)); - this->hwnd_ = other.hwnd_; - this->handle_ = other.handle_; - other.hwnd_ = nullptr; - other.handle_ = nullptr; - } - return *this; -} - -AutoHIMC::~AutoHIMC() { - if (handle_) { - if (!::ImmReleaseContext(hwnd_, handle_)) - log::TagWarn(log_tag, u"Failed to release HIMC."); - } -} - -// copied from chromium -namespace { -// Determines whether or not the given attribute represents a target -// (a.k.a. a selection). -bool IsTargetAttribute(char attribute) { - return (attribute == ATTR_TARGET_CONVERTED || - attribute == ATTR_TARGET_NOTCONVERTED); -} -// Helper function for ImeInput::GetCompositionInfo() method, to get the target -// range that's selected by the user in the current composition string. -void GetCompositionTargetRange(HIMC imm_context, int* target_start, - int* target_end) { - int attribute_size = - ::ImmGetCompositionString(imm_context, GCS_COMPATTR, NULL, 0); - if (attribute_size > 0) { - int start = 0; - int end = 0; - std::vector<char> attribute_data(attribute_size); - ::ImmGetCompositionString(imm_context, GCS_COMPATTR, attribute_data.data(), - attribute_size); - for (start = 0; start < attribute_size; ++start) { - if (IsTargetAttribute(attribute_data[start])) break; - } - for (end = start; end < attribute_size; ++end) { - if (!IsTargetAttribute(attribute_data[end])) break; - } - if (start == attribute_size) { - // This composition clause does not contain any target clauses, - // i.e. this clauses is an input clause. - // We treat the whole composition as a target clause. - start = 0; - end = attribute_size; - } - *target_start = start; - *target_end = end; - } -} -// Helper function for ImeInput::GetCompositionInfo() method, to get underlines -// information of the current composition string. -CompositionClauses GetCompositionClauses(HIMC imm_context, int target_start, - int target_end) { - CompositionClauses result; - int clause_size = - ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, NULL, 0); - int clause_length = clause_size / sizeof(std::uint32_t); - if (clause_length) { - result.reserve(clause_length - 1); - std::vector<std::uint32_t> clause_data(clause_length); - ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE, clause_data.data(), - clause_size); - for (int i = 0; i < clause_length - 1; ++i) { - CompositionClause clause; - clause.start = clause_data[i]; - clause.end = clause_data[i + 1]; - clause.target = false; - // Use thick underline for the target clause. - if (clause.start >= target_start && clause.end <= target_end) { - clause.target = true; - } - result.push_back(clause); - } - } - return result; -} - -std::u16string GetString(HIMC imm_context) { - LONG string_size = - ::ImmGetCompositionString(imm_context, GCS_COMPSTR, NULL, 0); - std::u16string result((string_size / sizeof(char16_t)), 0); - ::ImmGetCompositionString(imm_context, GCS_COMPSTR, result.data(), - string_size); - return result; -} - -std::u16string GetResultString(HIMC imm_context) { - LONG string_size = - ::ImmGetCompositionString(imm_context, GCS_RESULTSTR, NULL, 0); - std::u16string result((string_size / sizeof(char16_t)), 0); - ::ImmGetCompositionString(imm_context, GCS_RESULTSTR, result.data(), - string_size); - return result; -} - -CompositionText GetCompositionInfo(HIMC imm_context) { - // We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and - // convert them into underlines and selection range respectively. - - auto text = GetString(imm_context); - - int length = static_cast<int>(text.length()); - // Find out the range selected by the user. - int target_start = length; - int target_end = length; - GetCompositionTargetRange(imm_context, &target_start, &target_end); - - auto clauses = GetCompositionClauses(imm_context, target_start, target_end); - - int cursor = ::ImmGetCompositionString(imm_context, GCS_CURSORPOS, NULL, 0); - - return CompositionText{std::move(text), std::move(clauses), - TextRange{cursor}}; -} - -} // namespace - -WinInputMethodContext::WinInputMethodContext( - gsl::not_null<WinNativeWindow*> window) - : native_window_resolver_(window->GetResolver()) { - event_revoker_guards_.push_back( - EventRevokerGuard(window->NativeMessageEvent()->AddHandler( - std::bind(&WinInputMethodContext::OnWindowNativeMessage, this, - std::placeholders::_1)))); -} - -WinInputMethodContext::~WinInputMethodContext() {} - -void WinInputMethodContext::EnableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - - if (::ImmAssociateContextEx(hwnd, nullptr, IACE_DEFAULT) == FALSE) { - log::TagWarn(log_tag, u"Failed to enable ime."); - } -} - -void WinInputMethodContext::DisableIME() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return; - const auto hwnd = native_window->GetWindowHandle(); - - AutoHIMC himc{hwnd}; - - if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { - log::TagWarn(log_tag, - u"Failed to complete composition before disable ime."); - } - - if (::ImmAssociateContextEx(hwnd, nullptr, 0) == FALSE) { - log::TagWarn(log_tag, u"Failed to disable ime."); - } -} - -void WinInputMethodContext::CompleteComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - - if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_COMPLETE, 0)) { - log::TagWarn(log_tag, u"Failed to complete composition."); - } -} - -void WinInputMethodContext::CancelComposition() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - - if (!::ImmNotifyIME(himc.Get(), NI_COMPOSITIONSTR, CPS_CANCEL, 0)) { - log::TagWarn(log_tag, u"Failed to complete composition."); - } -} - -CompositionText WinInputMethodContext::GetCompositionText() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return CompositionText{}; - auto himc = *std::move(optional_himc); - - return GetCompositionInfo(himc.Get()); -} - -void WinInputMethodContext::SetCandidateWindowPosition(const Point& point) { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return; - auto himc = *std::move(optional_himc); - - ::CANDIDATEFORM form; - form.dwIndex = 1; - form.dwStyle = CFS_CANDIDATEPOS; - form.ptCurrentPos = DipToPi(point); - - if (!::ImmSetCandidateWindow(himc.Get(), &form)) - log::TagDebug(log_tag, - u"Failed to set input method candidate window position."); -} - -IEvent<std::nullptr_t>* WinInputMethodContext::CompositionStartEvent() { - return &composition_start_event_; -} - -IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEndEvent() { - return &composition_end_event_; -}; - -IEvent<std::nullptr_t>* WinInputMethodContext::CompositionEvent() { - return &composition_event_; -} - -IEvent<std::u16string_view>* WinInputMethodContext::TextEvent() { - return &text_event_; -} - -void WinInputMethodContext::OnWindowNativeMessage( - WindowNativeMessageEventArgs& args) { - const auto& message = args.GetWindowMessage(); - switch (message.msg) { - case WM_CHAR: { - const auto c = static_cast<char16_t>(message.w_param); - if (IsUtf16SurrogatePairCodeUnit(c)) { - // I don't think this will happen because normal key strike without ime - // should only trigger ascci character. If it is a charater from - // supplementary planes, it should be handled with ime messages. - log::TagWarn(log_tag, - u"A WM_CHAR message for character from supplementary " - u"planes is ignored."); - } else { - char16_t s[1] = {c}; - text_event_.Raise({s, 1}); - } - args.HandleWithResult(0); - break; - } - case WM_IME_COMPOSITION: { - composition_event_.Raise(nullptr); - auto composition_text = GetCompositionText(); - log::TagDebug(log_tag, u"WM_IME_COMPOSITION composition text:\n{}", - composition_text); - if (message.l_param & GCS_RESULTSTR) { - auto result_string = GetResultString(); - text_event_.Raise(result_string); - } - break; - } - case WM_IME_STARTCOMPOSITION: { - composition_start_event_.Raise(nullptr); - break; - } - case WM_IME_ENDCOMPOSITION: { - composition_end_event_.Raise(nullptr); - break; - } - } -} - -std::u16string WinInputMethodContext::GetResultString() { - auto optional_himc = TryGetHIMC(); - if (!optional_himc.has_value()) return u""; - auto himc = *std::move(optional_himc); - - auto result = win::GetResultString(himc.Get()); - return result; -} - -std::optional<AutoHIMC> WinInputMethodContext::TryGetHIMC() { - const auto native_window = Resolve(native_window_resolver_.get()); - if (native_window == nullptr) return std::nullopt; - const auto hwnd = native_window->GetWindowHandle(); - return AutoHIMC{hwnd}; -} - -WinInputMethodManager::WinInputMethodManager(WinUiApplication*) {} - -WinInputMethodManager::~WinInputMethodManager() {} - -std::unique_ptr<IInputMethodContext> WinInputMethodManager::GetContext( - INativeWindow* window) { - Expects(window); - const auto w = CheckPlatform<WinNativeWindow>(window, GetPlatformId()); - return std::make_unique<WinInputMethodContext>(w); -} -} // namespace cru::platform::native::win diff --git a/src/win/native/Keyboard.cpp b/src/win/native/Keyboard.cpp deleted file mode 100644 index 929ca737..00000000 --- a/src/win/native/Keyboard.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "cru/win/native/Keyboard.hpp" - -namespace cru::platform::native::win { -KeyCode VirtualKeyToKeyCode(int virtual_key) { - if (virtual_key >= 0x30 && virtual_key <= 0x39) { - return KeyCode{static_cast<int>(KeyCode::N0) + (virtual_key - 0x30)}; - } else if (virtual_key >= 0x41 && virtual_key <= 0x5a) { - return KeyCode{static_cast<int>(KeyCode::A) + (virtual_key - 0x41)}; - } else if (virtual_key >= VK_NUMPAD0 && virtual_key <= VK_NUMPAD9) { - return KeyCode{static_cast<int>(KeyCode::NumPad0) + - (virtual_key - VK_NUMPAD0)}; - } else if (virtual_key >= VK_F1 && virtual_key <= VK_F12) { - return KeyCode{static_cast<int>(KeyCode::F1) + (virtual_key - VK_F1)}; - } else { - switch (virtual_key) { -#define CRU_MAP_KEY(virtual_key, keycode) \ - case virtual_key: \ - return KeyCode::keycode; - - CRU_MAP_KEY(VK_LBUTTON, LeftButton) - CRU_MAP_KEY(VK_MBUTTON, MiddleButton) - CRU_MAP_KEY(VK_RBUTTON, RightButton) - CRU_MAP_KEY(VK_ESCAPE, Escape) - CRU_MAP_KEY(VK_OEM_3, GraveAccent) - CRU_MAP_KEY(VK_TAB, Tab) - CRU_MAP_KEY(VK_CAPITAL, CapsLock) - CRU_MAP_KEY(VK_LSHIFT, LeftShift) - CRU_MAP_KEY(VK_LCONTROL, LeftCtrl) - CRU_MAP_KEY(VK_LWIN, LeftSuper) - CRU_MAP_KEY(VK_LMENU, LeftAlt) - CRU_MAP_KEY(VK_OEM_MINUS, Minus) - CRU_MAP_KEY(VK_OEM_PLUS, Equal) - CRU_MAP_KEY(VK_BACK, Backspace) - CRU_MAP_KEY(VK_OEM_4, LeftSquareBracket) - CRU_MAP_KEY(VK_OEM_6, RightSquareBracket) - CRU_MAP_KEY(VK_OEM_5, BackSlash) - CRU_MAP_KEY(VK_OEM_1, Semicolon) - CRU_MAP_KEY(VK_OEM_7, Quote) - CRU_MAP_KEY(VK_OEM_COMMA, Comma) - CRU_MAP_KEY(VK_OEM_PERIOD, Period) - CRU_MAP_KEY(VK_OEM_2, Slash) - CRU_MAP_KEY(VK_RSHIFT, RightShift) - CRU_MAP_KEY(VK_RCONTROL, RightCtrl) - CRU_MAP_KEY(VK_RWIN, RightSuper) - CRU_MAP_KEY(VK_RMENU, RightAlt) - CRU_MAP_KEY(VK_INSERT, Insert) - CRU_MAP_KEY(VK_DELETE, Delete) - CRU_MAP_KEY(VK_HOME, Home) - CRU_MAP_KEY(VK_END, End) - CRU_MAP_KEY(VK_PRIOR, PageUp) - CRU_MAP_KEY(VK_NEXT, PageDown) - CRU_MAP_KEY(VK_UP, Up) - CRU_MAP_KEY(VK_LEFT, Left) - CRU_MAP_KEY(VK_DOWN, Down) - CRU_MAP_KEY(VK_RIGHT, Right) - CRU_MAP_KEY(VK_SNAPSHOT, PrintScreen) - CRU_MAP_KEY(VK_PAUSE, Pause) - -#undef CRU_MAP_KEY - - default: - return KeyCode::Unknown; - } - } -} - -KeyModifier RetrieveKeyMofifier() { - KeyModifier result{0}; - if (::GetKeyState(VK_SHIFT) < 0) result |= KeyModifiers::shift; - if (::GetKeyState(VK_CONTROL) < 0) result |= KeyModifiers::ctrl; - if (::GetKeyState(VK_MENU) < 0) result |= KeyModifiers::alt; - return result; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/Timer.cpp b/src/win/native/Timer.cpp deleted file mode 100644 index 662067fb..00000000 --- a/src/win/native/Timer.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "Timer.hpp" - -namespace cru::platform::native::win { -TimerManager::TimerManager(GodWindow* god_window) { god_window_ = god_window; } - -UINT_PTR TimerManager::CreateTimer(const UINT milliseconds, const bool loop, - TimerAction action) { - const auto id = current_count_++; - ::SetTimer(god_window_->GetHandle(), id, milliseconds, nullptr); - map_.emplace(id, std::make_pair(loop, std::move(action))); - return id; -} - -void TimerManager::KillTimer(const UINT_PTR id) { - const auto find_result = map_.find(id); - if (find_result != map_.cend()) { - ::KillTimer(god_window_->GetHandle(), id); - map_.erase(find_result); - } -} - -std::optional<std::pair<bool, TimerAction>> TimerManager::GetAction( - const UINT_PTR id) { - const auto find_result = map_.find(id); - if (find_result == map_.cend()) return std::nullopt; - return find_result->second; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/Timer.hpp b/src/win/native/Timer.hpp deleted file mode 100644 index 95f186a1..00000000 --- a/src/win/native/Timer.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "cru/win/WinPreConfig.hpp" - -#include "cru/common/Base.hpp" -#include "cru/win/native/GodWindow.hpp" - -#include <chrono> -#include <functional> -#include <map> -#include <optional> - -namespace cru::platform::native::win { -using TimerAction = std::function<void()>; - -class TimerManager : public Object { - public: - TimerManager(GodWindow* god_window); - - CRU_DELETE_COPY(TimerManager) - CRU_DELETE_MOVE(TimerManager) - - ~TimerManager() override = default; - - UINT_PTR CreateTimer(UINT milliseconds, bool loop, TimerAction action); - void KillTimer(UINT_PTR id); - std::optional<std::pair<bool, TimerAction>> GetAction(UINT_PTR id); - - private: - GodWindow* god_window_; - - std::map<UINT_PTR, std::pair<bool, TimerAction>> map_{}; - UINT_PTR current_count_ = 0; -}; -} // namespace cru::platform::native::win diff --git a/src/win/native/UiApplication.cpp b/src/win/native/UiApplication.cpp deleted file mode 100644 index dbf52e05..00000000 --- a/src/win/native/UiApplication.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "cru/win/native/UiApplication.hpp" - -#include "../DebugLogger.hpp" -#include "cru/common/Logger.hpp" -#include "cru/platform/Check.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "cru/win/native/Cursor.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/GodWindow.hpp" -#include "cru/win/native/InputMethod.hpp" -#include "cru/win/native/Window.hpp" -#include "GodWindowMessage.hpp" -#include "Timer.hpp" -#include "WindowManager.hpp" - -namespace cru::platform::native { -std::unique_ptr<IUiApplication> CreateUiApplication() { - return std::make_unique<win::WinUiApplication>(); -} -} // namespace cru::platform::native - -namespace cru::platform::native::win { -WinUiApplication* WinUiApplication::instance = nullptr; - -WinUiApplication::WinUiApplication() { - instance = this; - - instance_handle_ = ::GetModuleHandleW(nullptr); - if (!instance_handle_) - throw Win32Error("Failed to get module(instance) handle."); - - log::Logger::GetInstance()->AddSource( - std::make_unique<::cru::platform::win::WinDebugLoggerSource>()); - - graph_factory_ = - std::make_unique<cru::platform::graph::win::direct::DirectGraphFactory>(); - - 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>(); - input_method_manager_ = std::make_unique<WinInputMethodManager>(this); -} - -WinUiApplication::~WinUiApplication() { instance = nullptr; } - -int WinUiApplication::Run() { - MSG msg; - while (GetMessageW(&msg, nullptr, 0, 0)) { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - - for (const auto& handler : quit_handlers_) handler(); - - return static_cast<int>(msg.wParam); -} - -void WinUiApplication::RequestQuit(const int quit_code) { - ::PostQuitMessage(quit_code); -} - -void WinUiApplication::AddOnQuitHandler(std::function<void()> handler) { - quit_handlers_.push_back(std::move(handler)); -} - -void WinUiApplication::InvokeLater(std::function<void()> action) { - // copy the action to a safe place - auto p_action_copy = new std::function<void()>(std::move(action)); - - if (::PostMessageW(GetGodWindow()->GetHandle(), invoke_later_message_id, - reinterpret_cast<WPARAM>(p_action_copy), 0) == 0) - throw Win32Error(::GetLastError(), "InvokeLater failed to post message."); -} - -long long WinUiApplication::SetTimeout(std::chrono::milliseconds milliseconds, - std::function<void()> action) { - return gsl::narrow<long long>(timer_manager_->CreateTimer( - static_cast<UINT>(milliseconds.count()), false, std::move(action))); -} - -long long WinUiApplication::SetInterval(std::chrono::milliseconds milliseconds, - std::function<void()> action) { - return gsl::narrow<long long>(timer_manager_->CreateTimer( - static_cast<UINT>(milliseconds.count()), true, std::move(action))); -} - -void WinUiApplication::CancelTimer(long long id) { - if (id < 0) return; - timer_manager_->KillTimer(static_cast<UINT_PTR>(id)); -} - -std::vector<INativeWindow*> WinUiApplication::GetAllWindow() { - const auto&& windows = window_manager_->GetAllWindows(); - std::vector<INativeWindow*> result; - for (const auto w : windows) { - result.push_back(static_cast<INativeWindow*>(w)); - } - return result; -} - -std::shared_ptr<INativeWindowResolver> WinUiApplication::CreateWindow( - INativeWindow* parent) { - WinNativeWindow* p = nullptr; - if (parent != nullptr) { - p = CheckPlatform<WinNativeWindow>(parent, GetPlatformId()); - } - return (new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), - WS_OVERLAPPEDWINDOW, p)) - ->GetResolver(); -} - -cru::platform::graph::IGraphFactory* WinUiApplication::GetGraphFactory() { - return graph_factory_.get(); -} - -ICursorManager* WinUiApplication::GetCursorManager() { - return cursor_manager_.get(); -} - -IInputMethodManager* WinUiApplication::GetInputMethodManager() { - return input_method_manager_.get(); -} -} // namespace cru::platform::native::win diff --git a/src/win/native/Window.cpp b/src/win/native/Window.cpp deleted file mode 100644 index 81642451..00000000 --- a/src/win/native/Window.cpp +++ /dev/null @@ -1,442 +0,0 @@ -#include "cru/win/native/Window.hpp" - -#include "DpiUtil.hpp" -#include "WindowD2DPainter.hpp" -#include "WindowManager.hpp" -#include "cru/common/Logger.hpp" -#include "cru/platform/Check.hpp" -#include "cru/win/native/Cursor.hpp" -#include "cru/win/native/Exception.hpp" -#include "cru/win/native/Keyboard.hpp" -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/WindowClass.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" - -#include <imm.h> -#include <windowsx.h> - -namespace cru::platform::native::win { -WinNativeWindow::WinNativeWindow(WinUiApplication* application, - WindowClass* window_class, DWORD window_style, - WinNativeWindow* parent) - : application_(application), - resolver_(std::make_shared<WinNativeWindowResolver>(this)), - parent_window_(parent) { - Expects(application); // application can't be null. - - if (parent != nullptr) { - throw new std::runtime_error("Can't use a invalid window as parent."); - } - - const auto window_manager = application->GetWindowManager(); - - hwnd_ = CreateWindowExW( - 0, window_class->GetName(), L"", window_style, CW_USEDEFAULT, - CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, - parent == nullptr ? nullptr : parent->GetWindowHandle(), nullptr, - application->GetInstanceHandle(), nullptr); - - if (hwnd_ == nullptr) - throw Win32Error(::GetLastError(), "Failed to create window."); - - window_manager->RegisterWindow(hwnd_, this); - - SetCursor(application->GetCursorManager()->GetSystemCursor( - cru::platform::native::SystemCursorType::Arrow)); - - window_render_target_ = std::make_unique<WindowRenderTarget>( - application->GetDirectFactory(), hwnd_); -} - -WinNativeWindow::~WinNativeWindow() { - if (!sync_flag_) { - sync_flag_ = true; - Close(); - } - resolver_->Reset(); -} - -void WinNativeWindow::Close() { ::DestroyWindow(hwnd_); } - -bool WinNativeWindow::IsVisible() { return ::IsWindowVisible(hwnd_); } - -void WinNativeWindow::SetVisible(bool is_visible) { - is_visible ? ShowWindow(hwnd_, SW_SHOWNORMAL) : ShowWindow(hwnd_, SW_HIDE); -} -Size WinNativeWindow::GetClientSize() { - const auto pixel_rect = GetClientRectPixel(); - return Size(PixelToDipX(pixel_rect.right), PixelToDipY(pixel_rect.bottom)); -} - -void WinNativeWindow::SetClientSize(const Size& size) { - const auto window_style = - static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_STYLE)); - const auto window_ex_style = - static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_EXSTYLE)); - - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = DipToPixelX(size.width); - rect.bottom = DipToPixelY(size.height); - if (!AdjustWindowRectEx(&rect, window_style, FALSE, window_ex_style)) - throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx."); - - if (!SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left, - rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE)) - throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos."); -} - -Rect WinNativeWindow::GetWindowRect() { - RECT rect; - if (!::GetWindowRect(hwnd_, &rect)) - throw Win32Error(::GetLastError(), "Failed to invoke GetWindowRect."); - - return Rect::FromVertices(PixelToDipX(rect.left), PixelToDipY(rect.top), - PixelToDipX(rect.right), PixelToDipY(rect.bottom)); -} - -void WinNativeWindow::SetWindowRect(const Rect& rect) { - if (!SetWindowPos(hwnd_, nullptr, DipToPixelX(rect.left), - DipToPixelY(rect.top), DipToPixelX(rect.GetRight()), - DipToPixelY(rect.GetBottom()), SWP_NOZORDER)) - throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos."); -} - -Point WinNativeWindow::GetMousePosition() { - POINT p; - if (!::GetCursorPos(&p)) - throw Win32Error(::GetLastError(), "Failed to get cursor position."); - if (!::ScreenToClient(hwnd_, &p)) - throw Win32Error(::GetLastError(), "Failed to call ScreenToClient."); - return PiToDip(p); -} - -bool WinNativeWindow::CaptureMouse() { - ::SetCapture(hwnd_); - return true; -} - -bool WinNativeWindow::ReleaseMouse() { - const auto result = ::ReleaseCapture(); - return result != 0; -} - -void WinNativeWindow::RequestRepaint() { - log::TagDebug(log_tag, u"A repaint is requested."); - if (!::InvalidateRect(hwnd_, nullptr, FALSE)) - throw Win32Error(::GetLastError(), "Failed to invalidate window."); - if (!::UpdateWindow(hwnd_)) - throw Win32Error(::GetLastError(), "Failed to update window."); -} - -std::unique_ptr<graph::IPainter> WinNativeWindow::BeginPaint() { - return std::make_unique<WindowD2DPainter>(window_render_target_.get()); -} - -void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) { - if (cursor == nullptr) { - throw std::runtime_error("Can't use a nullptr as cursor."); - } - - cursor_ = CheckPlatform<WinCursor>(cursor, GetPlatformId()); - - if (!::SetClassLongPtrW(hwnd_, GCLP_HCURSOR, - reinterpret_cast<LONG_PTR>(cursor_->GetHandle()))) { - log::TagWarn(log_tag, - u"Failed to set cursor because failed to set class long. Last " - u"error code: {}.", - ::GetLastError()); - return; - } - - if (!IsVisible()) return; - - auto lg = [](const std::u16string_view& reason) { - log::TagWarn( - log_tag, - u"Failed to set cursor because {} when window is visible. (We need to " - u"update cursor if it is inside the window.) Last error code: {}.", - reason, ::GetLastError()); - }; - - ::POINT point; - if (!::GetCursorPos(&point)) { - lg(u"failed to get cursor pos"); - return; - } - - ::RECT rect; - if (!::GetClientRect(hwnd_, &rect)) { - lg(u"failed to get window's client rect"); - return; - } - - ::POINT lefttop{rect.left, rect.top}; - ::POINT rightbottom{rect.right, rect.bottom}; - if (!::ClientToScreen(hwnd_, &lefttop)) { - lg(u"failed to call ClientToScreen on lefttop"); - return; - } - - if (!::ClientToScreen(hwnd_, &rightbottom)) { - lg(u"failed to call ClientToScreen on rightbottom"); - return; - } - - if (point.x >= lefttop.x && point.y >= lefttop.y && - point.x <= rightbottom.x && point.y <= rightbottom.y) { - ::SetCursor(cursor_->GetHandle()); - } -} - -bool WinNativeWindow::HandleNativeWindowMessage(HWND hwnd, UINT msg, - WPARAM w_param, LPARAM l_param, - LRESULT* result) { - WindowNativeMessageEventArgs args{ - WindowNativeMessage{hwnd, msg, w_param, l_param}}; - native_message_event_.Raise(args); - if (args.IsHandled()) { - *result = args.GetResult(); - return true; - } - - switch (msg) { - case WM_PAINT: - OnPaintInternal(); - *result = 0; - return true; - case WM_ERASEBKGND: - *result = 1; - return true; - case WM_SETFOCUS: - OnSetFocusInternal(); - *result = 0; - return true; - case WM_KILLFOCUS: - OnKillFocusInternal(); - *result = 0; - return true; - case WM_MOUSEMOVE: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseMoveInternal(point); - *result = 0; - return true; - } - case WM_LBUTTONDOWN: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::left, point); - *result = 0; - return true; - } - case WM_LBUTTONUP: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::left, point); - *result = 0; - return true; - } - case WM_RBUTTONDOWN: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::right, point); - *result = 0; - return true; - } - case WM_RBUTTONUP: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::right, point); - *result = 0; - return true; - } - case WM_MBUTTONDOWN: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseDownInternal(platform::native::mouse_buttons::middle, point); - *result = 0; - return true; - } - case WM_MBUTTONUP: { - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - OnMouseUpInternal(platform::native::mouse_buttons::middle, point); - *result = 0; - return true; - } - case WM_MOUSEWHEEL: - POINT point; - point.x = GET_X_LPARAM(l_param); - point.y = GET_Y_LPARAM(l_param); - ScreenToClient(hwnd, &point); - OnMouseWheelInternal(GET_WHEEL_DELTA_WPARAM(w_param), point); - *result = 0; - return true; - case WM_KEYDOWN: - OnKeyDownInternal(static_cast<int>(w_param)); - *result = 0; - return true; - case WM_KEYUP: - OnKeyUpInternal(static_cast<int>(w_param)); - *result = 0; - return true; - case WM_SYSKEYDOWN: - if (l_param & (1 << 29)) { - OnKeyDownInternal(static_cast<int>(w_param)); - *result = 0; - return true; - } - return false; - case WM_SYSKEYUP: - if (l_param & (1 << 29)) { - OnKeyUpInternal(static_cast<int>(w_param)); - *result = 0; - return true; - } - return false; - case WM_SIZE: - OnResizeInternal(LOWORD(l_param), HIWORD(l_param)); - *result = 0; - return true; - case WM_ACTIVATE: - if (w_param == WA_ACTIVE || w_param == WA_CLICKACTIVE) - OnActivatedInternal(); - else if (w_param == WA_INACTIVE) - OnDeactivatedInternal(); - *result = 0; - return true; - case WM_DESTROY: - OnDestroyInternal(); - *result = 0; - return true; - case WM_IME_SETCONTEXT: - l_param &= ~ISC_SHOWUICOMPOSITIONWINDOW; - *result = ::DefWindowProcW(hwnd, msg, w_param, l_param); - return true; - // We must block these message from DefWindowProc or it will create - // an ugly composition window. - case WM_IME_STARTCOMPOSITION: - case WM_IME_COMPOSITION: - *result = 0; - return true; - default: - return false; - } -} - -RECT WinNativeWindow::GetClientRectPixel() { - RECT rect; - if (!GetClientRect(hwnd_, &rect)) - throw Win32Error(::GetLastError(), "Failed to invoke GetClientRect."); - return rect; -} - -void WinNativeWindow::OnDestroyInternal() { - application_->GetWindowManager()->UnregisterWindow(hwnd_); - hwnd_ = nullptr; - destroy_event_.Raise(nullptr); - if (!sync_flag_) { - sync_flag_ = true; - delete this; - } -} - -void WinNativeWindow::OnPaintInternal() { - paint_event_.Raise(nullptr); - ValidateRect(hwnd_, nullptr); - log::TagDebug(log_tag, u"A repaint is finished."); -} - -void WinNativeWindow::OnResizeInternal(const int new_width, - const int new_height) { - if (!(new_width == 0 && new_height == 0)) { - window_render_target_->ResizeBuffer(new_width, new_height); - resize_event_.Raise(Size{PixelToDipX(new_width), PixelToDipY(new_height)}); - } -} - -void WinNativeWindow::OnSetFocusInternal() { - has_focus_ = true; - focus_event_.Raise(FocusChangeType::Gain); -} - -void WinNativeWindow::OnKillFocusInternal() { - has_focus_ = false; - focus_event_.Raise(FocusChangeType::Lost); -} - -void WinNativeWindow::OnMouseMoveInternal(const POINT point) { - // when mouse was previous outside the window - if (!is_mouse_in_) { - // invoke TrackMouseEvent to have WM_MOUSELEAVE sent. - TRACKMOUSEEVENT tme; - tme.cbSize = sizeof tme; - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hwnd_; - - TrackMouseEvent(&tme); - - is_mouse_in_ = true; - mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Enter); - } - - mouse_move_event_.Raise(PiToDip(point)); -} - -void WinNativeWindow::OnMouseLeaveInternal() { - is_mouse_in_ = false; - mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Leave); -} - -void WinNativeWindow::OnMouseDownInternal(platform::native::MouseButton button, - POINT point) { - const auto dip_point = PiToDip(point); - mouse_down_event_.Raise({button, dip_point, RetrieveKeyMofifier()}); -} - -void WinNativeWindow::OnMouseUpInternal(platform::native::MouseButton button, - POINT point) { - const auto dip_point = PiToDip(point); - mouse_up_event_.Raise({button, dip_point, RetrieveKeyMofifier()}); -} - -void WinNativeWindow::OnMouseWheelInternal(short delta, POINT point) { - CRU_UNUSED(delta) - CRU_UNUSED(point) -} - -void WinNativeWindow::OnKeyDownInternal(int virtual_code) { - key_down_event_.Raise( - {VirtualKeyToKeyCode(virtual_code), RetrieveKeyMofifier()}); -} - -void WinNativeWindow::OnKeyUpInternal(int virtual_code) { - key_up_event_.Raise( - {VirtualKeyToKeyCode(virtual_code), RetrieveKeyMofifier()}); -} - -void WinNativeWindow::OnActivatedInternal() {} - -void WinNativeWindow::OnDeactivatedInternal() {} - -void WinNativeWindowResolver::Reset() { - Expects(window_); // already reset, can't reset again - window_ = nullptr; -} - -WinNativeWindow* Resolve(gsl::not_null<INativeWindowResolver*> resolver) { - const auto window = resolver->Resolve(); - return window == nullptr ? nullptr - : CheckPlatform<WinNativeWindow>( - window, WinNativeResource::k_platform_id); -} // namespace cru::platform::native::win -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowClass.cpp b/src/win/native/WindowClass.cpp deleted file mode 100644 index 2e74606e..00000000 --- a/src/win/native/WindowClass.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "cru/win/native/WindowClass.hpp" - -#include "cru/win/native/Exception.hpp" - -namespace cru::platform::native::win { -WindowClass::WindowClass(std::wstring name, WNDPROC window_proc, - HINSTANCE h_instance) - : name_(std::move(name)) { - WNDCLASSEXW window_class; - window_class.cbSize = sizeof(WNDCLASSEXW); - - window_class.style = CS_HREDRAW | CS_VREDRAW; - window_class.lpfnWndProc = window_proc; - window_class.cbClsExtra = 0; - window_class.cbWndExtra = 0; - window_class.hInstance = h_instance; - window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION); - window_class.hCursor = LoadCursor(NULL, IDC_ARROW); - window_class.hbrBackground = GetSysColorBrush(COLOR_BTNFACE); - window_class.lpszMenuName = NULL; - window_class.lpszClassName = name_.c_str(); - window_class.hIconSm = NULL; - - atom_ = ::RegisterClassExW(&window_class); - if (atom_ == 0) - throw Win32Error(::GetLastError(), "Failed to create window class."); -} -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowD2DPainter.cpp b/src/win/native/WindowD2DPainter.cpp deleted file mode 100644 index 7a97480b..00000000 --- a/src/win/native/WindowD2DPainter.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "WindowD2DPainter.hpp" - -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" - -namespace cru::platform::native::win { -using namespace cru::platform::graph::win::direct; - -WindowD2DPainter::WindowD2DPainter(WindowRenderTarget* render_target) - : D2DPainter(render_target->GetD2D1DeviceContext()), - render_target_(render_target) { - render_target_->GetD2D1DeviceContext()->BeginDraw(); -} - -WindowD2DPainter::~WindowD2DPainter() { EndDraw(); } - -void WindowD2DPainter::DoEndDraw() { - ThrowIfFailed(render_target_->GetD2D1DeviceContext()->EndDraw()); - render_target_->Present(); -} -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowD2DPainter.hpp b/src/win/native/WindowD2DPainter.hpp deleted file mode 100644 index a638b77a..00000000 --- a/src/win/native/WindowD2DPainter.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include "cru/win/graph/direct/Painter.hpp" -#include "cru/win/native/WindowRenderTarget.hpp" - -namespace cru::platform::native::win { -class WindowD2DPainter : public graph::win::direct::D2DPainter { - public: - explicit WindowD2DPainter(WindowRenderTarget* window); - - CRU_DELETE_COPY(WindowD2DPainter) - CRU_DELETE_MOVE(WindowD2DPainter) - - ~WindowD2DPainter() override; - - protected: - void DoEndDraw() override; - - private: - WindowRenderTarget* render_target_; -}; -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowManager.cpp b/src/win/native/WindowManager.cpp deleted file mode 100644 index 56cc8981..00000000 --- a/src/win/native/WindowManager.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "WindowManager.hpp" - -#include "cru/win/native/UiApplication.hpp" -#include "cru/win/native/Window.hpp" -#include "cru/win/native/WindowClass.hpp" - -namespace cru::platform::native::win { -LRESULT __stdcall GeneralWndProc(HWND hWnd, UINT Msg, WPARAM wParam, - LPARAM lParam) { - auto window = - WinUiApplication::GetInstance()->GetWindowManager()->FromHandle(hWnd); - - LRESULT result; - if (window != nullptr && - window->HandleNativeWindowMessage(hWnd, Msg, wParam, lParam, &result)) - return result; - - return DefWindowProc(hWnd, Msg, wParam, lParam); -} - -WindowManager::WindowManager(WinUiApplication* application) { - application_ = application; - general_window_class_ = std::make_unique<WindowClass>( - L"CruUIWindowClass", GeneralWndProc, application->GetInstanceHandle()); -} - -WindowManager::~WindowManager() { - for (const auto& [key, window] : window_map_) delete window; -} - -void WindowManager::RegisterWindow(HWND hwnd, WinNativeWindow* window) { - Expects(window_map_.count(hwnd) == 0); // The hwnd is already in the map. - window_map_.emplace(hwnd, window); -} - -void WindowManager::UnregisterWindow(HWND hwnd) { - const auto find_result = window_map_.find(hwnd); - Expects(find_result != window_map_.end()); // The hwnd is not in the map. - window_map_.erase(find_result); - if (window_map_.empty()) application_->RequestQuit(0); -} - -WinNativeWindow* WindowManager::FromHandle(HWND hwnd) { - const auto find_result = window_map_.find(hwnd); - if (find_result == window_map_.end()) - return nullptr; - else - return find_result->second; -} - -std::vector<WinNativeWindow*> WindowManager::GetAllWindows() const { - std::vector<WinNativeWindow*> windows; - for (const auto& [key, value] : window_map_) windows.push_back(value); - return windows; -} -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowManager.hpp b/src/win/native/WindowManager.hpp deleted file mode 100644 index 3f6387f7..00000000 --- a/src/win/native/WindowManager.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include "cru/win/WinPreConfig.hpp" - -#include "cru/common/Base.hpp" - -#include <map> -#include <memory> -#include <vector> - -namespace cru::platform::native::win { -class WinUiApplication; -class WinNativeWindow; -class WindowClass; - -class WindowManager : public Object { - public: - WindowManager(WinUiApplication* application); - - CRU_DELETE_COPY(WindowManager) - CRU_DELETE_MOVE(WindowManager) - - ~WindowManager() override; - - // Get the general window class for creating ordinary window. - WindowClass* GetGeneralWindowClass() const { - return general_window_class_.get(); - } - - // Register a window newly created. - // This function adds the hwnd to hwnd-window map. - // It should be called immediately after a window was created. - void RegisterWindow(HWND hwnd, WinNativeWindow* window); - - // Unregister a window that is going to be destroyed. - // This function removes the hwnd from the hwnd-window map. - // It should be called immediately before a window is going to be destroyed, - void UnregisterWindow(HWND hwnd); - - // Return a pointer to the Window object related to the HWND or nullptr if the - // hwnd is not in the map. - WinNativeWindow* FromHandle(HWND hwnd); - - std::vector<WinNativeWindow*> GetAllWindows() const; - - private: - WinUiApplication* application_; - - std::unique_ptr<WindowClass> general_window_class_; - std::map<HWND, WinNativeWindow*> window_map_; -}; -} // namespace cru::platform::native::win diff --git a/src/win/native/WindowRenderTarget.cpp b/src/win/native/WindowRenderTarget.cpp deleted file mode 100644 index 4a114ebf..00000000 --- a/src/win/native/WindowRenderTarget.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "cru/win/native/WindowRenderTarget.hpp" - -#include "cru/win/graph/direct/Exception.hpp" -#include "cru/win/graph/direct/Factory.hpp" -#include "DpiUtil.hpp" - -namespace cru::platform::native::win { -using namespace cru::platform::graph::win::direct; -WindowRenderTarget::WindowRenderTarget(DirectGraphFactory* factory, HWND hwnd) - : factory_(factory) { - Expects(factory); - - const auto d3d11_device = factory->GetD3D11Device(); - const auto dxgi_factory = factory->GetDxgiFactory(); - - d2d1_device_context_ = factory->CreateD2D1DeviceContext(); - - // Allocate a descriptor. - DXGI_SWAP_CHAIN_DESC1 swap_chain_desc; - swap_chain_desc.Width = 0; // use automatic sizing - swap_chain_desc.Height = 0; - swap_chain_desc.Format = - DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format - swap_chain_desc.Stereo = false; - swap_chain_desc.SampleDesc.Count = 1; // don't use multi-sampling - swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.BufferCount = 2; // use double buffering to enable flip - swap_chain_desc.Scaling = DXGI_SCALING_NONE; - swap_chain_desc.SwapEffect = - DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect - swap_chain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - swap_chain_desc.Flags = 0; - - // Get the final swap chain for this window from the DXGI factory. - ThrowIfFailed(dxgi_factory->CreateSwapChainForHwnd( - d3d11_device, hwnd, &swap_chain_desc, nullptr, nullptr, - &dxgi_swap_chain_)); - - CreateTargetBitmap(); -} - -void WindowRenderTarget::ResizeBuffer(const int width, const int height) { - // In order to resize buffer, we need to untarget the buffer first. - d2d1_device_context_->SetTarget(nullptr); - target_bitmap_ = nullptr; - ThrowIfFailed(dxgi_swap_chain_->ResizeBuffers(0, width, height, - DXGI_FORMAT_UNKNOWN, 0)); - CreateTargetBitmap(); -} - -void WindowRenderTarget::Present() { - ThrowIfFailed(dxgi_swap_chain_->Present(1, 0)); -} - -void WindowRenderTarget::CreateTargetBitmap() { - Expects(target_bitmap_ == nullptr); // target bitmap must not exist. - - // Direct2D needs the dxgi version of the backbuffer surface pointer. - Microsoft::WRL::ComPtr<IDXGISurface> dxgi_back_buffer; - ThrowIfFailed( - dxgi_swap_chain_->GetBuffer(0, IID_PPV_ARGS(&dxgi_back_buffer))); - - const auto dpi = GetDpi(); // TODO! DPI awareness. - - auto bitmap_properties = D2D1::BitmapProperties1( - D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW, - D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE), - dpi.x, dpi.y); - - // Get a D2D surface from the DXGI back buffer to use as the D2D render - // target. - ThrowIfFailed(d2d1_device_context_->CreateBitmapFromDxgiSurface( - dxgi_back_buffer.Get(), &bitmap_properties, &target_bitmap_)); - - d2d1_device_context_->SetTarget(target_bitmap_.Get()); -} -} // namespace cru::platform::native::win |