diff options
author | crupest <crupest@outlook.com> | 2022-05-15 14:08:06 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-05-15 14:08:06 +0800 |
commit | 8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6 (patch) | |
tree | 77e41cc14264060517c0f7ed95837012afb8342e /src/osx/gui | |
parent | 9e0c9d3499bc50c3534b4dc500d8b5d0b5f22752 (diff) | |
download | cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.tar.gz cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.tar.bz2 cru-8ad2966933957ac5d6ff8dcd5e732736fd5e4dc6.zip |
...
Diffstat (limited to 'src/osx/gui')
-rw-r--r-- | src/osx/gui/CMakeLists.txt | 15 | ||||
-rw-r--r-- | src/osx/gui/Clipboard.mm | 46 | ||||
-rw-r--r-- | src/osx/gui/ClipboardPrivate.h | 27 | ||||
-rw-r--r-- | src/osx/gui/Cursor.mm | 93 | ||||
-rw-r--r-- | src/osx/gui/CursorPrivate.h | 29 | ||||
-rw-r--r-- | src/osx/gui/InputMethod.mm | 84 | ||||
-rw-r--r-- | src/osx/gui/InputMethodPrivate.h | 64 | ||||
-rw-r--r-- | src/osx/gui/Keyboard.mm | 283 | ||||
-rw-r--r-- | src/osx/gui/KeyboardPrivate.h | 9 | ||||
-rw-r--r-- | src/osx/gui/Menu.mm | 180 | ||||
-rw-r--r-- | src/osx/gui/MenuPrivate.h | 65 | ||||
-rw-r--r-- | src/osx/gui/Resource.cpp | 6 | ||||
-rw-r--r-- | src/osx/gui/UiApplication.mm | 260 | ||||
-rw-r--r-- | src/osx/gui/Window.mm | 800 | ||||
-rw-r--r-- | src/osx/gui/WindowPrivate.h | 118 |
15 files changed, 0 insertions, 2079 deletions
diff --git a/src/osx/gui/CMakeLists.txt b/src/osx/gui/CMakeLists.txt deleted file mode 100644 index 5442ad15..00000000 --- a/src/osx/gui/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -add_library(CruPlatformGuiOsx SHARED - Clipboard.mm - Cursor.mm - InputMethod.mm - Keyboard.mm - Menu.mm - Resource.cpp - UiApplication.mm - Window.mm -) - -find_library(APPKIT AppKit REQUIRED) -find_library(UNIFORMTYPEIDENTIFIERS UniformTypeIdentifiers REQUIRED) - -target_link_libraries(CruPlatformGuiOsx PUBLIC CruPlatformGui CruPlatformGraphicsQuartz ${APPKIT} ${UNIFORMTYPEIDENTIFIERS}) diff --git a/src/osx/gui/Clipboard.mm b/src/osx/gui/Clipboard.mm deleted file mode 100644 index 6e3fb076..00000000 --- a/src/osx/gui/Clipboard.mm +++ /dev/null @@ -1,46 +0,0 @@ -#include "cru/osx/gui/Clipboard.h" -#include "ClipboardPrivate.h" - -#include "cru/common/log/Logger.h" -#include "cru/osx/Convert.h" - -#include <memory> - -namespace cru::platform::gui::osx { -using cru::platform::osx::Convert; - -OsxClipboard::OsxClipboard(cru::platform::gui::IUiApplication* ui_application, - std::unique_ptr<details::OsxClipboardPrivate> p) - : OsxGuiResource(ui_application), p_(std::move(p)) {} - -OsxClipboard::~OsxClipboard() {} - -String OsxClipboard::GetText() { return p_->GetText(); } - -void OsxClipboard::SetText(String text) { p_->SetText(text); } - -namespace details { -OsxClipboardPrivate::OsxClipboardPrivate(NSPasteboard* pasteboard) : pasteboard_(pasteboard) {} - -OsxClipboardPrivate::~OsxClipboardPrivate() {} - -String OsxClipboardPrivate::GetText() { - auto result = [pasteboard_ readObjectsForClasses:@[ NSString.class ] options:nil]; - if (result == nil) { - CRU_LOG_WARN(u"Failed to get text from clipboard"); - return u""; - } else { - if (result.count == 0) { - return u""; - } else { - return Convert((CFStringRef)result[0]); - } - } -} - -void OsxClipboardPrivate::SetText(String text) { - [pasteboard_ clearContents]; - [pasteboard_ writeObjects:@[ (NSString*)Convert(text) ]]; -} -} -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/ClipboardPrivate.h b/src/osx/gui/ClipboardPrivate.h deleted file mode 100644 index 63145a64..00000000 --- a/src/osx/gui/ClipboardPrivate.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include "cru/common/Base.h" -#include "cru/osx/gui/Clipboard.h" - -#include <AppKit/AppKit.h> - -namespace cru::platform::gui::osx { -namespace details { -class OsxClipboardPrivate : public Object { - CRU_DEFINE_CLASS_LOG_TAG(u"OsxClipboardPrivate") - public: - explicit OsxClipboardPrivate(NSPasteboard* pasteboard); - - CRU_DELETE_COPY(OsxClipboardPrivate) - CRU_DELETE_MOVE(OsxClipboardPrivate) - - ~OsxClipboardPrivate(); - - public: - String GetText(); - void SetText(String text); - - private: - NSPasteboard* pasteboard_; -}; -} // namespace details -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/Cursor.mm b/src/osx/gui/Cursor.mm deleted file mode 100644 index 13bdc858..00000000 --- a/src/osx/gui/Cursor.mm +++ /dev/null @@ -1,93 +0,0 @@ -#include "cru/osx/gui/Cursor.h" -#include "CursorPrivate.h" - -#include "cru/osx/Exception.h" -#include "cru/osx/gui/Resource.h" -#include "cru/platform/gui/Cursor.h" -#include "cru/platform/gui/UiApplication.h" - -#include <memory> - -namespace cru::platform::gui::osx { -namespace details { -OsxCursorPrivate::OsxCursorPrivate(OsxCursor* cursor, SystemCursorType cursor_type) { - cursor_ = cursor; - - switch (cursor_type) { - case SystemCursorType::Arrow: - ns_cursor_ = [NSCursor arrowCursor]; - break; - case SystemCursorType::Hand: - ns_cursor_ = [NSCursor pointingHandCursor]; - break; - case SystemCursorType::IBeam: - ns_cursor_ = [NSCursor IBeamCursor]; - break; - default: - throw Exception(u"Unknown system cursor type."); - } -} - -OsxCursorPrivate::~OsxCursorPrivate() {} -} - -OsxCursor::OsxCursor(IUiApplication* ui_application, SystemCursorType cursor_type) - : OsxGuiResource(ui_application) { - p_ = std::make_unique<details::OsxCursorPrivate>(this, cursor_type); -} - -OsxCursor::~OsxCursor() {} - -namespace details { -class OsxCursorManagerPrivate { - friend OsxCursorManager; - - public: - explicit OsxCursorManagerPrivate(OsxCursorManager* cursor_manager); - - CRU_DELETE_COPY(OsxCursorManagerPrivate) - CRU_DELETE_MOVE(OsxCursorManagerPrivate) - - ~OsxCursorManagerPrivate(); - - private: - OsxCursorManager* cursor_manager_; - - std::shared_ptr<OsxCursor> arrow_cursor_; - std::shared_ptr<OsxCursor> hand_cursor_; - std::shared_ptr<OsxCursor> ibeam_cursor_; -}; - -OsxCursorManagerPrivate::OsxCursorManagerPrivate(OsxCursorManager* cursor_manager) { - cursor_manager_ = cursor_manager; - arrow_cursor_ = - std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::Arrow); - hand_cursor_ = - std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::Hand); - ibeam_cursor_ = - std::make_shared<OsxCursor>(cursor_manager->GetUiApplication(), SystemCursorType::IBeam); -} - -OsxCursorManagerPrivate::~OsxCursorManagerPrivate() {} -} - -OsxCursorManager::OsxCursorManager(IUiApplication* ui_application) - : OsxGuiResource(ui_application) { - p_ = std::make_unique<details::OsxCursorManagerPrivate>(this); -} - -OsxCursorManager::~OsxCursorManager() {} - -std::shared_ptr<ICursor> OsxCursorManager::GetSystemCursor(SystemCursorType type) { - switch (type) { - case SystemCursorType::Arrow: - return p_->arrow_cursor_; - case SystemCursorType::Hand: - return p_->hand_cursor_; - case SystemCursorType::IBeam: - return p_->ibeam_cursor_; - default: - throw Exception(u"Unknown system cursor type."); - } -} -} diff --git a/src/osx/gui/CursorPrivate.h b/src/osx/gui/CursorPrivate.h deleted file mode 100644 index c840e286..00000000 --- a/src/osx/gui/CursorPrivate.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "cru/osx/gui/Cursor.h" - -#import <AppKit/NSCursor.h> - -namespace cru::platform::gui::osx { -class OsxWindow; - -namespace details { -class OsxWindowPrivate; - -class OsxCursorPrivate { - friend OsxWindow; - friend OsxWindowPrivate; - - public: - OsxCursorPrivate(OsxCursor* cursor, SystemCursorType cursor_type); - - CRU_DELETE_COPY(OsxCursorPrivate) - CRU_DELETE_MOVE(OsxCursorPrivate) - - ~OsxCursorPrivate(); - - private: - OsxCursor* cursor_; - NSCursor* ns_cursor_; -}; -} // namespace details -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/InputMethod.mm b/src/osx/gui/InputMethod.mm deleted file mode 100644 index 2c19c358..00000000 --- a/src/osx/gui/InputMethod.mm +++ /dev/null @@ -1,84 +0,0 @@ -#include "cru/osx/gui/InputMethod.h" - -#import <AppKit/AppKit.h> -#include "InputMethodPrivate.h" -#include "WindowPrivate.h" -#include "cru/common/log/Logger.h" -#include "cru/osx/Convert.h" -#include "cru/osx/gui/Window.h" - -namespace cru::platform::gui::osx { -namespace details { -OsxInputMethodContextPrivate::OsxInputMethodContextPrivate( - OsxInputMethodContext* input_method_context, OsxWindow* window) { - input_method_context_ = input_method_context; - window_ = window; -} - -OsxInputMethodContextPrivate::~OsxInputMethodContextPrivate() {} - -void OsxInputMethodContextPrivate::RaiseCompositionStartEvent() { - composition_start_event_.Raise(nullptr); -} -void OsxInputMethodContextPrivate::RaiseCompositionEndEvent() { - composition_end_event_.Raise(nullptr); -} -void OsxInputMethodContextPrivate::RaiseCompositionEvent() { composition_event_.Raise(nullptr); } - -void OsxInputMethodContextPrivate::RaiseTextEvent(StringView text) { text_event_.Raise(text); } - -void OsxInputMethodContextPrivate::PerformSel(SEL sel) { - // [window_->p_->GetNSWindow() performSelector:sel]; -} - -void OsxInputMethodContextPrivate::Activate() { is_enabled_ = true; } - -void OsxInputMethodContextPrivate::Deactivate() { - input_method_context_->CompleteComposition(); - is_enabled_ = false; -} -} - -OsxInputMethodContext::OsxInputMethodContext(OsxWindow* window) - : OsxGuiResource(window->GetUiApplication()) { - p_ = std::make_unique<details::OsxInputMethodContextPrivate>(this, window); -} - -OsxInputMethodContext::~OsxInputMethodContext() {} - -void OsxInputMethodContext::EnableIME() { p_->Activate(); } - -void OsxInputMethodContext::DisableIME() { p_->Deactivate(); } - -bool OsxInputMethodContext::ShouldManuallyDrawCompositionText() { return true; } - -void OsxInputMethodContext::CompleteComposition() { - // TODO: Implement this. -} - -void OsxInputMethodContext::CancelComposition() { - [[NSTextInputContext currentInputContext] discardMarkedText]; -} - -CompositionText OsxInputMethodContext::GetCompositionText() { return p_->composition_text_; } - -void OsxInputMethodContext::SetCandidateWindowPosition(const Point& point) { - p_->SetCandidateWindowPosition(point); -} - -IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionStartEvent() { - return &p_->composition_start_event_; -} - -IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEndEvent() { - return &p_->composition_end_event_; -} - -IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEvent() { - return &p_->composition_event_; -} - -IEvent<StringView>* OsxInputMethodContext::TextEvent() { return &p_->text_event_; } - -bool OsxInputMethodContext::IsEnabled() { return p_->is_enabled_; } -} diff --git a/src/osx/gui/InputMethodPrivate.h b/src/osx/gui/InputMethodPrivate.h deleted file mode 100644 index 1df21b37..00000000 --- a/src/osx/gui/InputMethodPrivate.h +++ /dev/null @@ -1,64 +0,0 @@ -#pragma once -#include "cru/osx/gui/InputMethod.h" - -#include <AppKit/AppKit.h> - -namespace cru::platform::gui::osx { -namespace details { -class OsxInputMethodContextPrivate { - friend OsxInputMethodContext; - - public: - OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context, - OsxWindow* window); - - CRU_DELETE_COPY(OsxInputMethodContextPrivate) - CRU_DELETE_MOVE(OsxInputMethodContextPrivate) - - ~OsxInputMethodContextPrivate(); - - void SetCompositionText(CompositionText composition_text) { - composition_text_ = std::move(composition_text); - } - - void RaiseCompositionStartEvent(); - void RaiseCompositionEndEvent(); - void RaiseCompositionEvent(); - void RaiseTextEvent(StringView text); - - Point GetCandidateWindowPosition() const { return candidate_window_point_; } - void SetCandidateWindowPosition(const Point& p) { - candidate_window_point_ = p; - } - - Range GetSelectionRange() const { return selection_range_; } - void SetSelectionRange(Range selection_range) { - selection_range_ = selection_range; - } - - void PerformSel(SEL sel); - - void Activate(); - void Deactivate(); - - private: - OsxWindow* window_; - - CompositionText composition_text_; - - Range selection_range_; - - OsxInputMethodContext* input_method_context_; - - // On Osx, this is the text lefttop point on screen. - Point candidate_window_point_; - - Event<std::nullptr_t> composition_start_event_; - Event<std::nullptr_t> composition_event_; - Event<std::nullptr_t> composition_end_event_; - Event<StringView> text_event_; - - bool is_enabled_ = false; -}; -} // namespace details -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/Keyboard.mm b/src/osx/gui/Keyboard.mm deleted file mode 100644 index 3e78eecb..00000000 --- a/src/osx/gui/Keyboard.mm +++ /dev/null @@ -1,283 +0,0 @@ -#include "cru/osx/gui/Keyboard.h" - -#import <AppKit/NSText.h> -#import <Carbon/Carbon.h> -#import "KeyboardPrivate.h" - -namespace cru::platform::gui::osx { -KeyCode KeyCodeFromOsxToCru(unsigned short n) { - switch (n) { -#define CRU_DEFINE_KEYCODE_MAP(osx, cru) \ - case osx: \ - return cru; - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_0, KeyCode::N0) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_1, KeyCode::N1) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_2, KeyCode::N2) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_3, KeyCode::N3) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_4, KeyCode::N4) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_5, KeyCode::N5) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_6, KeyCode::N6) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_7, KeyCode::N7) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_8, KeyCode::N8) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_9, KeyCode::N9) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_A, KeyCode::A) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_B, KeyCode::B) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_C, KeyCode::C) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_D, KeyCode::D) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_E, KeyCode::E) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_F, KeyCode::F) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_G, KeyCode::G) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_H, KeyCode::H) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_I, KeyCode::I) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_J, KeyCode::J) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_K, KeyCode::K) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_L, KeyCode::L) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_M, KeyCode::M) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_N, KeyCode::N) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_O, KeyCode::O) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_P, KeyCode::P) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Q, KeyCode::Q) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_R, KeyCode::R) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_S, KeyCode::S) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_T, KeyCode::T) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_U, KeyCode::U) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_V, KeyCode::V) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_W, KeyCode::W) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_X, KeyCode::X) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Y, KeyCode::Y) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Z, KeyCode::Z) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Comma, KeyCode::Comma) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Period, KeyCode::Period) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Slash, KeyCode::Slash) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Semicolon, KeyCode::Semicolon) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Quote, KeyCode::Quote) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_LeftBracket, KeyCode::LeftSquareBracket) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_RightBracket, KeyCode::RightSquareBracket) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Minus, KeyCode::Minus) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Equal, KeyCode::Equal) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Backslash, KeyCode::BackSlash) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Grave, KeyCode::GraveAccent) - CRU_DEFINE_KEYCODE_MAP(kVK_Escape, KeyCode::Escape) - CRU_DEFINE_KEYCODE_MAP(kVK_Tab, KeyCode::Tab) - CRU_DEFINE_KEYCODE_MAP(kVK_CapsLock, KeyCode::CapsLock) - CRU_DEFINE_KEYCODE_MAP(kVK_Shift, KeyCode::LeftShift) - CRU_DEFINE_KEYCODE_MAP(kVK_RightShift, KeyCode::RightShift) - CRU_DEFINE_KEYCODE_MAP(kVK_Control, KeyCode::LeftCtrl) - CRU_DEFINE_KEYCODE_MAP(kVK_RightControl, KeyCode::RightCtrl) - CRU_DEFINE_KEYCODE_MAP(kVK_Option, KeyCode::LeftAlt) - CRU_DEFINE_KEYCODE_MAP(kVK_RightOption, KeyCode::RightAlt) - CRU_DEFINE_KEYCODE_MAP(kVK_Command, KeyCode::LeftCommand) - CRU_DEFINE_KEYCODE_MAP(kVK_RightCommand, KeyCode::RightCommand) - CRU_DEFINE_KEYCODE_MAP(kVK_Delete, KeyCode::Backspace) - CRU_DEFINE_KEYCODE_MAP(kVK_Return, KeyCode::Return) - CRU_DEFINE_KEYCODE_MAP(kVK_ForwardDelete, KeyCode::Delete) - CRU_DEFINE_KEYCODE_MAP(kVK_Home, KeyCode::Home) - CRU_DEFINE_KEYCODE_MAP(kVK_End, KeyCode::End) - CRU_DEFINE_KEYCODE_MAP(kVK_PageUp, KeyCode::PageUp) - CRU_DEFINE_KEYCODE_MAP(kVK_PageDown, KeyCode::PageDown) - CRU_DEFINE_KEYCODE_MAP(kVK_LeftArrow, KeyCode::Left) - CRU_DEFINE_KEYCODE_MAP(kVK_RightArrow, KeyCode::Right) - CRU_DEFINE_KEYCODE_MAP(kVK_UpArrow, KeyCode::Up) - CRU_DEFINE_KEYCODE_MAP(kVK_DownArrow, KeyCode::Down) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad0, KeyCode::NumPad0) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad1, KeyCode::NumPad1) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad2, KeyCode::NumPad2) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad3, KeyCode::NumPad3) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad4, KeyCode::NumPad4) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad5, KeyCode::NumPad5) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad6, KeyCode::NumPad6) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad7, KeyCode::NumPad7) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad8, KeyCode::NumPad8) - CRU_DEFINE_KEYCODE_MAP(kVK_ANSI_Keypad9, KeyCode::NumPad9) - CRU_DEFINE_KEYCODE_MAP(kVK_Space, KeyCode::Space) - default: - return KeyCode::Unknown; - } - -#undef CRU_DEFINE_KEYCODE_MAP -} - -unsigned short KeyCodeFromCruToOsx(KeyCode k) { - switch (k) { -#define CRU_DEFINE_KEYCODE_MAP(cru, osx) \ - case cru: \ - return osx; - CRU_DEFINE_KEYCODE_MAP(KeyCode::N0, kVK_ANSI_0) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N1, kVK_ANSI_1) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N2, kVK_ANSI_2) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N3, kVK_ANSI_3) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N4, kVK_ANSI_4) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N5, kVK_ANSI_5) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N6, kVK_ANSI_6) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N7, kVK_ANSI_7) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N8, kVK_ANSI_8) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N9, kVK_ANSI_9) - CRU_DEFINE_KEYCODE_MAP(KeyCode::A, kVK_ANSI_A) - CRU_DEFINE_KEYCODE_MAP(KeyCode::B, kVK_ANSI_B) - CRU_DEFINE_KEYCODE_MAP(KeyCode::C, kVK_ANSI_C) - CRU_DEFINE_KEYCODE_MAP(KeyCode::D, kVK_ANSI_D) - CRU_DEFINE_KEYCODE_MAP(KeyCode::E, kVK_ANSI_E) - CRU_DEFINE_KEYCODE_MAP(KeyCode::F, kVK_ANSI_F) - CRU_DEFINE_KEYCODE_MAP(KeyCode::G, kVK_ANSI_G) - CRU_DEFINE_KEYCODE_MAP(KeyCode::H, kVK_ANSI_H) - CRU_DEFINE_KEYCODE_MAP(KeyCode::I, kVK_ANSI_I) - CRU_DEFINE_KEYCODE_MAP(KeyCode::J, kVK_ANSI_J) - CRU_DEFINE_KEYCODE_MAP(KeyCode::K, kVK_ANSI_K) - CRU_DEFINE_KEYCODE_MAP(KeyCode::L, kVK_ANSI_L) - CRU_DEFINE_KEYCODE_MAP(KeyCode::M, kVK_ANSI_M) - CRU_DEFINE_KEYCODE_MAP(KeyCode::N, kVK_ANSI_N) - CRU_DEFINE_KEYCODE_MAP(KeyCode::O, kVK_ANSI_O) - CRU_DEFINE_KEYCODE_MAP(KeyCode::P, kVK_ANSI_P) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Q, kVK_ANSI_Q) - CRU_DEFINE_KEYCODE_MAP(KeyCode::R, kVK_ANSI_R) - CRU_DEFINE_KEYCODE_MAP(KeyCode::S, kVK_ANSI_S) - CRU_DEFINE_KEYCODE_MAP(KeyCode::T, kVK_ANSI_T) - CRU_DEFINE_KEYCODE_MAP(KeyCode::U, kVK_ANSI_U) - CRU_DEFINE_KEYCODE_MAP(KeyCode::V, kVK_ANSI_V) - CRU_DEFINE_KEYCODE_MAP(KeyCode::W, kVK_ANSI_W) - CRU_DEFINE_KEYCODE_MAP(KeyCode::X, kVK_ANSI_X) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Y, kVK_ANSI_Y) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Z, kVK_ANSI_Z) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Comma, kVK_ANSI_Comma) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Period, kVK_ANSI_Period) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Slash, kVK_ANSI_Slash) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Semicolon, kVK_ANSI_Semicolon) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Quote, kVK_ANSI_Quote) - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftSquareBracket, kVK_ANSI_LeftBracket) - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightSquareBracket, kVK_ANSI_RightBracket) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Minus, kVK_ANSI_Minus) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Equal, kVK_ANSI_Equal) - CRU_DEFINE_KEYCODE_MAP(KeyCode::BackSlash, kVK_ANSI_Backslash) - CRU_DEFINE_KEYCODE_MAP(KeyCode::GraveAccent, kVK_ANSI_Grave) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Escape, kVK_Escape) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Tab, kVK_Tab) - CRU_DEFINE_KEYCODE_MAP(KeyCode::CapsLock, kVK_CapsLock) - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftShift, kVK_Shift) - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightShift, kVK_RightShift) - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftCtrl, kVK_Control) - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightCtrl, kVK_RightControl) - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftAlt, kVK_Option) - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightAlt, kVK_RightOption) - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftCommand, kVK_Command) - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightCommand, kVK_RightCommand) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Backspace, kVK_Delete) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Return, kVK_Return) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Delete, kVK_ForwardDelete) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Home, kVK_Home) - CRU_DEFINE_KEYCODE_MAP(KeyCode::End, kVK_End) - CRU_DEFINE_KEYCODE_MAP(KeyCode::PageUp, kVK_PageUp) - CRU_DEFINE_KEYCODE_MAP(KeyCode::PageDown, kVK_PageDown) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Left, kVK_LeftArrow) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Right, kVK_RightArrow) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Up, kVK_UpArrow) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Down, kVK_DownArrow) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad0, kVK_ANSI_Keypad0) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad1, kVK_ANSI_Keypad1) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad2, kVK_ANSI_Keypad2) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad3, kVK_ANSI_Keypad3) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad4, kVK_ANSI_Keypad4) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad5, kVK_ANSI_Keypad5) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad6, kVK_ANSI_Keypad6) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad7, kVK_ANSI_Keypad7) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad8, kVK_ANSI_Keypad8) - CRU_DEFINE_KEYCODE_MAP(KeyCode::NumPad9, kVK_ANSI_Keypad9) - CRU_DEFINE_KEYCODE_MAP(KeyCode::Space, kVK_Space) - default: - return 0; - } -#undef CRU_DEFINE_KEYCODE_MAP -} - -NSString* ConvertKeyCodeToKeyEquivalent(KeyCode key_code) { -#define CRU_DEFINE_KEYCODE_MAP(key_code, str) \ - case key_code: \ - return str; - - switch (key_code) { - CRU_DEFINE_KEYCODE_MAP(KeyCode::A, @"a") - CRU_DEFINE_KEYCODE_MAP(KeyCode::B, @"b") - CRU_DEFINE_KEYCODE_MAP(KeyCode::C, @"c") - CRU_DEFINE_KEYCODE_MAP(KeyCode::D, @"d") - CRU_DEFINE_KEYCODE_MAP(KeyCode::E, @"e") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F, @"f") - CRU_DEFINE_KEYCODE_MAP(KeyCode::G, @"g") - CRU_DEFINE_KEYCODE_MAP(KeyCode::H, @"h") - CRU_DEFINE_KEYCODE_MAP(KeyCode::I, @"i") - CRU_DEFINE_KEYCODE_MAP(KeyCode::J, @"j") - CRU_DEFINE_KEYCODE_MAP(KeyCode::K, @"k") - CRU_DEFINE_KEYCODE_MAP(KeyCode::L, @"l") - CRU_DEFINE_KEYCODE_MAP(KeyCode::M, @"m") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N, @"n") - CRU_DEFINE_KEYCODE_MAP(KeyCode::O, @"o") - CRU_DEFINE_KEYCODE_MAP(KeyCode::P, @"p") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Q, @"q") - CRU_DEFINE_KEYCODE_MAP(KeyCode::R, @"r") - CRU_DEFINE_KEYCODE_MAP(KeyCode::S, @"s") - CRU_DEFINE_KEYCODE_MAP(KeyCode::T, @"t") - CRU_DEFINE_KEYCODE_MAP(KeyCode::U, @"u") - CRU_DEFINE_KEYCODE_MAP(KeyCode::V, @"v") - CRU_DEFINE_KEYCODE_MAP(KeyCode::W, @"w") - CRU_DEFINE_KEYCODE_MAP(KeyCode::X, @"x") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Y, @"y") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Z, @"z") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N0, @"0") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N1, @"1") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N2, @"2") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N3, @"3") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N4, @"4") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N5, @"5") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N6, @"6") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N7, @"7") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N8, @"8") - CRU_DEFINE_KEYCODE_MAP(KeyCode::N9, @"9") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F1, @"F1") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F2, @"F2") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F3, @"F3") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F4, @"F4") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F5, @"F5") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F6, @"F6") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F7, @"F7") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F8, @"F8") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F9, @"F9") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F10, @"F10") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F11, @"F11") - CRU_DEFINE_KEYCODE_MAP(KeyCode::F12, @"F12") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Minus, @"-") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Equal, @"=") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Comma, @",") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Period, @".") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Slash, @"/") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Semicolon, @";") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Quote, @"'") - CRU_DEFINE_KEYCODE_MAP(KeyCode::LeftSquareBracket, @"[") - CRU_DEFINE_KEYCODE_MAP(KeyCode::RightSquareBracket, @"]") - CRU_DEFINE_KEYCODE_MAP(KeyCode::BackSlash, @"\\") - CRU_DEFINE_KEYCODE_MAP(KeyCode::GraveAccent, @"`") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Return, @"\n") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Escape, @"\e") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Tab, @"\t") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Backspace, @"\x08") - CRU_DEFINE_KEYCODE_MAP(KeyCode::Delete, @"\x7F") - default: - throw Exception(u"Failed to convert key code to key equivalent string."); - } -#undef CRU_DEFINE_KEYCODE_MAP -} - -NSEventModifierFlags ConvertKeyModifier(KeyModifier k) { - NSEventModifierFlags flags = 0; - if (k & KeyModifiers::shift) { - flags |= NSEventModifierFlagShift; - } - if (k & KeyModifiers::ctrl) { - flags |= NSEventModifierFlagControl; - } - if (k & KeyModifiers::alt) { - flags |= NSEventModifierFlagOption; - } - if (k & KeyModifiers::command) { - flags |= NSEventModifierFlagCommand; - } - return flags; -} -} diff --git a/src/osx/gui/KeyboardPrivate.h b/src/osx/gui/KeyboardPrivate.h deleted file mode 100644 index b98ea5d4..00000000 --- a/src/osx/gui/KeyboardPrivate.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include "cru/osx/gui/Keyboard.h" - -#import <AppKit/NSEvent.h> - -namespace cru::platform::gui::osx { -NSString* ConvertKeyCodeToKeyEquivalent(KeyCode key_code); -NSEventModifierFlags ConvertKeyModifier(KeyModifier k); -} diff --git a/src/osx/gui/Menu.mm b/src/osx/gui/Menu.mm deleted file mode 100644 index 5d0fd4d5..00000000 --- a/src/osx/gui/Menu.mm +++ /dev/null @@ -1,180 +0,0 @@ -#include "cru/osx/gui/Menu.h" -#import "MenuPrivate.h" - -#include "KeyboardPrivate.h" -#include "cru/common/platform/osx/Convert.h" - -#import <AppKit/NSApplication.h> - -namespace cru::platform::gui::osx { -using platform::osx::Convert; - -namespace { -std::unique_ptr<OsxMenu> application_menu = nullptr; -} - -namespace details { -OsxMenuItemPrivate::OsxMenuItemPrivate(OsxMenuItem* d) { - d_ = d; - sub_menu_ = new OsxMenu(d->GetUiApplication()); - sub_menu_->p_->SetParentItem(d); - handler_ = [[CruOsxMenuItemClickHandler alloc] init:this]; -} - -OsxMenuItemPrivate::~OsxMenuItemPrivate() { delete sub_menu_; } - -void OsxMenuItemPrivate::AttachToNative(NSMenuItem* native_menu_item, bool check_submenu) { - Expects(sub_menu_); - - menu_item_ = native_menu_item; - [native_menu_item setTarget:handler_]; - [native_menu_item setAction:@selector(handleClick)]; - if (check_submenu && [native_menu_item hasSubmenu]) { - sub_menu_->p_->AttachToNative([native_menu_item submenu]); - } -} - -OsxMenuPrivate::OsxMenuPrivate(OsxMenu* d) { d_ = d; } - -OsxMenuPrivate::~OsxMenuPrivate() { - for (auto item : items_) { - delete item; - } -} - -void OsxMenuPrivate::AttachToNative(NSMenu* native_menu) { - menu_ = native_menu; - - auto item_count = [native_menu numberOfItems]; - for (int i = 0; i < item_count; i++) { - auto native_item = [native_menu itemAtIndex:i]; - auto item = new OsxMenuItem(d_->GetUiApplication()); - item->p_->SetParentMenu(d_); - item->p_->AttachToNative(native_item, true); - items_.push_back(item); - } -} -} - -OsxMenuItem::OsxMenuItem(IUiApplication* ui_application) : OsxGuiResource(ui_application) { - p_ = new details::OsxMenuItemPrivate(this); -} - -OsxMenuItem::~OsxMenuItem() { delete p_; } - -String OsxMenuItem::GetTitle() { return Convert((CFStringRef)[p_->menu_item_ title]); } - -void OsxMenuItem::SetTitle(String title) { [p_->menu_item_ setTitle:(NSString*)Convert(title)]; } - -bool OsxMenuItem::IsEnabled() { return [p_->menu_item_ isEnabled]; } - -void OsxMenuItem::SetEnabled(bool enabled) { [p_->menu_item_ setEnabled:enabled]; } - -IMenu* OsxMenuItem::GetParentMenu() { return p_->parent_menu_; } - -IMenu* OsxMenuItem::GetSubmenu() { return p_->sub_menu_; } - -void OsxMenuItem::SetKeyboardShortcut(KeyCode key, KeyModifier modifiers) { - [p_->menu_item_ setKeyEquivalent:ConvertKeyCodeToKeyEquivalent(key)]; - [p_->menu_item_ setKeyEquivalentModifierMask:ConvertKeyModifier(modifiers)]; -} - -void OsxMenuItem::DeleteKeyboardShortcut() { - [p_->menu_item_ setKeyEquivalent:@""]; - [p_->menu_item_ setKeyEquivalentModifierMask:0]; -} - -void OsxMenuItem::SetOnClickHandler(std::function<void()> handler) { - p_->on_click_handler_ = std::move(handler); -} - -OsxMenu* OsxMenu::CreateOrGetApplicationMenu(IUiApplication* ui_application) { - if (application_menu) { - return application_menu.get(); - } - - NSMenu* native_main_menu = [[NSMenu alloc] init]; - [NSApp setMainMenu:native_main_menu]; - [native_main_menu setAutoenablesItems:NO]; - - application_menu.reset(new OsxMenu(ui_application)); - application_menu->p_->AttachToNative(native_main_menu); - - application_menu->CreateItemAt(0); - - return application_menu.get(); -} - -OsxMenu::OsxMenu(IUiApplication* ui_application) : OsxGuiResource(ui_application) { - p_ = new details::OsxMenuPrivate(this); -} - -OsxMenu::~OsxMenu() { delete p_; } - -IMenuItem* OsxMenu::GetItemAt(int index) { - if (index < 0 || index >= p_->items_.size()) { - return nullptr; - } - - return p_->items_[index]; -} - -int OsxMenu::GetItemCount() { return p_->items_.size(); } - -IMenuItem* OsxMenu::CreateItemAt(int index) { - if (index < 0) index = 0; - if (index > p_->items_.size()) index = p_->items_.size(); - - if (p_->parent_item_ && p_->items_.empty()) { - Expects(p_->menu_ == nullptr); - p_->menu_ = [[NSMenu alloc] init]; - [p_->menu_ setAutoenablesItems:NO]; - [p_->parent_item_->p_->GetNative() setSubmenu:p_->menu_]; - } - - auto native_item = [[NSMenuItem alloc] init]; - [p_->menu_ insertItem:native_item atIndex:index]; - - auto item = new OsxMenuItem(GetUiApplication()); - item->p_->SetParentMenu(this); - item->p_->AttachToNative(native_item, false); - p_->items_.insert(p_->items_.begin() + index, item); - - return item; -} - -void OsxMenu::RemoveItemAt(int index) { - if (index < 0 || index >= p_->items_.size()) { - return; - } - - auto item = p_->items_[index]; - [p_->menu_ removeItem:item->p_->GetNative()]; - p_->items_.erase(p_->items_.begin() + index); - - delete item; - - if (p_->items_.empty() && p_->parent_item_) { - Expects(p_->menu_ != nullptr); - [p_->parent_item_->p_->GetNative() setSubmenu:nullptr]; - p_->menu_ = nullptr; - } -} -} - -@implementation CruOsxMenuItemClickHandler { - cru::platform::gui::osx::details::OsxMenuItemPrivate* p_; -} - -- (id)init:(cru::platform::gui::osx::details::OsxMenuItemPrivate*)p { - p_ = p; - return self; -} - -- (void)handleClick { - if (p_->GetOnClickHandler()) { - p_->GetOnClickHandler()(); - } -} - -@end diff --git a/src/osx/gui/MenuPrivate.h b/src/osx/gui/MenuPrivate.h deleted file mode 100644 index d5269312..00000000 --- a/src/osx/gui/MenuPrivate.h +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once -#include "cru/osx/gui/Menu.h" - -#import <AppKit/NSMenu.h> -#import <AppKit/NSMenuItem.h> - -@interface CruOsxMenuItemClickHandler : NSObject -- init:(cru::platform::gui::osx::details::OsxMenuItemPrivate*)p; -- (void)handleClick; -@end - -namespace cru::platform::gui::osx { -namespace details { - -class OsxMenuItemPrivate { - friend OsxMenuItem; - - public: - explicit OsxMenuItemPrivate(OsxMenuItem* d); - - CRU_DELETE_COPY(OsxMenuItemPrivate) - CRU_DELETE_MOVE(OsxMenuItemPrivate) - - ~OsxMenuItemPrivate(); - - public: - NSMenuItem* GetNative() { return menu_item_; } - void SetParentMenu(OsxMenu* menu) { parent_menu_ = menu; } - void AttachToNative(NSMenuItem* native_menu_item, bool check_submenu); - - const std::function<void()> GetOnClickHandler() const { return on_click_handler_; } - - private: - OsxMenuItem* d_; - OsxMenu* parent_menu_ = nullptr; - NSMenuItem* menu_item_ = nullptr; - OsxMenu* sub_menu_ = nullptr; - std::function<void()> on_click_handler_; - CruOsxMenuItemClickHandler* handler_; -}; - -class OsxMenuPrivate { - friend OsxMenu; - - public: - explicit OsxMenuPrivate(OsxMenu* d); - - CRU_DELETE_COPY(OsxMenuPrivate) - CRU_DELETE_MOVE(OsxMenuPrivate) - - ~OsxMenuPrivate(); - - public: - void SetParentItem(OsxMenuItem* item) { parent_item_ = item; } - void AttachToNative(NSMenu* native_menu); - - private: - OsxMenu* d_; - OsxMenuItem* parent_item_ = nullptr; - NSMenu* menu_ = nullptr; - std::vector<OsxMenuItem*> items_; -}; -} // namespace details - -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/Resource.cpp b/src/osx/gui/Resource.cpp deleted file mode 100644 index a6be5d75..00000000 --- a/src/osx/gui/Resource.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "cru/osx/gui/Resource.h" - -namespace cru::platform::gui::osx { -OsxGuiResource::OsxGuiResource(IUiApplication* ui_application) - : ui_application_(ui_application) {} -} // namespace cru::platform::gui::osx diff --git a/src/osx/gui/UiApplication.mm b/src/osx/gui/UiApplication.mm deleted file mode 100644 index 43c49c5c..00000000 --- a/src/osx/gui/UiApplication.mm +++ /dev/null @@ -1,260 +0,0 @@ -#include "cru/osx/gui/UiApplication.h" - -#include "ClipboardPrivate.h" -#include "cru/common/log/Logger.h" -#include "cru/common/platform/osx/Convert.h" -#include "cru/osx/graphics/quartz/Factory.h" -#include "cru/osx/gui/Clipboard.h" -#include "cru/osx/gui/Cursor.h" -#include "cru/osx/gui/Menu.h" -#include "cru/osx/gui/Window.h" -#include "cru/platform/graphics/Factory.h" -#include "cru/platform/gui/Base.h" -#include "cru/platform/gui/UiApplication.h" -#include "cru/platform/gui/Window.h" - -#include <AppKit/NSApplication.h> -#include <Foundation/NSRunLoop.h> -#include <UniformTypeIdentifiers/UTType.h> - -#include <algorithm> -#include <iterator> -#include <memory> -#include <unordered_map> -#include <vector> - -@interface CruAppDelegate : NSObject <NSApplicationDelegate> -- (id)init:(cru::platform::gui::osx::details::OsxUiApplicationPrivate*)p; -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender; -- (void)applicationWillTerminate:(NSNotification*)notification; -@end - -namespace cru::platform::gui::osx { - -using cru::platform::osx::Convert; - -namespace details { -class OsxUiApplicationPrivate { - friend OsxUiApplication; - - public: - explicit OsxUiApplicationPrivate(OsxUiApplication* osx_ui_application) - : osx_ui_application_(osx_ui_application) { - app_delegate_ = [[CruAppDelegate alloc] init:this]; - } - - CRU_DELETE_COPY(OsxUiApplicationPrivate) - CRU_DELETE_MOVE(OsxUiApplicationPrivate) - - ~OsxUiApplicationPrivate() = default; - - void CallQuitHandlers(); - - private: - OsxUiApplication* osx_ui_application_; - CruAppDelegate* app_delegate_; - std::vector<std::function<void()>> quit_handlers_; - bool quit_on_all_window_closed_ = true; - - long long current_timer_id_ = 1; - std::unordered_map<long long, std::function<void()>> next_tick_; - std::unordered_map<long long, NSTimer*> timers_; - - std::vector<OsxWindow*> windows_; - - std::unique_ptr<OsxCursorManager> cursor_manager_; - - std::unique_ptr<OsxClipboard> clipboard_; - - std::unique_ptr<platform::graphics::osx::quartz::QuartzGraphicsFactory> quartz_graphics_factory_; -}; - -void OsxUiApplicationPrivate::CallQuitHandlers() { - for (const auto& handler : quit_handlers_) { - handler(); - } -} -} - -OsxUiApplication::OsxUiApplication() - : OsxGuiResource(this), p_(new details::OsxUiApplicationPrivate(this)) { - [NSApplication sharedApplication]; - - [NSApp setDelegate:p_->app_delegate_]; - p_->quartz_graphics_factory_ = std::make_unique<graphics::osx::quartz::QuartzGraphicsFactory>(); - p_->cursor_manager_ = std::make_unique<OsxCursorManager>(this); - p_->clipboard_ = std::make_unique<OsxClipboard>( - this, std::make_unique<details::OsxClipboardPrivate>([NSPasteboard generalPasteboard])); -} - -OsxUiApplication::~OsxUiApplication() {} - -int OsxUiApplication::Run() { - [NSApp run]; - return 0; -} - -void OsxUiApplication::RequestQuit(int quit_code) { - [NSApp terminate:[NSNumber numberWithInteger:quit_code]]; -} - -void OsxUiApplication::AddOnQuitHandler(std::function<void()> handler) { - p_->quit_handlers_.push_back(std::move(handler)); -} - -bool OsxUiApplication::IsQuitOnAllWindowClosed() { return p_->quit_on_all_window_closed_; } - -void OsxUiApplication::SetQuitOnAllWindowClosed(bool quit_on_all_window_closed) { - p_->quit_on_all_window_closed_ = quit_on_all_window_closed; -} - -long long OsxUiApplication::SetImmediate(std::function<void()> action) { - const long long id = p_->current_timer_id_++; - p_->next_tick_.emplace(id, std::move(action)); - - [[NSRunLoop mainRunLoop] performBlock:^{ - const auto i = p_->next_tick_.find(id); - if (i != p_->next_tick_.cend()) { - i->second(); - } - p_->next_tick_.erase(i); - }]; - - return id; -} - -long long OsxUiApplication::SetTimeout(std::chrono::milliseconds milliseconds, - std::function<void()> action) { - long long id = p_->current_timer_id_++; - p_->timers_.emplace(id, [NSTimer scheduledTimerWithTimeInterval:milliseconds.count() / 1000.0 - repeats:false - block:^(NSTimer* timer) { - action(); - p_->timers_.erase(id); - }]); - - return id; -} - -long long OsxUiApplication::SetInterval(std::chrono::milliseconds milliseconds, - std::function<void()> action) { - long long id = p_->current_timer_id_++; - p_->timers_.emplace(id, [NSTimer scheduledTimerWithTimeInterval:milliseconds.count() / 1000.0 - repeats:true - block:^(NSTimer* timer) { - action(); - }]); - - return id; -} - -void OsxUiApplication::CancelTimer(long long id) { - p_->next_tick_.erase(id); - auto i = p_->timers_.find(id); - if (i != p_->timers_.cend()) { - [i->second invalidate]; - p_->timers_.erase(i); - } -} - -std::vector<INativeWindow*> OsxUiApplication::GetAllWindow() { - std::vector<INativeWindow*> result; - std::transform(p_->windows_.cbegin(), p_->windows_.cend(), std::back_inserter(result), - [](OsxWindow* w) { return static_cast<INativeWindow*>(w); }); - return result; -} - -INativeWindow* OsxUiApplication::CreateWindow() { - auto window = new OsxWindow(this); - p_->windows_.push_back(window); - return window; -} - -ICursorManager* OsxUiApplication::GetCursorManager() { return p_->cursor_manager_.get(); } - -IClipboard* OsxUiApplication::GetClipboard() { return p_->clipboard_.get(); } - -IMenu* OsxUiApplication::GetApplicationMenu() { return OsxMenu::CreateOrGetApplicationMenu(this); } - -graphics::IGraphicsFactory* OsxUiApplication::GetGraphicsFactory() { - return p_->quartz_graphics_factory_.get(); -} - -std::optional<String> OsxUiApplication::ShowSaveDialog(SaveDialogOptions options) { - NSSavePanel* panel = [NSSavePanel savePanel]; - [panel setTitle:(NSString*)Convert(options.title)]; - [panel setPrompt:(NSString*)Convert(options.prompt)]; - [panel setMessage:(NSString*)Convert(options.message)]; - - NSMutableArray* allowed_content_types = [NSMutableArray array]; - - for (const auto& file_type : options.allowed_file_types) { - [allowed_content_types - addObject:[UTType typeWithFilenameExtension:(NSString*)Convert(file_type)]]; - } - - [panel setAllowedContentTypes:allowed_content_types]; - [panel setAllowsOtherFileTypes:options.allow_all_file_types]; - - auto model_result = [panel runModal]; - if (model_result == NSModalResponseOK) { - return Convert((CFStringRef)[[panel URL] path]); - } else { - return std::nullopt; - } -} - -std::optional<std::vector<String>> OsxUiApplication::ShowOpenDialog(OpenDialogOptions options) { - NSOpenPanel* panel = [NSOpenPanel openPanel]; - [panel setTitle:(NSString*)Convert(options.title)]; - [panel setPrompt:(NSString*)Convert(options.prompt)]; - [panel setMessage:(NSString*)Convert(options.message)]; - - NSMutableArray* allowed_content_types = [NSMutableArray array]; - - for (const auto& file_type : options.allowed_file_types) { - [allowed_content_types - addObject:[UTType typeWithFilenameExtension:(NSString*)Convert(file_type)]]; - } - - [panel setAllowedContentTypes:allowed_content_types]; - [panel setAllowsOtherFileTypes:options.allow_all_file_types]; - - [panel setCanChooseFiles:options.can_choose_files]; - [panel setCanChooseDirectories:options.can_choose_directories]; - [panel setAllowsMultipleSelection:options.allow_mulitple_selection]; - - auto model_result = [panel runModal]; - if (model_result == NSModalResponseOK) { - std::vector<String> result; - for (NSURL* url in [panel URLs]) { - result.push_back(Convert((CFStringRef)[url path])); - } - return result; - } else { - return std::nullopt; - } -} - -void OsxUiApplication::UnregisterWindow(OsxWindow* window) { - p_->windows_.erase( - std::remove(p_->windows_.begin(), p_->windows_.end(), static_cast<INativeWindow*>(window)), - p_->windows_.cend()); -} -} - -@implementation CruAppDelegate { - cru::platform::gui::osx::details::OsxUiApplicationPrivate* _p; -} - -- (id)init:(cru::platform::gui::osx::details::OsxUiApplicationPrivate*)p { - _p = p; - return self; -} -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender { - return NSApplicationTerminateReply::NSTerminateNow; -} -- (void)applicationWillTerminate:(NSNotification*)notification { - _p->CallQuitHandlers(); -} -@end diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm deleted file mode 100644 index 8d15ef37..00000000 --- a/src/osx/gui/Window.mm +++ /dev/null @@ -1,800 +0,0 @@ -#include "cru/osx/gui/Window.h" -#include "WindowPrivate.h" - -#include "CursorPrivate.h" -#include "InputMethodPrivate.h" -#include "cru/common/Range.h" -#include "cru/common/log/Logger.h" -#include "cru/osx/Convert.h" -#include "cru/osx/graphics/quartz/Convert.h" -#include "cru/osx/graphics/quartz/Painter.h" -#include "cru/osx/gui/Cursor.h" -#include "cru/osx/gui/InputMethod.h" -#include "cru/osx/gui/Keyboard.h" -#include "cru/osx/gui/Resource.h" -#include "cru/osx/gui/UiApplication.h" -#include "cru/platform/Check.h" -#include "cru/platform/graphics/NullPainter.h" -#include "cru/platform/gui/TimerHelper.h" - -#include <AppKit/AppKit.h> -#include <Foundation/Foundation.h> - -#include <limits> -#include <memory> -#include <unordered_set> - -namespace { -constexpr int key_down_debug = 0; -} - -using cru::platform::osx::Convert; -using cru::platform::graphics::osx::quartz::Convert; - -namespace cru::platform::gui::osx { -namespace { -inline NSWindowStyleMask CalcWindowStyleMask(WindowStyleFlag flag) { - return flag & WindowStyleFlags::NoCaptionAndBorder - ? NSWindowStyleMaskBorderless - : NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | - NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable; -} -} - -namespace details { -OsxWindowPrivate::OsxWindowPrivate(OsxWindow* osx_window) : osx_window_(osx_window) { - window_delegate_ = [[CruWindowDelegate alloc] init:this]; - - content_rect_ = {100, 100, 400, 200}; - - input_method_context_ = std::make_unique<OsxInputMethodContext>(osx_window); -} - -OsxWindowPrivate::~OsxWindowPrivate() {} - -void OsxWindowPrivate::OnWindowWillClose() { - if (window_) destroy_event_.Raise(nullptr); - window_ = nil; - CGLayerRelease(draw_layer_); - draw_layer_ = nullptr; - - if (osx_window_->GetUiApplication()->IsQuitOnAllWindowClosed()) { - const auto& all_window = osx_window_->GetUiApplication()->GetAllWindow(); - - bool quit = true; - - for (auto window : all_window) { - auto w = CheckPlatform<OsxWindow>(window, osx_window_->GetPlatformId()); - if (w->p_->window_) { - quit = false; - break; - } - } - - if (quit) { - osx_window_->GetUiApplication()->RequestQuit(0); - } - } -} - -void OsxWindowPrivate::OnWindowDidExpose() { osx_window_->RequestRepaint(); } -void OsxWindowPrivate::OnWindowDidUpdate() {} -void OsxWindowPrivate::OnWindowDidMove() { content_rect_ = RetrieveContentRect(); } - -void OsxWindowPrivate::OnWindowDidResize() { - content_rect_ = RetrieveContentRect(); - - auto view = [window_ contentView]; - [view removeTrackingArea:[view trackingAreas][0]]; - auto tracking_area = [[NSTrackingArea alloc] - initWithRect:CGRectMake(0, 0, content_rect_.width, content_rect_.height) - options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways) - owner:view - userInfo:nil]; - [view addTrackingArea:tracking_area]; - - CGLayerRelease(draw_layer_); - draw_layer_ = CreateLayer(Convert(content_rect_.GetSize())); - - resize_event_.Raise(osx_window_->GetClientSize()); - - osx_window_->RequestRepaint(); -} - -void OsxWindowPrivate::OnBecomeKeyWindow() { focus_event_.Raise(FocusChangeType::Gain); } - -void OsxWindowPrivate::OnResignKeyWindow() { focus_event_.Raise(FocusChangeType::Lose); } - -void OsxWindowPrivate::OnMouseEnterLeave(MouseEnterLeaveType type) { - mouse_enter_leave_event_.Raise(type); - if (type == MouseEnterLeaveType::Enter) { - mouse_in_ = true; - UpdateCursor(); - } else { - mouse_in_ = false; - } -} - -void OsxWindowPrivate::OnMouseMove(Point p) { mouse_move_event_.Raise(TransformMousePoint(p)); } - -void OsxWindowPrivate::OnMouseDown(MouseButton button, Point p, KeyModifier key_modifier) { - mouse_down_event_.Raise({button, TransformMousePoint(p), key_modifier}); -} - -void OsxWindowPrivate::OnMouseUp(MouseButton button, Point p, KeyModifier key_modifier) { - mouse_up_event_.Raise({button, TransformMousePoint(p), key_modifier}); -} - -void OsxWindowPrivate::OnMouseWheel(float delta, Point p, KeyModifier key_modifier, - bool horizontal) { - mouse_wheel_event_.Raise({delta, TransformMousePoint(p), key_modifier, horizontal}); -} - -void OsxWindowPrivate::OnKeyDown(KeyCode key, KeyModifier key_modifier) { - key_down_event_.Raise({key, key_modifier}); -} - -void OsxWindowPrivate::OnKeyUp(KeyCode key, KeyModifier key_modifier) { - key_up_event_.Raise({key, key_modifier}); -} - -CGLayerRef OsxWindowPrivate::CreateLayer(const CGSize& size) { - auto s = size; - if (s.width == 0) s.width = 1; - if (s.height == 0) s.height = 1; - - auto draw_layer = CGLayerCreateWithContext(nullptr, s, nullptr); - Ensures(draw_layer); - - return draw_layer; -} - -void OsxWindowPrivate::UpdateCursor() { - auto cursor = cursor_ == nullptr - ? std::dynamic_pointer_cast<OsxCursor>( - osx_window_->GetUiApplication()->GetCursorManager()->GetSystemCursor( - SystemCursorType::Arrow)) - : cursor_; - - [cursor->p_->ns_cursor_ set]; -} - -Point OsxWindowPrivate::TransformMousePoint(const Point& point) { - Point r = point; - r.y = content_rect_.height - r.y; - return r; -} - -void OsxWindowPrivate::CreateWindow() { - Expects(!window_); - - NSWindowStyleMask style_mask = CalcWindowStyleMask(style_flag_); - window_ = [[CruWindow alloc] init:this - contentRect:{0, 0, content_rect_.width, content_rect_.height} - style:style_mask]; - Ensures(window_); - - osx_window_->SetClientRect(content_rect_); - - [window_ setDelegate:window_delegate_]; - - if (parent_) { - auto parent = CheckPlatform<OsxWindow>(parent_, this->osx_window_->GetPlatformId()); - [window_ setParentWindow:parent->p_->window_]; - } - - NSView* content_view = [[CruView alloc] init:this - input_context_p:input_method_context_->p_.get() - frame:Rect(Point{}, content_rect_.GetSize())]; - - [window_ setContentView:content_view]; - - auto title_str = Convert(title_); - [window_ setTitle:(NSString*)title_str]; - CFRelease(title_str); - - draw_layer_ = CreateLayer(Convert(content_rect_.GetSize())); - - create_event_.Raise(nullptr); - - osx_window_->RequestRepaint(); -} - -Size OsxWindowPrivate::GetScreenSize() { - auto screen = window_ ? [window_ screen] : [NSScreen mainScreen]; - auto size = [screen frame].size; - return Convert(size); -} - -Rect OsxWindowPrivate::RetrieveContentRect() { - NSRect rect = [NSWindow contentRectForFrameRect:[window_ frame] - styleMask:CalcWindowStyleMask(style_flag_)]; - rect.origin.y = GetScreenSize().height - rect.origin.y - rect.size.height; - return cru::platform::graphics::osx::quartz::Convert(rect); -} - -} - -OsxWindow::OsxWindow(OsxUiApplication* ui_application) - : OsxGuiResource(ui_application), p_(new details::OsxWindowPrivate(this)) {} - -OsxWindow::~OsxWindow() { - if (p_->window_) { - [p_->window_ close]; - } - dynamic_cast<OsxUiApplication*>(GetUiApplication())->UnregisterWindow(this); -} - -void OsxWindow::Close() { - if (p_->window_) { - [p_->window_ close]; - } -} - -INativeWindow* OsxWindow::GetParent() { return p_->parent_; } - -void OsxWindow::SetParent(INativeWindow* parent) { - auto p = CheckPlatform<OsxWindow>(parent, GetPlatformId()); - - p_->parent_ = parent; - - if (p_->window_) { - [p_->window_ setParentWindow:p->p_->window_]; - } -} - -WindowStyleFlag OsxWindow::GetStyleFlag() { return p_->style_flag_; } - -void OsxWindow::SetStyleFlag(WindowStyleFlag flag) { - p_->style_flag_ = flag; - - if (p_->window_) { - [p_->window_ close]; - } -} - -String OsxWindow::GetTitle() { return p_->title_; } - -void OsxWindow::SetTitle(String title) { - p_->title_ = title; - - if (p_->window_) { - auto str = Convert(title); - [p_->window_ setTitle:(NSString*)str]; - CFRelease(str); - } -} - -WindowVisibilityType OsxWindow::GetVisibility() { - if (!p_->window_) return WindowVisibilityType::Hide; - if ([p_->window_ isMiniaturized]) return WindowVisibilityType::Minimize; - return [p_->window_ isVisible] ? WindowVisibilityType::Show : WindowVisibilityType::Hide; -} - -void OsxWindow::SetVisibility(WindowVisibilityType visibility) { - if (p_->window_) { - if (visibility == WindowVisibilityType::Show) { - [p_->window_ orderFront:nil]; - p_->visibility_change_event_.Raise(WindowVisibilityType::Show); - } else if (visibility == WindowVisibilityType::Hide) { - [p_->window_ orderOut:nil]; - p_->visibility_change_event_.Raise(WindowVisibilityType::Hide); - } else if (visibility == WindowVisibilityType::Minimize) { - [p_->window_ miniaturize:nil]; - } - } else { - if (visibility == WindowVisibilityType::Show) { - p_->CreateWindow(); - [p_->window_ orderFront:nil]; - p_->visibility_change_event_.Raise(WindowVisibilityType::Show); - } - } -} - -Size OsxWindow::GetClientSize() { return p_->content_rect_.GetSize(); } - -void OsxWindow::SetClientSize(const Size& size) { - if (p_->window_) { - auto rect = GetClientRect(); - rect.SetSize(size); - SetClientRect(rect); - } else { - p_->content_rect_.SetSize(size); - } -} - -Rect OsxWindow::GetClientRect() { return p_->content_rect_; } - -void OsxWindow::SetClientRect(const Rect& rect) { - if (p_->window_) { - auto r = Convert(rect); - r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height; - r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)]; - [p_->window_ setFrame:r display:false]; - } else { - p_->content_rect_ = rect; - } -} - -Rect OsxWindow::GetWindowRect() { - auto r = Convert(p_->content_rect_); - r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height; - r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)]; - r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height; - return Convert(r); -} - -void OsxWindow::SetWindowRect(const Rect& rect) { - auto r = Convert(rect); - r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height; - r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->style_flag_)]; - r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height; - SetClientRect(Convert(r)); -} - -void OsxWindow::RequestRepaint() { - if (!p_->draw_timer_) { - p_->draw_timer_ = GetUiApplication()->SetImmediate([this] { - p_->paint_event_.Raise(nullptr); - p_->draw_timer_.Release(); - }); - } -} - -std::unique_ptr<graphics::IPainter> OsxWindow::BeginPaint() { - if (!p_->window_) { - return std::make_unique<graphics::NullPainter>(); - } - - CGContextRef cg_context = CGLayerGetContext(p_->draw_layer_); - - return std::make_unique<cru::platform::graphics::osx::quartz::QuartzCGContextPainter>( - GetUiApplication()->GetGraphicsFactory(), cg_context, false, GetClientSize(), - [this](graphics::osx::quartz::QuartzCGContextPainter*) { - [[p_->window_ contentView] setNeedsDisplay:YES]; - }); -} - -bool OsxWindow::RequestFocus() { - if (!p_->window_) return false; - [p_->window_ makeKeyWindow]; - return true; -} - -Point OsxWindow::GetMousePosition() { - auto p = [p_->window_ mouseLocationOutsideOfEventStream]; - return Point(p.x, p.y); -} - -bool OsxWindow::CaptureMouse() { return true; } - -bool OsxWindow::ReleaseMouse() { return true; } - -void OsxWindow::SetCursor(std::shared_ptr<ICursor> cursor) { - p_->cursor_ = CheckPlatform<OsxCursor>(cursor, GetPlatformId()); - p_->UpdateCursor(); -} - -void OsxWindow::SetToForeground() { - if (!p_->window_) return; - [p_->window_ makeMainWindow]; - [p_->window_ orderFrontRegardless]; -} - -IEvent<std::nullptr_t>* OsxWindow::CreateEvent() { return &p_->create_event_; } -IEvent<std::nullptr_t>* OsxWindow::DestroyEvent() { return &p_->destroy_event_; } -IEvent<std::nullptr_t>* OsxWindow::PaintEvent() { return &p_->paint_event_; } -IEvent<WindowVisibilityType>* OsxWindow::VisibilityChangeEvent() { - return &p_->visibility_change_event_; -} -IEvent<Size>* OsxWindow::ResizeEvent() { return &p_->resize_event_; } -IEvent<FocusChangeType>* OsxWindow::FocusEvent() { return &p_->focus_event_; } -IEvent<MouseEnterLeaveType>* OsxWindow::MouseEnterLeaveEvent() { - return &p_->mouse_enter_leave_event_; -} -IEvent<Point>* OsxWindow::MouseMoveEvent() { return &p_->mouse_move_event_; } -IEvent<NativeMouseButtonEventArgs>* OsxWindow::MouseDownEvent() { return &p_->mouse_down_event_; } -IEvent<NativeMouseButtonEventArgs>* OsxWindow::MouseUpEvent() { return &p_->mouse_up_event_; } -IEvent<NativeMouseWheelEventArgs>* OsxWindow::MouseWheelEvent() { return &p_->mouse_wheel_event_; } -IEvent<NativeKeyEventArgs>* OsxWindow::KeyDownEvent() { return &p_->key_down_event_; } -IEvent<NativeKeyEventArgs>* OsxWindow::KeyUpEvent() { return &p_->key_up_event_; } - -IInputMethodContext* OsxWindow::GetInputMethodContext() { return p_->input_method_context_.get(); } -} - -namespace { -cru::platform::gui::KeyModifier GetKeyModifier(NSEvent* event) { - cru::platform::gui::KeyModifier key_modifier; - if (event.modifierFlags & NSEventModifierFlagControl) - key_modifier |= cru::platform::gui::KeyModifiers::ctrl; - if (event.modifierFlags & NSEventModifierFlagOption) - key_modifier |= cru::platform::gui::KeyModifiers::alt; - if (event.modifierFlags & NSEventModifierFlagShift) - key_modifier |= cru::platform::gui::KeyModifiers::shift; - if (event.modifierFlags & NSEventModifierFlagCommand) - key_modifier |= cru::platform::gui::KeyModifiers::command; - return key_modifier; -} -} - -@implementation CruWindow { - cru::platform::gui::osx::details::OsxWindowPrivate* _p; -} - -- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p - contentRect:(NSRect)contentRect - style:(NSWindowStyleMask)style { - [super initWithContentRect:contentRect - styleMask:style - backing:NSBackingStoreBuffered - defer:false]; - _p = p; - - [self setAcceptsMouseMovedEvents:YES]; - - return self; -} - -- (BOOL)canBecomeMainWindow { - return YES; -} - -- (BOOL)canBecomeKeyWindow { - return YES; -} -@end - -@implementation CruView { - cru::platform::gui::osx::details::OsxWindowPrivate* _p; - cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _input_context_p; - NSMutableAttributedString* _input_context_text; -} - -- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p - input_context_p: - (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p - frame:(cru::platform::Rect)frame { - [super initWithFrame:cru::platform::graphics::osx::quartz::Convert(frame)]; - _p = p; - _input_context_p = input_context_p; - - auto tracking_area = [[NSTrackingArea alloc] - initWithRect:Convert(frame) - options:(NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways) - owner:self - userInfo:nil]; - [self addTrackingArea:tracking_area]; - - return self; -} - -- (void)drawRect:(NSRect)dirtyRect { - auto cg_context = [[NSGraphicsContext currentContext] CGContext]; - auto layer = _p->GetDrawLayer(); - Ensures(layer); - CGContextDrawLayerAtPoint(cg_context, CGPointMake(0, 0), layer); -} - -- (BOOL)acceptsFirstResponder { - return YES; -} - -- (BOOL)canBecomeKeyView { - return YES; -} - -- (void)mouseMoved:(NSEvent*)event { - _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y)); -} - -- (void)mouseDragged:(NSEvent*)event { - _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y)); -} - -- (void)rightMouseDragged:(NSEvent*)event { - _p->OnMouseMove(cru::platform::Point(event.locationInWindow.x, event.locationInWindow.y)); -} - -- (void)mouseEntered:(NSEvent*)event { - _p->OnMouseEnterLeave(cru::platform::gui::MouseEnterLeaveType::Enter); -} - -- (void)mouseExited:(NSEvent*)event { - _p->OnMouseEnterLeave(cru::platform::gui::MouseEnterLeaveType::Leave); -} - -- (void)mouseDown:(NSEvent*)event { - [[self window] makeKeyWindow]; - - auto key_modifier = GetKeyModifier(event); - cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y); - - _p->OnMouseDown(cru::platform::gui::mouse_buttons::left, p, key_modifier); -} - -- (void)mouseUp:(NSEvent*)event { - auto key_modifier = GetKeyModifier(event); - cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y); - - _p->OnMouseUp(cru::platform::gui::mouse_buttons::left, p, key_modifier); -} - -- (void)rightMouseDown:(NSEvent*)event { - auto key_modifier = GetKeyModifier(event); - cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y); - - _p->OnMouseDown(cru::platform::gui::mouse_buttons::right, p, key_modifier); -} - -- (void)rightMouseUp:(NSEvent*)event { - auto key_modifier = GetKeyModifier(event); - cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y); - - _p->OnMouseUp(cru::platform::gui::mouse_buttons::right, p, key_modifier); -} - -- (void)scrollWheel:(NSEvent*)event { - auto key_modifier = GetKeyModifier(event); - cru::platform::Point p(event.locationInWindow.x, event.locationInWindow.y); - - if (event.scrollingDeltaY) { - _p->OnMouseWheel(static_cast<float>(event.scrollingDeltaY), p, key_modifier, false); - } - - if (event.scrollingDeltaX) { - _p->OnMouseWheel(static_cast<float>(event.scrollingDeltaX), p, key_modifier, true); - } -} - -namespace { -using cru::platform::gui::KeyCode; -const std::unordered_set<KeyCode> input_context_handle_codes{ - KeyCode::A, - KeyCode::B, - KeyCode::C, - KeyCode::D, - KeyCode::E, - KeyCode::F, - KeyCode::G, - KeyCode::H, - KeyCode::I, - KeyCode::J, - KeyCode::K, - KeyCode::L, - KeyCode::M, - KeyCode::N, - KeyCode::O, - KeyCode::P, - KeyCode::Q, - KeyCode::R, - KeyCode::S, - KeyCode::T, - KeyCode::U, - KeyCode::V, - KeyCode::W, - KeyCode::X, - KeyCode::Y, - KeyCode::Z, - KeyCode::N0, - KeyCode::N1, - KeyCode::N2, - KeyCode::N3, - KeyCode::N4, - KeyCode::N5, - KeyCode::N6, - KeyCode::N7, - KeyCode::N8, - KeyCode::N9, - KeyCode::Comma, - KeyCode::Period, - KeyCode::Slash, - KeyCode::Semicolon, - KeyCode::Quote, - KeyCode::LeftSquareBracket, - KeyCode::RightSquareBracket, - KeyCode::BackSlash, - KeyCode::Minus, - KeyCode::Equal, - KeyCode::GraveAccent, -}; -} - -const std::unordered_set<KeyCode> input_context_handle_codes_when_has_text{ - KeyCode::Backspace, KeyCode::Space, KeyCode::Return, KeyCode::Left, - KeyCode::Right, KeyCode::Up, KeyCode::Down}; - -- (void)keyDown:(NSEvent*)event { - auto key_modifier = GetKeyModifier(event); - - bool handled = false; - - auto input_context = dynamic_cast<cru::platform::gui::osx::OsxInputMethodContext*>( - _p->GetWindow()->GetInputMethodContext()); - Ensures(input_context); - - auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode); - - if (input_context->IsEnabled()) { - if (input_context_handle_codes.count(c) && - !(key_modifier & ~cru::platform::gui::KeyModifiers::shift)) { - handled = [[self inputContext] handleEvent:event]; - } else if (input_context_handle_codes_when_has_text.count(c) && !key_modifier) { - if (!input_context->GetCompositionText().text.empty()) { - handled = [[self inputContext] handleEvent:event]; - } else { - if (c == KeyCode::Return) { - _input_context_p->RaiseTextEvent(u"\n"); - handled = true; - } else if (c == KeyCode::Space) { - _input_context_p->RaiseTextEvent(u" "); - handled = true; - } - } - } - } - - if (!handled) { - _p->OnKeyDown(c, key_modifier); - } -} - -- (void)keyUp:(NSEvent*)event { - // cru::CRU_LOG_DEBUG(u"CruView", u"Recieved key up."); - - auto key_modifier = GetKeyModifier(event); - auto c = cru::platform::gui::osx::KeyCodeFromOsxToCru(event.keyCode); - - _p->OnKeyUp(c, key_modifier); -} - -- (BOOL)hasMarkedText { - return _input_context_text != nil; -} - -- (NSRange)markedRange { - return _input_context_text == nil ? NSRange{NSNotFound, 0} - : NSRange{0, [_input_context_text length]}; -} - -- (NSRange)selectedRange { - return NSMakeRange(_input_context_p->GetSelectionRange().position, - _input_context_p->GetSelectionRange().count); -} - -- (void)setMarkedText:(id)string - selectedRange:(NSRange)selectedRange - replacementRange:(NSRange)replacementRange { - CFStringRef s; - if ([string isKindOfClass:[NSString class]]) { - s = (CFStringRef)string; - } else { - auto as = (CFAttributedStringRef)string; - s = CFAttributedStringGetString(as); - } - - auto ss = Convert(s); - - // cru::CRU_LOG_DEBUG(u"CruView", - // u"Received setMarkedText string: {}, selected range: ({}, {}), " - // u"replacement range: ({}, {}).", - // ss, selectedRange.location, selectedRange.length, replacementRange.location, - // replacementRange.length); - - if (_input_context_text == nil) { - _input_context_text = [[NSMutableAttributedString alloc] init]; - _input_context_p->RaiseCompositionStartEvent(); - } - - if (replacementRange.location == NSNotFound) replacementRange.location = 0; - - [_input_context_text - replaceCharactersInRange:NSMakeRange(0, [_input_context_text length]) - withAttributedString:[[NSAttributedString alloc] initWithString:(NSString*)s]]; - - cru::platform::gui::CompositionText composition_text; - composition_text.text = Convert((CFStringRef)[_input_context_text string]); - composition_text.selection.position = ss.IndexFromCodePointToCodeUnit(selectedRange.location); - composition_text.selection.count = - ss.IndexFromCodePointToCodeUnit(selectedRange.location + selectedRange.length) - - composition_text.selection.position; - _input_context_p->SetCompositionText(composition_text); - _input_context_p->RaiseCompositionEvent(); -} - -- (void)unmarkText { - _input_context_text = nil; - _input_context_p->RaiseCompositionEndEvent(); -} - -- (NSArray<NSAttributedStringKey>*)validAttributesForMarkedText { - return @[ - (NSString*)kCTUnderlineColorAttributeName, (NSString*)kCTUnderlineStyleAttributeName, - (NSString*)kCTForegroundColorAttributeName, (NSString*)kCTBackgroundColorAttributeName - ]; -} - -- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range - actualRange:(NSRangePointer)actualRange { - cru::Range r(range.location, range.length); - - r = r.CoerceInto(0, [_input_context_text length]); - - return [_input_context_text attributedSubstringFromRange:NSMakeRange(r.position, r.count)]; -} - -- (void)insertText:(id)string replacementRange:(NSRange)replacementRange { - CFStringRef s; - if ([string isKindOfClass:[NSString class]]) { - s = (CFStringRef)string; - } else { - auto as = (CFAttributedStringRef)string; - s = CFAttributedStringGetString(as); - } - - _input_context_text = nil; - _input_context_p->SetCompositionText(cru::platform::gui::CompositionText()); - cru::String ss = Convert(s); - - // cru::CRU_LOG_DEBUG(u"CruView", u"Finish composition: {}, replacement range: ({}, {})", ss, - // replacementRange.location, replacementRange.length); - - _input_context_p->RaiseCompositionEvent(); - _input_context_p->RaiseCompositionEndEvent(); - _input_context_p->RaiseTextEvent(ss); -} - -- (NSUInteger)characterIndexForPoint:(NSPoint)point { - return NSNotFound; -} - -- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(NSRangePointer)actualRange { - NSRect result; - result.origin.x = _input_context_p->GetCandidateWindowPosition().x; - result.origin.y = _input_context_p->GetCandidateWindowPosition().y; - result.size.height = 16; - result.size.width = 0; - return result; -} - -- (void)doCommandBySelector:(SEL)selector { - _input_context_p->PerformSel(selector); -} -@end - -@implementation CruWindowDelegate { - cru::platform::gui::osx::details::OsxWindowPrivate* _p; -} - -- (id)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p { - _p = p; - return self; -} - -- (void)windowWillClose:(NSNotification*)notification { - _p->OnWindowWillClose(); -} - -- (void)windowDidExpose:(NSNotification*)notification { - _p->OnWindowDidExpose(); -} - -- (void)windowDidUpdate:(NSNotification*)notification { - _p->OnWindowDidUpdate(); -} - -- (void)windowDidMove:(NSNotification*)notification { - _p->OnWindowDidMove(); -} - -- (void)windowDidResize:(NSNotification*)notification { - _p->OnWindowDidResize(); -} - -- (void)windowDidBecomeKey:(NSNotification*)notification { - _p->OnBecomeKeyWindow(); -} - -- (void)windowDidResignKey:(NSNotification*)notification { - _p->OnResignKeyWindow(); -} -@end diff --git a/src/osx/gui/WindowPrivate.h b/src/osx/gui/WindowPrivate.h deleted file mode 100644 index cdd34246..00000000 --- a/src/osx/gui/WindowPrivate.h +++ /dev/null @@ -1,118 +0,0 @@ -#pragma once -#include "cru/osx/gui/Window.h" - -#include "cru/common/Event.h" -#include "cru/osx/gui/Cursor.h" -#include "cru/platform/gui/TimerHelper.h" -#include "cru/platform/gui/Window.h" - -#import <AppKit/AppKit.h> - -@interface CruWindowDelegate : NSObject <NSWindowDelegate> -- (id)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p; -@end - -@interface CruWindow : NSWindow -- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p - contentRect:(NSRect)contentRect - style:(NSWindowStyleMask)style; -@end - -@interface CruView : NSView <NSTextInputClient> -- (instancetype)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p - input_context_p: - (cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)input_context_p - frame:(cru::platform::Rect)frame; -@end - -namespace cru::platform::gui::osx { - -namespace details { -class OsxInputMethodContextPrivate; - -class OsxWindowPrivate { - friend OsxWindow; - friend OsxInputMethodContextPrivate; - - public: - explicit OsxWindowPrivate(OsxWindow* osx_window); - - CRU_DELETE_COPY(OsxWindowPrivate) - CRU_DELETE_MOVE(OsxWindowPrivate) - - ~OsxWindowPrivate(); - - public: - void OnMouseEnterLeave(MouseEnterLeaveType type); - void OnMouseMove(Point p); - void OnMouseDown(MouseButton button, Point p, KeyModifier key_modifier); - void OnMouseUp(MouseButton button, Point p, KeyModifier key_modifier); - void OnMouseWheel(float delta, Point p, KeyModifier key_modifier, bool horizontal); - void OnKeyDown(KeyCode key, KeyModifier key_modifier); - void OnKeyUp(KeyCode key, KeyModifier key_modifier); - - void OnWindowWillClose(); - void OnWindowDidExpose(); - void OnWindowDidUpdate(); - void OnWindowDidMove(); - void OnWindowDidResize(); - void OnBecomeKeyWindow(); - void OnResignKeyWindow(); - - CGLayerRef GetDrawLayer() { return draw_layer_; } - - OsxWindow* GetWindow() { return osx_window_; } - NSWindow* GetNSWindow() { return window_; } - - private: - Size GetScreenSize(); - - void CreateWindow(); - - void UpdateCursor(); - - Point TransformMousePoint(const Point& point); - - CGLayerRef CreateLayer(const CGSize& size); - - Rect RetrieveContentRect(); - - private: - OsxWindow* osx_window_; - - INativeWindow* parent_ = nullptr; - WindowStyleFlag style_flag_ = WindowStyleFlag{}; - - String title_; - - Rect content_rect_; - - NSWindow* window_ = nil; - CruWindowDelegate* window_delegate_ = nil; - - CGLayerRef draw_layer_ = nullptr; - - bool mouse_in_ = false; - - std::shared_ptr<OsxCursor> cursor_ = nullptr; - - std::unique_ptr<OsxInputMethodContext> input_method_context_; - - TimerAutoCanceler draw_timer_; - - Event<std::nullptr_t> create_event_; - Event<std::nullptr_t> destroy_event_; - Event<std::nullptr_t> paint_event_; - Event<WindowVisibilityType> visibility_change_event_; - Event<Size> resize_event_; - Event<FocusChangeType> focus_event_; - Event<MouseEnterLeaveType> mouse_enter_leave_event_; - Event<Point> mouse_move_event_; - Event<NativeMouseButtonEventArgs> mouse_down_event_; - Event<NativeMouseButtonEventArgs> mouse_up_event_; - Event<NativeMouseWheelEventArgs> mouse_wheel_event_; - Event<NativeKeyEventArgs> key_down_event_; - Event<NativeKeyEventArgs> key_up_event_; -}; -} // namespace details -} // namespace cru::platform::gui::osx |