aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-10-15 20:35:17 +0800
committercrupest <crupest@outlook.com>2021-10-15 20:35:17 +0800
commited368423531b24e8735db0afe38c7486145caa56 (patch)
tree2a88be9ce9062ac3c7e5c4ceb496d687102815ec
parentd3e2a751353e6c5b0e4d7c0a2af1cdbc09d3ea95 (diff)
downloadcru-ed368423531b24e8735db0afe38c7486145caa56.tar.gz
cru-ed368423531b24e8735db0afe38c7486145caa56.tar.bz2
cru-ed368423531b24e8735db0afe38c7486145caa56.zip
...
-rw-r--r--demos/CMakeLists.txt8
-rw-r--r--demos/input_method/main.cpp23
-rw-r--r--include/cru/common/String.hpp144
-rw-r--r--include/cru/osx/gui/Cursor.hpp43
-rw-r--r--include/cru/osx/gui/Window.hpp2
-rw-r--r--include/cru/platform/bootstrap/Bootstrap.hpp2
-rw-r--r--src/common/String.cpp2
-rw-r--r--src/osx/gui/CMakeLists.txt3
-rw-r--r--src/osx/gui/Cursor.mm93
-rw-r--r--src/osx/gui/CursorPrivate.h29
-rw-r--r--src/osx/gui/UiApplication.mm16
-rw-r--r--src/osx/gui/Window.mm102
-rw-r--r--src/platform/CMakeLists.txt2
-rw-r--r--src/platform/bootstrap/Bootstrap.cpp8
-rw-r--r--src/platform/bootstrap/CMakeLists.txt10
15 files changed, 375 insertions, 112 deletions
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt
index f975a6e9..1a86c69f 100644
--- a/demos/CMakeLists.txt
+++ b/demos/CMakeLists.txt
@@ -1,14 +1,14 @@
add_library(cru_demo_base INTERFACE)
-target_link_libraries(cru_demo_base INTERFACE cru_platform_boostrap)
+target_link_libraries(cru_demo_base INTERFACE cru_platform_bootstrap)
if(WIN32) # Currently only enable tests on Windows.
add_subdirectory(main)
add_subdirectory(scroll_view)
add_subdirectory(input_method)
-endif()
-
-if(UNIX AND NOT APPLE)
+elseif(APPLE)
+ add_subdirectory(input_method)
+elseif(UNIX)
add_subdirectory(xcb)
endif()
diff --git a/demos/input_method/main.cpp b/demos/input_method/main.cpp
index b509cd97..7c22783c 100644
--- a/demos/input_method/main.cpp
+++ b/demos/input_method/main.cpp
@@ -7,41 +7,42 @@
#include "cru/platform/gui/Window.hpp"
int main() {
+ using namespace cru;
using namespace cru::platform;
using namespace cru::platform::graphics;
using namespace cru::platform::gui;
- IUiApplication* application = boostrap::CreateUiApplication();
+ IUiApplication* application = bootstrap::CreateUiApplication();
- auto graph_factory = application->GetGraphFactory();
+ auto graphics_factory = application->GetGraphicsFactory();
auto window = application->CreateWindow(nullptr);
auto input_method_context = window->GetInputMethodContext();
- auto brush = graph_factory->CreateSolidColorBrush();
+ auto brush = graphics_factory->CreateSolidColorBrush();
brush->SetColor(colors::black);
- auto odd_clause_brush = graph_factory->CreateSolidColorBrush();
+ auto odd_clause_brush = graphics_factory->CreateSolidColorBrush();
odd_clause_brush->SetColor(colors::yellow);
- auto even_clause_brush = graph_factory->CreateSolidColorBrush();
+ auto even_clause_brush = graphics_factory->CreateSolidColorBrush();
even_clause_brush->SetColor(colors::green);
- auto target_clause_brush = graph_factory->CreateSolidColorBrush();
+ auto target_clause_brush = graphics_factory->CreateSolidColorBrush();
target_clause_brush->SetColor(colors::blue);
- std::shared_ptr<IFont> font = graph_factory->CreateFont(u"等线", 30);
+ std::shared_ptr<IFont> font = graphics_factory->CreateFont(u"等线", 30);
float window_width = 10000;
auto prompt_text_layout =
- graph_factory->CreateTextLayout(font,
+ graphics_factory->CreateTextLayout(font,
u"Alt+F1: Enable IME\n"
u"Alt+F2: Disable IME\n"
u"Alt+F3: Complete composition.\n"
u"Alt+F4: Cancel composition.");
std::optional<CompositionText> optional_composition_text;
- std::u16string committed_text;
+ String committed_text;
window->ResizeEvent()->AddHandler(
[&prompt_text_layout, &window_width](const Size& size) {
@@ -57,7 +58,7 @@ int main() {
const auto anchor_y = prompt_text_layout->GetTextBounds().height;
- auto text_layout = graph_factory->CreateTextLayout(
+ auto text_layout = graphics_factory->CreateTextLayout(
font, committed_text + (optional_composition_text
? optional_composition_text->text
: u""));
@@ -121,7 +122,7 @@ int main() {
});
input_method_context->TextEvent()->AddHandler(
- [window, &committed_text](const std::u16string_view& c) {
+ [window, &committed_text](const StringView& c) {
committed_text += c;
window->RequestRepaint();
});
diff --git a/include/cru/common/String.hpp b/include/cru/common/String.hpp
index 0530c208..13176fc6 100644
--- a/include/cru/common/String.hpp
+++ b/include/cru/common/String.hpp
@@ -71,7 +71,7 @@ class CRU_BASE_API String {
template <Index size>
String(const char16_t (&str)[size])
- : String(reinterpret_cast<const_pointer>(str), size) {}
+ : String(reinterpret_cast<const_pointer>(str), size - 1) {}
template <typename Iter>
String(Iter start, Iter end) {
@@ -164,7 +164,7 @@ class CRU_BASE_API String {
inline void append(StringView str);
public:
- String& operator+=(const String& other);
+ String& operator+=(StringView other);
public:
Utf16CodePointIterator CodePointIterator() const {
@@ -199,6 +199,76 @@ class CRU_BASE_API String {
Index capacity_ = 0; // always 1 smaller than real buffer size
};
+class CRU_BASE_API StringView {
+ public:
+ using value_type = char16_t;
+ using size_type = Index;
+ using difference_type = Index;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using pointer = value_type*;
+ using const_pointer = const value_type*;
+ using iterator = const value_type*;
+ using const_iterator = const value_type*;
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+ StringView() = default;
+
+ constexpr StringView(const_pointer ptr, Index size)
+ : ptr_(ptr), size_(size) {}
+
+ template <Index size>
+ constexpr StringView(const value_type (&array)[size])
+ : StringView(array, size - 1) {}
+
+ StringView(const String& str) : StringView(str.data(), str.size()) {}
+
+ CRU_DEFAULT_COPY(StringView)
+ CRU_DEFAULT_MOVE(StringView)
+
+ ~StringView() = default;
+
+ Index size() const { return size_; }
+ const value_type* data() const { return ptr_; }
+
+ public:
+ iterator begin() { return this->ptr_; }
+ const_iterator begin() const { return this->ptr_; }
+ const_iterator cbegin() const { return this->ptr_; }
+
+ iterator end() { return this->ptr_ + this->size_; }
+ const_iterator end() const { return this->ptr_ + this->size_; }
+ const_iterator cend() const { return this->ptr_ + this->size_; }
+
+ reverse_iterator rbegin() { return reverse_iterator{begin()}; }
+ const_reverse_iterator rbegin() const {
+ return const_reverse_iterator{begin()};
+ }
+ const_reverse_iterator crbegin() const {
+ return const_reverse_iterator{cbegin()};
+ }
+
+ reverse_iterator rend() { return reverse_iterator{end()}; }
+ const_reverse_iterator rend() const { return const_reverse_iterator{end()}; }
+ const_reverse_iterator crend() const {
+ return const_reverse_iterator{cend()};
+ }
+
+ StringView substr(Index pos);
+ StringView substr(Index pos, Index size);
+
+ int Compare(const StringView& other) const;
+
+ String ToString() const { return String(ptr_, size_); }
+
+ value_type operator[](Index index) const { return ptr_[index]; }
+
+ private:
+ const char16_t* ptr_;
+ Index size_;
+};
+
CRU_DEFINE_COMPARE_OPERATORS(String)
inline String operator+(const String& left, const String& right) {
@@ -285,76 +355,6 @@ String String::Format(T&&... args) const {
return cru::Format(*this, std::forward<T>(args)...);
}
-class CRU_BASE_API StringView {
- public:
- using value_type = char16_t;
- using size_type = Index;
- using difference_type = Index;
- using reference = value_type&;
- using const_reference = const value_type&;
- using pointer = value_type*;
- using const_pointer = const value_type*;
- using iterator = const value_type*;
- using const_iterator = const value_type*;
- using reverse_iterator = std::reverse_iterator<iterator>;
- using const_reverse_iterator = std::reverse_iterator<const_iterator>;
-
- StringView() = default;
-
- constexpr StringView(const_pointer ptr, Index size)
- : ptr_(ptr), size_(size) {}
-
- template <Index size>
- constexpr StringView(const value_type (&array)[size])
- : StringView(array, size) {}
-
- StringView(const String& str) : StringView(str.data(), str.size()) {}
-
- CRU_DEFAULT_COPY(StringView)
- CRU_DEFAULT_MOVE(StringView)
-
- ~StringView() = default;
-
- Index size() const { return size_; }
- const value_type* data() const { return ptr_; }
-
- public:
- iterator begin() { return this->ptr_; }
- const_iterator begin() const { return this->ptr_; }
- const_iterator cbegin() const { return this->ptr_; }
-
- iterator end() { return this->ptr_ + this->size_; }
- const_iterator end() const { return this->ptr_ + this->size_; }
- const_iterator cend() const { return this->ptr_ + this->size_; }
-
- reverse_iterator rbegin() { return reverse_iterator{begin()}; }
- const_reverse_iterator rbegin() const {
- return const_reverse_iterator{begin()};
- }
- const_reverse_iterator crbegin() const {
- return const_reverse_iterator{cbegin()};
- }
-
- reverse_iterator rend() { return reverse_iterator{end()}; }
- const_reverse_iterator rend() const { return const_reverse_iterator{end()}; }
- const_reverse_iterator crend() const {
- return const_reverse_iterator{cend()};
- }
-
- StringView substr(Index pos);
- StringView substr(Index pos, Index size);
-
- int Compare(const StringView& other) const;
-
- String ToString() const { return String(ptr_, size_); }
-
- value_type operator[](Index index) const { return ptr_[index]; }
-
- private:
- const char16_t* ptr_;
- Index size_;
-};
-
CRU_DEFINE_COMPARE_OPERATORS(StringView)
inline String::iterator String::insert(const_iterator pos, StringView str) {
diff --git a/include/cru/osx/gui/Cursor.hpp b/include/cru/osx/gui/Cursor.hpp
new file mode 100644
index 00000000..497f5853
--- /dev/null
+++ b/include/cru/osx/gui/Cursor.hpp
@@ -0,0 +1,43 @@
+#pragma once
+#include "Resource.hpp"
+#include "cru/platform/gui/Cursor.hpp"
+
+#include <memory>
+
+namespace cru::platform::gui::osx {
+namespace details {
+class OsxWindowPrivate;
+class OsxCursorPrivate;
+class OsxCursorManagerPrivate;
+} // namespace details
+
+class OsxCursor : public OsxGuiResource, public virtual ICursor {
+ friend class OsxWindow;
+ friend class details::OsxWindowPrivate;
+
+ public:
+ OsxCursor(IUiApplication* ui_application, SystemCursorType cursor_type);
+ CRU_DELETE_COPY(OsxCursor)
+ CRU_DELETE_MOVE(OsxCursor)
+
+ ~OsxCursor() override;
+
+ private:
+ std::unique_ptr<details::OsxCursorPrivate> p_;
+};
+
+class OsxCursorManager : public OsxGuiResource, public virtual ICursorManager {
+ public:
+ explicit OsxCursorManager(IUiApplication* ui_application);
+
+ CRU_DELETE_COPY(OsxCursorManager)
+ CRU_DELETE_MOVE(OsxCursorManager)
+
+ ~OsxCursorManager() override;
+
+ std::shared_ptr<ICursor> GetSystemCursor(SystemCursorType type) override;
+
+ private:
+ std::unique_ptr<details::OsxCursorManagerPrivate> p_;
+};
+} // namespace cru::platform::gui::osx
diff --git a/include/cru/osx/gui/Window.hpp b/include/cru/osx/gui/Window.hpp
index 56ae83e6..710246bc 100644
--- a/include/cru/osx/gui/Window.hpp
+++ b/include/cru/osx/gui/Window.hpp
@@ -133,6 +133,6 @@ class OsxInputMethodContext : public OsxGuiResource,
IEvent<StringView>* TextEvent() override;
private:
- details::OsxInputMethodContextPrivate* p_;
+ std::unique_ptr<details::OsxInputMethodContextPrivate> p_;
};
} // namespace cru::platform::gui::osx
diff --git a/include/cru/platform/bootstrap/Bootstrap.hpp b/include/cru/platform/bootstrap/Bootstrap.hpp
index 730df28c..33fb5122 100644
--- a/include/cru/platform/bootstrap/Bootstrap.hpp
+++ b/include/cru/platform/bootstrap/Bootstrap.hpp
@@ -11,7 +11,7 @@
#define CRU_PLATFORM_BOOTSTRAP_API
#endif
-namespace cru::platform::boostrap {
+namespace cru::platform::bootstrap {
CRU_PLATFORM_BOOTSTRAP_API cru::platform::gui::IUiApplication*
CreateUiApplication();
}
diff --git a/src/common/String.cpp b/src/common/String.cpp
index ef5eb176..30f83174 100644
--- a/src/common/String.cpp
+++ b/src/common/String.cpp
@@ -243,7 +243,7 @@ Range String::RangeFromCodePointToCodeUnit(Range code_point_range) const {
IndexFromCodePointToCodeUnit(code_point_range.GetEnd()));
}
-String& String::operator+=(const String& other) {
+String& String::operator+=(StringView other) {
append(other);
return *this;
}
diff --git a/src/osx/gui/CMakeLists.txt b/src/osx/gui/CMakeLists.txt
index 27546fc2..e2647165 100644
--- a/src/osx/gui/CMakeLists.txt
+++ b/src/osx/gui/CMakeLists.txt
@@ -1,10 +1,13 @@
set(CRU_OSX_GUI_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/osx/gui)
add_library(cru_osx_gui SHARED
+ Cursor.mm
Keyboard.mm
Resource.cpp
UiApplication.mm
Window.mm
+
+ CursorPrivate.h
)
target_sources(cru_osx_gui PUBLIC
diff --git a/src/osx/gui/Cursor.mm b/src/osx/gui/Cursor.mm
new file mode 100644
index 00000000..30b0f0fd
--- /dev/null
+++ b/src/osx/gui/Cursor.mm
@@ -0,0 +1,93 @@
+#include "cru/osx/gui/Cursor.hpp"
+#include "CursorPrivate.h"
+
+#include "cru/osx/Exception.hpp"
+#include "cru/osx/gui/Resource.hpp"
+#include "cru/platform/gui/Cursor.hpp"
+#include "cru/platform/gui/UiApplication.hpp"
+
+#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
new file mode 100644
index 00000000..5daf09f7
--- /dev/null
+++ b/src/osx/gui/CursorPrivate.h
@@ -0,0 +1,29 @@
+#pragma once
+#include "cru/osx/gui/Cursor.hpp"
+
+#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/UiApplication.mm b/src/osx/gui/UiApplication.mm
index d2e6fe30..4ac3d1df 100644
--- a/src/osx/gui/UiApplication.mm
+++ b/src/osx/gui/UiApplication.mm
@@ -1,7 +1,9 @@
#include "cru/osx/gui/UiApplication.hpp"
#include "cru/osx/graphics/quartz/Factory.hpp"
+#include "cru/osx/gui/Cursor.hpp"
#include "cru/osx/gui/Window.hpp"
+#include "cru/platform/graphics/Factory.hpp"
#include "cru/platform/gui/UiApplication.hpp"
#include "cru/platform/gui/Window.hpp"
@@ -50,6 +52,8 @@ class OsxUiApplicationPrivate {
std::vector<OsxWindow*> windows_;
+ std::unique_ptr<OsxCursorManager> cursor_manager_;
+
std::unique_ptr<platform::graphics::osx::quartz::QuartzGraphicsFactory> quartz_graphics_factory_;
};
@@ -64,6 +68,7 @@ OsxUiApplication::OsxUiApplication()
: OsxGuiResource(this), p_(new details::OsxUiApplicationPrivate(this)) {
[NSApp setDelegate:p_->app_delegate_];
p_->quartz_graphics_factory_ = std::make_unique<graphics::osx::quartz::QuartzGraphicsFactory>();
+ p_->cursor_manager_ = std::make_unique<OsxCursorManager>(this);
}
OsxUiApplication::~OsxUiApplication() {}
@@ -143,6 +148,12 @@ INativeWindow* OsxUiApplication::CreateWindow(INativeWindow* parent, CreateWindo
return window;
}
+ICursorManager* OsxUiApplication::GetCursorManager() { return p_->cursor_manager_.get(); }
+
+graphics::IGraphicsFactory* OsxUiApplication::GetGraphicsFactory() {
+ return p_->quartz_graphics_factory_.get();
+}
+
void OsxUiApplication::UnregisterWindow(OsxWindow* window) {
p_->windows_.erase(
std::remove(p_->windows_.begin(), p_->windows_.end(), static_cast<INativeWindow*>(window)),
@@ -150,8 +161,9 @@ void OsxUiApplication::UnregisterWindow(OsxWindow* window) {
}
}
-@implementation AppDelegate
-cru::platform::gui::osx::details::OsxUiApplicationPrivate* _p;
+@implementation AppDelegate {
+ cru::platform::gui::osx::details::OsxUiApplicationPrivate* _p;
+}
- (id)init:(cru::platform::gui::osx::details::OsxUiApplicationPrivate*)p {
_p = p;
diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm
index c2134c76..da39d34d 100644
--- a/src/osx/gui/Window.mm
+++ b/src/osx/gui/Window.mm
@@ -1,11 +1,16 @@
#include "cru/osx/gui/Window.hpp"
+#include "CursorPrivate.h"
#include "cru/common/Range.hpp"
#include "cru/osx/Convert.hpp"
#include "cru/osx/graphics/quartz/Painter.hpp"
+#include "cru/osx/gui/Cursor.hpp"
#include "cru/osx/gui/Keyboard.hpp"
+#include "cru/osx/gui/Resource.hpp"
#include "cru/osx/gui/UiApplication.hpp"
+#include "cru/platform/Check.hpp"
#include "cru/platform/gui/Base.hpp"
+#include "cru/platform/gui/Cursor.hpp"
#include "cru/platform/gui/InputMethod.hpp"
#include "cru/platform/gui/Keyboard.hpp"
#include "cru/platform/gui/Window.hpp"
@@ -34,6 +39,7 @@ namespace details {
class OsxWindowPrivate {
friend OsxWindow;
+ friend OsxInputMethodContextPrivate;
public:
explicit OsxWindowPrivate(OsxWindow* osx_window) : osx_window_(osx_window) {
@@ -52,6 +58,9 @@ class OsxWindowPrivate {
void OnWindowDidResize();
private:
+ void UpdateCursor();
+
+ private:
OsxWindow* osx_window_;
INativeWindow* parent_;
@@ -61,6 +70,12 @@ class OsxWindowPrivate {
NSWindow* window_;
WindowDelegate* window_delegate_;
+
+ bool mouse_in_ = false;
+
+ std::shared_ptr<OsxCursor> cursor_ = nullptr;
+
+ std::unique_ptr<OsxInputMethodContext> input_method_context_;
};
void OsxWindowPrivate::OnWindowWillClose() { osx_window_->destroy_event_.Raise(nullptr); }
@@ -69,6 +84,16 @@ void OsxWindowPrivate::OnWindowDidUpdate() { osx_window_->paint_event_.Raise(nul
void OsxWindowPrivate::OnWindowDidResize() {
osx_window_->resize_event_.Raise(osx_window_->GetClientSize());
}
+
+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];
+}
}
namespace {
@@ -86,6 +111,8 @@ OsxWindow::OsxWindow(OsxUiApplication* ui_application, INativeWindow* parent, bo
p_->frame_ = frame;
p_->content_rect_ = {100, 100, 400, 200};
+
+ p_->input_method_context_ = std::make_unique<OsxInputMethodContext>(this);
}
OsxWindow::~OsxWindow() {
@@ -155,6 +182,8 @@ void OsxWindow::SetWindowRect(const Rect& rect) {
}
}
+void OsxWindow::RequestRepaint() { [p_->window_ update]; }
+
std::unique_ptr<graphics::IPainter> OsxWindow::BeginPaint() {
NSGraphicsContext* ns_graphics_context =
[NSGraphicsContext graphicsContextWithWindow:p_->window_];
@@ -194,9 +223,12 @@ void OsxWindow::CreateWindow() {
switch (event.type) {
case NSEventTypeMouseEntered:
this->mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Enter);
+ p_->mouse_in_ = true;
+ p_->UpdateCursor();
break;
case NSEventTypeMouseExited:
this->mouse_enter_leave_event_.Raise(MouseEnterLeaveType::Leave);
+ p_->mouse_in_ = false;
break;
case NSEventTypeMouseMoved:
this->mouse_move_event_.Raise(
@@ -247,17 +279,35 @@ void OsxWindow::CreateWindow() {
}];
}
+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());
+ if (p_->mouse_in_) {
+ p_->UpdateCursor();
+ }
+}
+
+IInputMethodContext* OsxWindow::GetInputMethodContext() { return p_->input_method_context_.get(); }
+
namespace details {
class OsxInputMethodContextPrivate {
friend OsxInputMethodContext;
public:
- explicit OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context);
+ OsxInputMethodContextPrivate(OsxInputMethodContext* input_method_context, OsxWindow* window);
CRU_DELETE_COPY(OsxInputMethodContextPrivate)
CRU_DELETE_MOVE(OsxInputMethodContextPrivate)
- ~OsxInputMethodContextPrivate() = default;
+ ~OsxInputMethodContextPrivate();
void SetCompositionText(CompositionText composition_text) {
composition_text_ = std::move(composition_text);
@@ -274,7 +324,11 @@ class OsxInputMethodContextPrivate {
Range GetSelectionRange() const { return selection_range_; }
void SetSelectionRange(Range selection_range) { selection_range_ = selection_range; }
+ void PerformSel(SEL sel);
+
private:
+ OsxWindow* window_;
+
CompositionText composition_text_;
Range selection_range_;
@@ -290,6 +344,14 @@ class OsxInputMethodContextPrivate {
Event<StringView> text_event_;
};
+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);
}
@@ -299,8 +361,20 @@ void OsxInputMethodContextPrivate::RaiseCompositionEndEvent() {
void OsxInputMethodContextPrivate::RaiseCompositionEvent() { composition_event_.Raise(nullptr); }
void OsxInputMethodContextPrivate::RaiseTextEvent(StringView text) { text_event_.Raise(text); }
+
+void OsxInputMethodContextPrivate::PerformSel(SEL sel) {
+ [window_->p_->window_ performSelector:sel];
}
+}
+
+OsxInputMethodContext::OsxInputMethodContext(OsxWindow* window)
+ : OsxGuiResource(window->GetUiApplication()) {
+ p_ = std::make_unique<details::OsxInputMethodContextPrivate>(this, window);
+}
+
+OsxInputMethodContext::~OsxInputMethodContext() {}
+
void OsxInputMethodContext::EnableIME() { [[NSTextInputContext currentInputContext] deactivate]; }
void OsxInputMethodContext::DisableIME() { [[NSTextInputContext currentInputContext] activate]; }
@@ -336,34 +410,36 @@ IEvent<std::nullptr_t>* OsxInputMethodContext::CompositionEvent() {
IEvent<StringView>* OsxInputMethodContext::TextEvent() { return &p_->text_event_; }
}
-@implementation WindowDelegate
-cru::platform::gui::osx::details::OsxWindowPrivate* p_;
+@implementation WindowDelegate {
+ cru::platform::gui::osx::details::OsxWindowPrivate* _p;
+}
- (id)init:(cru::platform::gui::osx::details::OsxWindowPrivate*)p {
- p_ = p;
+ _p = p;
return self;
}
- (void)windowWillClose:(NSNotification*)notification {
- p_->OnWindowWillClose();
+ _p->OnWindowWillClose();
}
- (void)windowDidExpose:(NSNotification*)notification {
- p_->OnWindowDidExpose();
+ _p->OnWindowDidExpose();
}
- (void)windowDidUpdate:(NSNotification*)notification {
- p_->OnWindowDidUpdate();
+ _p->OnWindowDidUpdate();
}
- (void)windowDidResize:(NSNotification*)notification {
- p_->OnWindowDidResize();
+ _p->OnWindowDidResize();
}
@end
-@implementation InputClient
-cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _p;
-NSMutableAttributedString* _text;
+@implementation InputClient {
+ cru::platform::gui::osx::details::OsxInputMethodContextPrivate* _p;
+ NSMutableAttributedString* _text;
+}
- (id)init:(cru::platform::gui::osx::details::OsxInputMethodContextPrivate*)p {
_p = p;
@@ -440,6 +516,6 @@ NSMutableAttributedString* _text;
}
- (void)doCommandBySelector:(SEL)selector {
- // TODO: Call with window.
+ _p->PerformSel(selector);
}
@end
diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt
index 0288bed0..8d6929ec 100644
--- a/src/platform/CMakeLists.txt
+++ b/src/platform/CMakeLists.txt
@@ -21,4 +21,6 @@ add_subdirectory(gui)
if(WIN32)
add_subdirectory(bootstrap)
+elseif(APPLE)
+ add_subdirectory(bootstrap)
endif()
diff --git a/src/platform/bootstrap/Bootstrap.cpp b/src/platform/bootstrap/Bootstrap.cpp
index 99b5badb..c167be19 100644
--- a/src/platform/bootstrap/Bootstrap.cpp
+++ b/src/platform/bootstrap/Bootstrap.cpp
@@ -1,15 +1,17 @@
#include "cru/platform/bootstrap/Bootstrap.hpp"
+#include "cru/osx/gui/UiApplication.hpp"
#ifdef CRU_PLATFORM_WINDOWS
#include "cru/win/gui/UiApplication.hpp"
#else
#endif
-namespace cru::platform::boostrap {
+namespace cru::platform::bootstrap {
cru::platform::gui::IUiApplication* CreateUiApplication() {
#ifdef CRU_PLATFORM_WINDOWS
return new cru::platform::gui::win::WinUiApplication();
-#else
+#elif CRU_PLATFORM_OSX
+ return new cru::platform::gui::osx::OsxUiApplication();
#endif
}
-} // namespace cru::platform::boostrap
+} // namespace cru::platform::bootstrap
diff --git a/src/platform/bootstrap/CMakeLists.txt b/src/platform/bootstrap/CMakeLists.txt
index 7759415f..c979f586 100644
--- a/src/platform/bootstrap/CMakeLists.txt
+++ b/src/platform/bootstrap/CMakeLists.txt
@@ -1,13 +1,15 @@
set(CRU_PLATFORM_BOOTSTRAP_INCLUDE_DIR ${CRU_INCLUDE_DIR}/cru/platform/bootstrap)
-add_library(cru_platform_boostrap SHARED
+add_library(cru_platform_bootstrap SHARED
Bootstrap.cpp
)
-target_sources(cru_platform_boostrap PUBLIC
+target_sources(cru_platform_bootstrap PUBLIC
${CRU_PLATFORM_BOOTSTRAP_INCLUDE_DIR}/Bootstrap.hpp
)
if(WIN32)
- target_link_libraries(cru_platform_boostrap PUBLIC cru_win_gui)
+ target_link_libraries(cru_platform_bootstrap PUBLIC cru_win_gui)
+elseif(APPLE)
+ target_link_libraries(cru_platform_bootstrap PUBLIC cru_osx_gui)
endif()
-target_compile_definitions(cru_platform_boostrap PRIVATE CRU_PLATFORM_BOOTSTRAP_EXPORT_API)
+target_compile_definitions(cru_platform_bootstrap PRIVATE CRU_PLATFORM_BOOTSTRAP_EXPORT_API)