aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/osx/gui/Window.mm143
-rw-r--r--src/osx/gui/WindowPrivate.h10
-rw-r--r--src/ui/components/Menu.cpp5
-rw-r--r--src/ui/controls/Popup.cpp16
-rw-r--r--src/ui/controls/RootControl.cpp60
-rw-r--r--src/ui/controls/Window.cpp9
-rw-r--r--src/ui/host/WindowHost.cpp35
7 files changed, 128 insertions, 150 deletions
diff --git a/src/osx/gui/Window.mm b/src/osx/gui/Window.mm
index 9f0d9742..b838165f 100644
--- a/src/osx/gui/Window.mm
+++ b/src/osx/gui/Window.mm
@@ -56,10 +56,10 @@ void OsxWindowPrivate::OnWindowWillClose() {
void OsxWindowPrivate::OnWindowDidExpose() { osx_window_->RequestRepaint(); }
void OsxWindowPrivate::OnWindowDidUpdate() {}
+void OsxWindowPrivate::OnWindowDidMove() { content_rect_ = RetrieveContentRect(); }
+
void OsxWindowPrivate::OnWindowDidResize() {
- NSRect rect = [NSWindow contentRectForFrameRect:[window_ frame]
- styleMask:CalcWindowStyleMask(frame_)];
- content_rect_ = cru::platform::graphics::osx::quartz::Convert(rect);
+ content_rect_ = RetrieveContentRect();
auto view = [window_ contentView];
[view removeTrackingArea:[view trackingAreas][0]];
@@ -72,13 +72,7 @@ void OsxWindowPrivate::OnWindowDidResize() {
CGLayerRelease(draw_layer_);
- // If size is 0 then create layer will fail.
- auto s = rect.size;
- if (s.width == 0) s.width = 1;
- if (s.height == 0) s.height = 1;
-
- draw_layer_ = CGLayerCreateWithContext(nullptr, s, nullptr);
- Ensures(draw_layer_);
+ draw_layer_ = CreateLayer(Convert(content_rect_.GetSize()));
resize_event_.Raise(osx_window_->GetClientSize());
@@ -121,6 +115,17 @@ 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>(
@@ -137,6 +142,48 @@ Point OsxWindowPrivate::TransformMousePoint(const Point& point) {
return r;
}
+void OsxWindowPrivate::CreateWindow() {
+ NSRect content_rect = Convert(content_rect_);
+ NSWindowStyleMask style_mask = CalcWindowStyleMask(frame_);
+
+ auto cr = content_rect;
+ cr.origin.y = GetScreenSize().height - content_rect.origin.y - content_rect.size.height;
+ window_ = [[CruWindow alloc] init:this contentRect:content_rect style:style_mask];
+ Ensures(window_);
+
+ [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];
+
+ draw_layer_ = CreateLayer(content_rect.size);
+
+ 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(frame_)];
+ rect.origin.y = GetScreenSize().height - rect.origin.y - rect.size.height;
+ return cru::platform::graphics::osx::quartz::Convert(rect);
+}
+
}
OsxWindow::OsxWindow(OsxUiApplication* ui_application, INativeWindow* parent, bool frame)
@@ -178,7 +225,7 @@ void OsxWindow::SetVisible(bool is_visible) {
}
} else {
if (is_visible) {
- CreateWindow();
+ p_->CreateWindow();
[p_->window_ orderFront:nil];
}
}
@@ -194,26 +241,33 @@ void OsxWindow::SetClientSize(const Size& size) {
}
}
-Rect OsxWindow::GetWindowRect() {
+Rect OsxWindow::GetClientRect() { return p_->content_rect_; }
+
+void OsxWindow::SetClientRect(const Rect& rect) {
if (p_->window_) {
- auto r = [p_->window_ frame];
- return Rect(r.origin.x, r.origin.y, r.size.width, r.size.height);
+ auto r = Convert(rect);
+ r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
+ r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->frame_)];
+ [p_->window_ setFrame:r display:false];
} else {
- NSRect rr{p_->content_rect_.left, p_->content_rect_.top, p_->content_rect_.width,
- p_->content_rect_.height};
- auto r = [NSWindow frameRectForContentRect:rr styleMask:CalcWindowStyleMask(p_->frame_)];
- return Rect(r.origin.x, r.origin.y, r.size.width, r.size.height);
+ 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_->frame_)];
+ r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
+ return Convert(r);
+}
+
void OsxWindow::SetWindowRect(const Rect& rect) {
- auto rr = NSRect{rect.left, rect.top, rect.width, rect.height};
- if (p_->window_) {
- [p_->window_ setFrame:rr display:false];
- } else {
- auto r = [NSWindow contentRectForFrameRect:rr styleMask:CalcWindowStyleMask(p_->frame_)];
- p_->content_rect_ = Rect(r.origin.x, r.origin.y, r.size.width, r.size.height);
- }
+ auto r = Convert(rect);
+ r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
+ r = [NSWindow frameRectForContentRect:r styleMask:CalcWindowStyleMask(p_->frame_)];
+ r.origin.y = p_->GetScreenSize().height - r.origin.y - r.size.height;
+ SetClientRect(Convert(r));
}
void OsxWindow::RequestRepaint() {
@@ -236,40 +290,6 @@ std::unique_ptr<graphics::IPainter> OsxWindow::BeginPaint() {
});
}
-void OsxWindow::CreateWindow() {
- NSRect content_rect = CGRectMake(p_->content_rect_.left, p_->content_rect_.top,
- p_->content_rect_.width, p_->content_rect_.height);
-
- NSWindowStyleMask style_mask = CalcWindowStyleMask(p_->frame_);
-
- p_->window_ = [[CruWindow alloc] init:p_.get() contentRect:content_rect style:style_mask];
- Ensures(p_->window_);
-
- [p_->window_ setDelegate:p_->window_delegate_];
-
- if (p_->parent_) {
- auto parent = CheckPlatform<OsxWindow>(p_->parent_, GetPlatformId());
- [p_->window_ setParentWindow:parent->p_->window_];
- }
-
- NSView* content_view = [[CruView alloc] init:p_.get()
- input_context_p:p_->input_method_context_->p_.get()
- frame:Rect(Point{}, p_->content_rect_.GetSize())];
-
- [p_->window_ setContentView:content_view];
-
- // If size is 0 then create layer will fail.
- auto s = p_->content_rect_.GetSize();
- if (s.width == 0) s.width = 1;
- if (s.height == 0) s.height = 1;
-
- p_->draw_layer_ =
- CGLayerCreateWithContext(nullptr, cru::platform::graphics::osx::quartz::Convert(s), nullptr);
- Ensures(p_->draw_layer_);
-
- RequestRepaint();
-}
-
bool OsxWindow::RequestFocus() {
if (!p_->window_) return false;
[p_->window_ makeKeyWindow];
@@ -292,6 +312,7 @@ void OsxWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
}
}
+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<Size>* OsxWindow::ResizeEvent() { return &p_->resize_event_; }
@@ -660,6 +681,10 @@ const std::unordered_set<KeyCode> input_context_handle_codes_when_has_text{
_p->OnWindowDidUpdate();
}
+- (void)windowDidMove:(NSNotification*)notification {
+ _p->OnWindowDidMove();
+}
+
- (void)windowDidResize:(NSNotification*)notification {
_p->OnWindowDidResize();
}
diff --git a/src/osx/gui/WindowPrivate.h b/src/osx/gui/WindowPrivate.h
index 0778195a..88760673 100644
--- a/src/osx/gui/WindowPrivate.h
+++ b/src/osx/gui/WindowPrivate.h
@@ -53,6 +53,7 @@ class OsxWindowPrivate {
void OnWindowWillClose();
void OnWindowDidExpose();
void OnWindowDidUpdate();
+ void OnWindowDidMove();
void OnWindowDidResize();
void OnBecomeKeyWindow();
void OnResignKeyWindow();
@@ -63,10 +64,18 @@ class OsxWindowPrivate {
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_;
@@ -88,6 +97,7 @@ class OsxWindowPrivate {
TimerAutoCanceler draw_timer_;
+ Event<std::nullptr_t> create_event_;
Event<std::nullptr_t> destroy_event_;
Event<std::nullptr_t> paint_event_;
Event<Size> resize_event_;
diff --git a/src/ui/components/Menu.cpp b/src/ui/components/Menu.cpp
index af54c46c..964eead9 100644
--- a/src/ui/components/Menu.cpp
+++ b/src/ui/components/Menu.cpp
@@ -1,4 +1,5 @@
#include "cru/ui/components/Menu.hpp"
+#include "cru/platform/gui/Window.hpp"
#include "cru/ui/UiManager.hpp"
#include "cru/ui/controls/Button.hpp"
#include "cru/ui/controls/Control.hpp"
@@ -82,11 +83,11 @@ PopupMenu::~PopupMenu() {
controls::Control* PopupMenu::GetRootControl() { return popup_; }
void PopupMenu::SetPosition(const Point& position) {
- popup_->SetRect(Rect{position, {}});
+ popup_->GetWindowHost()->GetNativeWindow()->SetClientRect(Rect{position, {}});
}
void PopupMenu::Show() {
popup_->GetWindowHost()->RelayoutWithSize(Size::Infinate(), true);
- popup_->Show();
+ popup_->GetWindowHost()->GetNativeWindow()->SetVisible(true);
}
} // namespace cru::ui::components
diff --git a/src/ui/controls/Popup.cpp b/src/ui/controls/Popup.cpp
index 515c7b31..ae6ac1d2 100644
--- a/src/ui/controls/Popup.cpp
+++ b/src/ui/controls/Popup.cpp
@@ -8,19 +8,13 @@
#include <memory>
namespace cru::ui::controls {
-Popup::Popup(Control* attached_control) : RootControl(attached_control) {
+Popup::Popup(Control* attached_control)
+ : RootControl(
+ attached_control,
+ host::CreateWindowParams{
+ nullptr, platform::gui::CreateWindowFlags::NoCaptionAndBorder}) {
SetGainFocusOnCreateAndDestroyWhenLoseFocus(true);
}
Popup::~Popup() = default;
-
-gsl::not_null<platform::gui::INativeWindow*> Popup::CreateNativeWindow(
- gsl::not_null<host::WindowHost*> host,
- platform::gui::INativeWindow* parent) {
- auto window = host->CreateNativeWindow(
- {parent, platform::gui::CreateWindowFlags::NoCaptionAndBorder});
-
- return window;
-}
-
} // namespace cru::ui::controls
diff --git a/src/ui/controls/RootControl.cpp b/src/ui/controls/RootControl.cpp
index 007a0ac1..4ae41c80 100644
--- a/src/ui/controls/RootControl.cpp
+++ b/src/ui/controls/RootControl.cpp
@@ -11,57 +11,35 @@
#include <memory>
namespace cru::ui::controls {
-RootControl::RootControl(Control* attached_control)
+RootControl::RootControl(Control* attached_control,
+ host::CreateWindowParams params)
: attached_control_(attached_control) {
render_object_ = std::make_unique<render::StackLayoutRenderObject>();
render_object_->SetAttachedControl(this);
SetContainerRenderObject(render_object_.get());
- window_host_ = std::make_unique<host::WindowHost>(this);
-}
-
-RootControl::~RootControl() {}
-
-render::RenderObject* RootControl::GetRenderObject() const {
- return render_object_.get();
-}
-
-void RootControl::EnsureWindowCreated() { this->GetNativeWindow(true); }
+ window_host_ = std::make_unique<host::WindowHost>(this, params);
-Rect RootControl::GetRect() { return window_host_->GetWindowRect(); }
-
-void RootControl::SetRect(const Rect& rect) {
- window_host_->SetWindowRect(rect);
-}
-
-void RootControl::Show(bool create) {
- platform::gui::INativeWindow* native_window = GetNativeWindow(create);
- if (!native_window) return;
- native_window->SetVisible(true);
if (gain_focus_on_create_and_destroy_when_lose_focus_) {
- native_window->RequestFocus();
+ auto native_window = window_host_->GetNativeWindow();
+ native_window->CreateEvent()->AddHandler(
+ [](platform::gui::INativeWindow* window) {
+ window->CreateEvent()->AddHandler(
+ [window](std::nullptr_t) { window->RequestFocus(); });
+ });
+
+ native_window->FocusEvent()->AddHandler(
+ [native_window](platform::gui::FocusChangeType type) {
+ if (type == platform::gui::FocusChangeType::Lost) {
+ native_window->Close();
+ }
+ });
}
}
-platform::gui::INativeWindow* RootControl::GetNativeWindow(bool create) {
- const auto host = GetWindowHost();
- platform::gui::INativeWindow* native_window = host->GetNativeWindow();
- if (!create) return native_window;
- if (!native_window) {
- native_window = this->CreateNativeWindow(
- host, attached_control_
- ? attached_control_->GetWindowHost()->GetNativeWindow()
- : nullptr);
+RootControl::~RootControl() {}
- if (gain_focus_on_create_and_destroy_when_lose_focus_) {
- native_window->FocusEvent()->AddHandler(
- [native_window](platform::gui::FocusChangeType type) {
- if (type == platform::gui::FocusChangeType::Lost) {
- native_window->Close();
- }
- });
- }
- }
- return native_window;
+render::RenderObject* RootControl::GetRenderObject() const {
+ return render_object_.get();
}
void RootControl::SetGainFocusOnCreateAndDestroyWhenLoseFocus(bool value) {
diff --git a/src/ui/controls/Window.cpp b/src/ui/controls/Window.cpp
index ba66f42e..00fab8e9 100644
--- a/src/ui/controls/Window.cpp
+++ b/src/ui/controls/Window.cpp
@@ -12,13 +12,8 @@ Window* Window::Create(Control* attached_control) {
return new Window(attached_control);
}
-Window::Window(Control* attached_control) : RootControl(attached_control) {}
+Window::Window(Control* attached_control)
+ : RootControl(attached_control, host::CreateWindowParams{}) {}
Window::~Window() {}
-
-gsl::not_null<platform::gui::INativeWindow*> Window::CreateNativeWindow(
- gsl::not_null<host::WindowHost*> host,
- platform::gui::INativeWindow* parent) {
- return host->CreateNativeWindow({parent});
-}
} // namespace cru::ui::controls
diff --git a/src/ui/host/WindowHost.cpp b/src/ui/host/WindowHost.cpp
index d26b43ab..3f3976b4 100644
--- a/src/ui/host/WindowHost.cpp
+++ b/src/ui/host/WindowHost.cpp
@@ -104,7 +104,8 @@ inline void BindNativeEvent(
}
} // namespace
-WindowHost::WindowHost(controls::Control* root_control)
+WindowHost::WindowHost(controls::Control* root_control,
+ CreateWindowParams params)
: root_control_(root_control), focus_control_(root_control) {
root_control_->TraverseDescendants([this](controls::Control* control) {
control->window_host_ = this;
@@ -115,14 +116,14 @@ WindowHost::WindowHost(controls::Control* root_control)
root_render_object_->SetWindowHostRecursive(this);
this->layout_paint_cycler_ = std::make_unique<LayoutPaintCycler>(this);
+
+ CreateNativeWindow(params);
}
WindowHost::~WindowHost() {}
gsl::not_null<platform::gui::INativeWindow*> WindowHost::CreateNativeWindow(
CreateWindowParams create_window_params) {
- if (native_window_ != nullptr) return native_window_;
-
const auto ui_application = IUiApplication::GetInstance();
auto native_window = ui_application->CreateWindow(create_window_params.parent,
@@ -153,10 +154,6 @@ gsl::not_null<platform::gui::INativeWindow*> WindowHost::CreateNativeWindow(
BindNativeEvent(this, native_window, native_window->KeyUpEvent(),
&WindowHost::OnNativeKeyUp, event_revoker_guards_);
- if (saved_rect_) {
- native_window->SetWindowRect(saved_rect_.value());
- }
-
native_window_change_event_.Raise(native_window);
return native_window_;
@@ -194,8 +191,7 @@ void WindowHost::RelayoutWithSize(const Size& available_size,
render::MeasureSize::NotSpecified());
if (set_window_size_to_fit_content) {
- auto rect = GetWindowRect();
- SetWindowRect({rect.GetLeftTop(), root_render_object_->GetSize()});
+ native_window_->SetClientSize(root_render_object_->GetSize());
}
root_render_object_->Layout(Point{});
@@ -277,29 +273,8 @@ void WindowHost::RunAfterLayoutStable(std::function<void()> action) {
}
}
-Rect WindowHost::GetWindowRect() {
- if (native_window_) return native_window_->GetWindowRect();
- return saved_rect_.value_or(Rect{});
-}
-
-void WindowHost::SetSavedWindowRect(std::optional<Rect> rect) {
- saved_rect_ = std::move(rect);
-}
-
-void WindowHost::SetWindowRect(const Rect& rect) {
- SetSavedWindowRect(rect);
- if (native_window_) native_window_->SetWindowRect(rect);
-}
-
void WindowHost::OnNativeDestroy(INativeWindow* window, std::nullptr_t) {
CRU_UNUSED(window)
-
- saved_rect_ = this->native_window_->GetWindowRect();
-
- this->native_window_ = nullptr;
- event_revoker_guards_.clear();
-
- native_window_change_event_.Raise(nullptr);
}
void WindowHost::OnNativePaint(INativeWindow* window, std::nullptr_t) {