aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/platform/native/ui_application.hpp5
-rw-r--r--include/cru/platform/native/window.hpp24
-rw-r--r--include/cru/ui/window.hpp34
-rw-r--r--include/cru/win/native/ui_application.hpp2
-rw-r--r--include/cru/win/native/window.hpp42
-rw-r--r--src/ui/window.cpp90
-rw-r--r--src/win/native/ui_application.cpp8
-rw-r--r--src/win/native/window.cpp130
8 files changed, 193 insertions, 142 deletions
diff --git a/include/cru/platform/native/ui_application.hpp b/include/cru/platform/native/ui_application.hpp
index b69b1f52..edbcc578 100644
--- a/include/cru/platform/native/ui_application.hpp
+++ b/include/cru/platform/native/ui_application.hpp
@@ -3,6 +3,7 @@
#include <chrono>
#include <functional>
+#include <memory>
#include <vector>
namespace cru::platform::graph {
@@ -11,6 +12,7 @@ struct IGraphFactory;
namespace cru::platform::native {
struct INativeWindow;
+struct INativeWindowResolver;
struct ICursorManager;
// The entry point of a ui application.
@@ -39,7 +41,8 @@ struct IUiApplication : public virtual INativeResource {
virtual void CancelTimer(unsigned long id) = 0;
virtual std::vector<INativeWindow*> GetAllWindow() = 0;
- virtual INativeWindow* CreateWindow(INativeWindow* parent) = 0;
+ virtual std::shared_ptr<INativeWindowResolver> CreateWindow(
+ INativeWindow* parent) = 0;
virtual cru::platform::graph::IGraphFactory* GetGraphFactory() = 0;
diff --git a/include/cru/platform/native/window.hpp b/include/cru/platform/native/window.hpp
index bfaf170b..84193a13 100644
--- a/include/cru/platform/native/window.hpp
+++ b/include/cru/platform/native/window.hpp
@@ -12,22 +12,17 @@ struct IPainter;
}
namespace cru::platform::native {
+struct INativeWindowResolver;
+
// Represents a native window, which exposes some low-level events and
// operations.
//
-// Although you can always retain an instance of this class, the real window
-// associated with it might be have already been destroyed by explicitly calling
-// Close or closed by the user, which leads to an invalid instance. You can
-// check the validity by IsValid. When you call perform native operations on the
-// invalid instance, there is no effect.
+// Usually you save an INativeWindowResolver after creating a window. Because
+// window may be destroyed when user do certain actions like click the close
+// button. Then the INativeWindow instance is destroyed and
+// INativeWindowResolver::Resolve return nullptr to indicate the fact.
struct INativeWindow : virtual INativeResource {
- // Return if the window is still valid, that is, hasn't been closed or
- // destroyed.
- virtual bool IsValid() = 0;
-
- // Set if the instance is deleted automatically when the window is destroyed
- // by other ways. Default is true.
- virtual void SetDeleteThisOnDestroy(bool value) = 0;
+ virtual std::shared_ptr<INativeWindowResolver> GetResolver() = 0;
virtual void Close() = 0;
@@ -71,4 +66,9 @@ struct INativeWindow : virtual INativeResource {
virtual IEvent<int>* KeyDownEvent() = 0;
virtual IEvent<int>* KeyUpEvent() = 0;
};
+
+// See INativeWindow for more info.
+struct INativeWindowResolver : virtual INativeResource {
+ virtual INativeWindow* Resolve() = 0;
+};
} // namespace cru::platform::native
diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp
index 35d6772e..105063d9 100644
--- a/include/cru/ui/window.hpp
+++ b/include/cru/ui/window.hpp
@@ -9,7 +9,8 @@
namespace cru::platform::native {
struct INativeWindow;
-}
+struct INativeWindowResolver;
+} // namespace cru::platform::native
namespace cru::ui {
namespace render {
@@ -38,13 +39,11 @@ class Window final : public ContentControl, public SelfResolvable<Window> {
~Window() override;
public:
- std::string_view GetControlType() const override final;
+ std::string_view GetControlType() const final;
render::RenderObject* GetRenderObject() const override;
- platform::native::INativeWindow* GetNativeWindow() const {
- return native_window_;
- }
+ platform::native::INativeWindow* GetNativeWindow();
// Get current control that mouse hovers on. This ignores the mouse-capture
// control. Even when mouse is captured by another control, this function
@@ -85,22 +84,29 @@ class Window final : public ContentControl, public SelfResolvable<Window> {
//*************** region: native messages ***************
- void OnNativeDestroy(std::nullptr_t);
- void OnNativePaint(std::nullptr_t);
- void OnNativeResize(const Size& size);
+ void OnNativeDestroy(platform::native::INativeWindow* window, std::nullptr_t);
+ void OnNativePaint(platform::native::INativeWindow* window, std::nullptr_t);
+ void OnNativeResize(platform::native::INativeWindow* window,
+ const Size& size);
- void OnNativeFocus(cru::platform::native::FocusChangeType focus);
+ void OnNativeFocus(platform::native::INativeWindow* window,
+ cru::platform::native::FocusChangeType focus);
void OnNativeMouseEnterLeave(
+ platform::native::INativeWindow* window,
cru::platform::native::MouseEnterLeaveType enter);
- void OnNativeMouseMove(const Point& point);
+ void OnNativeMouseMove(platform::native::INativeWindow* window,
+ const Point& point);
void OnNativeMouseDown(
+ platform::native::INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args);
void OnNativeMouseUp(
+ platform::native::INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args);
- void OnNativeKeyDown(int virtual_code);
- void OnNativeKeyUp(int virtual_code);
+ void OnNativeKeyDown(platform::native::INativeWindow* window,
+ int virtual_code);
+ void OnNativeKeyUp(platform::native::INativeWindow* window, int virtual_code);
//*************** region: event dispatcher helper ***************
@@ -112,7 +118,9 @@ class Window final : public ContentControl, public SelfResolvable<Window> {
void UpdateCursor();
private:
- platform::native::INativeWindow* native_window_;
+ std::shared_ptr<platform::native::INativeWindowResolver>
+ native_window_resolver_;
+
std::vector<EventRevokerGuard> event_revoker_guards_;
std::unique_ptr<render::WindowRenderObject> render_object_;
diff --git a/include/cru/win/native/ui_application.hpp b/include/cru/win/native/ui_application.hpp
index 80e358e4..73f67abe 100644
--- a/include/cru/win/native/ui_application.hpp
+++ b/include/cru/win/native/ui_application.hpp
@@ -45,7 +45,7 @@ class WinUiApplication : public WinNativeResource,
void CancelTimer(unsigned long id) override;
std::vector<INativeWindow*> GetAllWindow() override;
- INativeWindow* CreateWindow(INativeWindow* parent) override;
+ std::shared_ptr<INativeWindowResolver> CreateWindow(INativeWindow* parent) override;
cru::platform::graph::IGraphFactory* GetGraphFactory() override;
diff --git a/include/cru/win/native/window.hpp b/include/cru/win/native/window.hpp
index 9752682f..3c883338 100644
--- a/include/cru/win/native/window.hpp
+++ b/include/cru/win/native/window.hpp
@@ -12,12 +12,12 @@ class WinCursor;
class WindowClass;
class WindowManager;
class WindowRenderTarget;
+class WinNativeWindowResolver;
class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
public:
- WinNativeWindow(WinUiApplication* application,
- WindowClass* window_class, DWORD window_style,
- WinNativeWindow* parent);
+ WinNativeWindow(WinUiApplication* application, WindowClass* window_class,
+ DWORD window_style, WinNativeWindow* parent);
CRU_DELETE_COPY(WinNativeWindow)
CRU_DELETE_MOVE(WinNativeWindow)
@@ -25,8 +25,9 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
~WinNativeWindow() override;
public:
- bool IsValid() override;
- void SetDeleteThisOnDestroy(bool value) override;
+ std::shared_ptr<INativeWindowResolver> GetResolver() override {
+ return std::static_pointer_cast<INativeWindowResolver>(resolver_);
+ }
void Close() override;
@@ -118,7 +119,14 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
private:
WinUiApplication* application_;
- bool delete_this_on_destroy_ = true;
+ // when delete is called first, it set this to true to indicate
+ // destroy message handler not to double delete this instance;
+ // when destroy handler is called first (by user action or method
+ // Close), it set this to true to indicate delete not call Close
+ // again.
+ bool sync_flag_ = false;
+
+ std::shared_ptr<WinNativeWindowResolver> resolver_;
HWND hwnd_;
WinNativeWindow* parent_window_;
@@ -143,4 +151,26 @@ class WinNativeWindow : public WinNativeResource, public virtual INativeWindow {
Event<WindowNativeMessageEventArgs&> native_message_event_;
};
+
+class WinNativeWindowResolver : public WinNativeResource,
+ public virtual INativeWindowResolver {
+ friend WinNativeWindow::~WinNativeWindow();
+
+ public:
+ WinNativeWindowResolver(WinNativeWindow* window) : window_(window) {}
+
+ CRU_DELETE_COPY(WinNativeWindowResolver)
+ CRU_DELETE_MOVE(WinNativeWindowResolver)
+
+ ~WinNativeWindowResolver() override = default;
+
+ public:
+ INativeWindow* Resolve() override { return window_; }
+
+ private:
+ void Reset();
+
+ private:
+ WinNativeWindow* window_;
+};
} // namespace cru::platform::native::win
diff --git a/src/ui/window.cpp b/src/ui/window.cpp
index 6ff44b4b..35463778 100644
--- a/src/ui/window.cpp
+++ b/src/ui/window.cpp
@@ -11,6 +11,8 @@
namespace cru::ui {
using cru::platform::native::FocusChangeType;
+using cru::platform::native::INativeWindow;
+using cru::platform::native::INativeWindowResolver;
using cru::platform::native::IUiApplication;
using cru::platform::native::MouseEnterLeaveType;
@@ -88,11 +90,12 @@ Window* Window::CreateOverlapped() {
namespace {
template <typename T>
-void BindNativeEvent(Window* window, IEvent<T>* event,
- void (Window::*handler)(typename IEvent<T>::EventArgs),
- std::vector<EventRevokerGuard>& guard_pool) {
- guard_pool.push_back(EventRevokerGuard(
- event->AddHandler(std::bind(handler, window, std::placeholders::_1))));
+inline void BindNativeEvent(
+ Window* window, INativeWindow* native_window, IEvent<T>* event,
+ void (Window::*handler)(INativeWindow*, typename IEvent<T>::EventArgs),
+ std::vector<EventRevokerGuard>& guard_pool) {
+ guard_pool.push_back(EventRevokerGuard(event->AddHandler(
+ std::bind(handler, window, native_window, std::placeholders::_1))));
}
} // namespace
@@ -101,30 +104,34 @@ Window::Window(tag_overlapped_constructor)
focus_control_(this),
mouse_captured_control_(nullptr) {
window_ = this;
- native_window_ = IUiApplication::GetInstance()->CreateWindow(nullptr);
+ native_window_resolver_ =
+ IUiApplication::GetInstance()->CreateWindow(nullptr);
+
+ const auto native_window = native_window_resolver_->Resolve();
+
render_object_.reset(new render::WindowRenderObject(this));
render_object_->SetAttachedControl(this);
- BindNativeEvent(this, native_window_->DestroyEvent(),
+ BindNativeEvent(this, native_window, native_window->DestroyEvent(),
&Window::OnNativeDestroy, event_revoker_guards_);
- BindNativeEvent(this, native_window_->PaintEvent(), &Window::OnNativePaint,
- event_revoker_guards_);
- BindNativeEvent(this, native_window_->ResizeEvent(), &Window::OnNativeResize,
- event_revoker_guards_);
- BindNativeEvent(this, native_window_->FocusEvent(), &Window::OnNativeFocus,
- event_revoker_guards_);
- BindNativeEvent(this, native_window_->MouseEnterLeaveEvent(),
+ BindNativeEvent(this, native_window, native_window->PaintEvent(),
+ &Window::OnNativePaint, event_revoker_guards_);
+ BindNativeEvent(this, native_window, native_window->ResizeEvent(),
+ &Window::OnNativeResize, event_revoker_guards_);
+ BindNativeEvent(this, native_window, native_window->FocusEvent(),
+ &Window::OnNativeFocus, event_revoker_guards_);
+ BindNativeEvent(this, native_window, native_window->MouseEnterLeaveEvent(),
&Window::OnNativeMouseEnterLeave, event_revoker_guards_);
- BindNativeEvent(this, native_window_->MouseMoveEvent(),
+ BindNativeEvent(this, native_window, native_window->MouseMoveEvent(),
&Window::OnNativeMouseMove, event_revoker_guards_);
- BindNativeEvent(this, native_window_->MouseDownEvent(),
+ BindNativeEvent(this, native_window, native_window->MouseDownEvent(),
&Window::OnNativeMouseDown, event_revoker_guards_);
- BindNativeEvent(this, native_window_->MouseUpEvent(),
+ BindNativeEvent(this, native_window, native_window->MouseUpEvent(),
&Window::OnNativeMouseUp, event_revoker_guards_);
- BindNativeEvent(this, native_window_->KeyDownEvent(),
+ BindNativeEvent(this, native_window, native_window->KeyDownEvent(),
&Window::OnNativeKeyDown, event_revoker_guards_);
- BindNativeEvent(this, native_window_->KeyUpEvent(), &Window::OnNativeKeyUp,
- event_revoker_guards_);
+ BindNativeEvent(this, native_window, native_window->KeyUpEvent(),
+ &Window::OnNativeKeyUp, event_revoker_guards_);
}
Window::~Window() {
@@ -138,6 +145,10 @@ render::RenderObject* Window::GetRenderObject() const {
return render_object_.get();
}
+platform::native::INativeWindow* Window::GetNativeWindow() {
+ return native_window_resolver_->Resolve();
+}
+
bool Window::RequestFocusFor(Control* control) {
assert(control != nullptr); // The control to request focus can't be null.
// You can set it as the window.
@@ -194,21 +205,27 @@ Control* Window::HitTest(const Point& point) {
return render_object_->HitTest(point)->GetAttachedControl();
}
-void Window::OnNativeDestroy(std::nullptr_t) { delete this; }
+void Window::OnNativeDestroy(INativeWindow* window, std::nullptr_t) {
+ CRU_UNUSED(window)
+ delete this;
+}
-void Window::OnNativePaint(std::nullptr_t) {
- auto painter = native_window_->BeginPaint();
+void Window::OnNativePaint(INativeWindow* window, std::nullptr_t) {
+ auto painter = window->BeginPaint();
render_object_->Draw(painter.get());
painter->EndDraw();
}
-void Window::OnNativeResize(const Size& size) {
+void Window::OnNativeResize(INativeWindow* window, const Size& size) {
+ CRU_UNUSED(window)
CRU_UNUSED(size)
render_object_->GetRenderHost()->InvalidateLayout();
}
-void Window::OnNativeFocus(FocusChangeType focus) {
+void Window::OnNativeFocus(INativeWindow* window, FocusChangeType focus) {
+ CRU_UNUSED(window)
+
focus == FocusChangeType::Gain
? DispatchEvent(event_names::GainFocus, focus_control_,
&Control::GainFocusEvent, nullptr, true)
@@ -216,7 +233,10 @@ void Window::OnNativeFocus(FocusChangeType focus) {
&Control::LoseFocusEvent, nullptr, true);
}
-void Window::OnNativeMouseEnterLeave(MouseEnterLeaveType type) {
+void Window::OnNativeMouseEnterLeave(INativeWindow* window,
+ MouseEnterLeaveType type) {
+ CRU_UNUSED(window)
+
if (type == MouseEnterLeaveType::Leave) {
DispatchEvent(event_names::MouseLeave, mouse_hover_control_,
&Control::MouseLeaveEvent, nullptr);
@@ -224,7 +244,9 @@ void Window::OnNativeMouseEnterLeave(MouseEnterLeaveType type) {
}
}
-void Window::OnNativeMouseMove(const Point& point) {
+void Window::OnNativeMouseMove(INativeWindow* window, const Point& point) {
+ CRU_UNUSED(window)
+
// Find the first control that hit test succeed.
const auto new_mouse_hover_control = HitTest(point);
const auto old_mouse_hover_control = mouse_hover_control_;
@@ -256,7 +278,10 @@ void Window::OnNativeMouseMove(const Point& point) {
}
void Window::OnNativeMouseDown(
+ INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args) {
+ CRU_UNUSED(window)
+
Control* control =
mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point);
DispatchEvent(event_names::MouseDown, control, &Control::MouseDownEvent,
@@ -264,19 +289,26 @@ void Window::OnNativeMouseDown(
}
void Window::OnNativeMouseUp(
+ INativeWindow* window,
const platform::native::NativeMouseButtonEventArgs& args) {
+ CRU_UNUSED(window)
+
Control* control =
mouse_captured_control_ ? mouse_captured_control_ : HitTest(args.point);
DispatchEvent(event_names::MouseUp, control, &Control::MouseUpEvent, nullptr,
args.point, args.button);
}
-void Window::OnNativeKeyDown(int virtual_code) {
+void Window::OnNativeKeyDown(INativeWindow* window, int virtual_code) {
+ CRU_UNUSED(window)
+
DispatchEvent(event_names::KeyDown, focus_control_, &Control::KeyDownEvent,
nullptr, virtual_code);
}
-void Window::OnNativeKeyUp(int virtual_code) {
+void Window::OnNativeKeyUp(INativeWindow* window, int virtual_code) {
+ CRU_UNUSED(window)
+
DispatchEvent(event_names::KeyUp, focus_control_, &Control::KeyUpEvent,
nullptr, virtual_code);
}
diff --git a/src/win/native/ui_application.cpp b/src/win/native/ui_application.cpp
index 75fce6ce..9ab61551 100644
--- a/src/win/native/ui_application.cpp
+++ b/src/win/native/ui_application.cpp
@@ -103,13 +103,15 @@ std::vector<INativeWindow*> WinUiApplication::GetAllWindow() {
return result;
}
-INativeWindow* WinUiApplication::CreateWindow(INativeWindow* parent) {
+std::shared_ptr<INativeWindowResolver> WinUiApplication::CreateWindow(
+ INativeWindow* parent) {
WinNativeWindow* p = nullptr;
if (parent != nullptr) {
p = CheckPlatform<WinNativeWindow>(parent, GetPlatformId());
}
- return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(),
- WS_OVERLAPPEDWINDOW, p);
+ return (new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(),
+ WS_OVERLAPPEDWINDOW, p))
+ ->GetResolver();
}
cru::platform::graph::IGraphFactory* WinUiApplication::GetGraphFactory() {
diff --git a/src/win/native/window.cpp b/src/win/native/window.cpp
index a8016676..2e99a5cb 100644
--- a/src/win/native/window.cpp
+++ b/src/win/native/window.cpp
@@ -23,10 +23,12 @@ inline Point PiToDip(const POINT& pi_point) {
WinNativeWindow::WinNativeWindow(WinUiApplication* application,
WindowClass* window_class, DWORD window_style,
WinNativeWindow* parent)
- : application_(application), parent_window_(parent) {
+ : application_(application),
+ resolver_(std::make_shared<WinNativeWindowResolver>(this)),
+ parent_window_(parent) {
assert(application); // application can't be null.
- if (parent != nullptr && !parent->IsValid()) {
+ if (parent != nullptr) {
throw new std::runtime_error("Can't use a invalid window as parent.");
}
@@ -51,63 +53,45 @@ WinNativeWindow::WinNativeWindow(WinUiApplication* application,
}
WinNativeWindow::~WinNativeWindow() {
- if (IsValid()) {
- SetDeleteThisOnDestroy(false); // avoid double delete.
+ if (!sync_flag_) {
+ sync_flag_ = true;
Close();
}
+ resolver_->Reset();
}
-bool WinNativeWindow::IsValid() { return hwnd_ != nullptr; }
+void WinNativeWindow::Close() { ::DestroyWindow(hwnd_); }
-void WinNativeWindow::SetDeleteThisOnDestroy(bool value) {
- delete_this_on_destroy_ = value;
-}
-
-void WinNativeWindow::Close() {
- if (IsValid()) DestroyWindow(hwnd_);
-}
-
-bool WinNativeWindow::IsVisible() {
- if (IsValid()) return ::IsWindowVisible(hwnd_);
- return false;
-}
+bool WinNativeWindow::IsVisible() { return ::IsWindowVisible(hwnd_); }
void WinNativeWindow::SetVisible(bool is_visible) {
- if (!IsValid()) return;
is_visible ? ShowWindow(hwnd_, SW_SHOWNORMAL) : ShowWindow(hwnd_, SW_HIDE);
}
Size WinNativeWindow::GetClientSize() {
- if (!IsValid()) return Size{};
-
const auto pixel_rect = GetClientRectPixel();
return Size(PixelToDipX(pixel_rect.right), PixelToDipY(pixel_rect.bottom));
}
void WinNativeWindow::SetClientSize(const Size& size) {
- if (IsValid()) {
- const auto window_style =
- static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_STYLE));
- const auto window_ex_style =
- static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_EXSTYLE));
-
- RECT rect;
- rect.left = 0;
- rect.top = 0;
- rect.right = DipToPixelX(size.width);
- rect.bottom = DipToPixelY(size.height);
- if (!AdjustWindowRectEx(&rect, window_style, FALSE, window_ex_style))
- throw Win32Error(::GetLastError(),
- "Failed to invoke AdjustWindowRectEx.");
-
- if (!SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
- rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
- throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
- }
+ const auto window_style =
+ static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_STYLE));
+ const auto window_ex_style =
+ static_cast<DWORD>(GetWindowLongPtr(hwnd_, GWL_EXSTYLE));
+
+ RECT rect;
+ rect.left = 0;
+ rect.top = 0;
+ rect.right = DipToPixelX(size.width);
+ rect.bottom = DipToPixelY(size.height);
+ if (!AdjustWindowRectEx(&rect, window_style, FALSE, window_ex_style))
+ throw Win32Error(::GetLastError(), "Failed to invoke AdjustWindowRectEx.");
+
+ if (!SetWindowPos(hwnd_, nullptr, 0, 0, rect.right - rect.left,
+ rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE))
+ throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
}
Rect WinNativeWindow::GetWindowRect() {
- if (!IsValid()) return Rect{};
-
RECT rect;
if (!::GetWindowRect(hwnd_, &rect))
throw Win32Error(::GetLastError(), "Failed to invoke GetWindowRect.");
@@ -117,50 +101,37 @@ Rect WinNativeWindow::GetWindowRect() {
}
void WinNativeWindow::SetWindowRect(const Rect& rect) {
- if (IsValid()) {
- if (!SetWindowPos(hwnd_, nullptr, DipToPixelX(rect.left),
- DipToPixelY(rect.top), DipToPixelX(rect.GetRight()),
- DipToPixelY(rect.GetBottom()), SWP_NOZORDER))
- throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
- }
+ if (!SetWindowPos(hwnd_, nullptr, DipToPixelX(rect.left),
+ DipToPixelY(rect.top), DipToPixelX(rect.GetRight()),
+ DipToPixelY(rect.GetBottom()), SWP_NOZORDER))
+ throw Win32Error(::GetLastError(), "Failed to invoke SetWindowPos.");
}
Point WinNativeWindow::GetMousePosition() {
- if (IsValid()) {
- POINT p;
- if (!::GetCursorPos(&p))
- throw Win32Error(::GetLastError(), "Failed to get cursor position.");
- if (!::ScreenToClient(hwnd_, &p))
- throw Win32Error(::GetLastError(), "Failed to call ScreenToClient.");
- return PiToDip(p);
- }
- return Point{};
+ POINT p;
+ if (!::GetCursorPos(&p))
+ throw Win32Error(::GetLastError(), "Failed to get cursor position.");
+ if (!::ScreenToClient(hwnd_, &p))
+ throw Win32Error(::GetLastError(), "Failed to call ScreenToClient.");
+ return PiToDip(p);
}
bool WinNativeWindow::CaptureMouse() {
- if (IsValid()) {
- ::SetCapture(hwnd_);
- return true;
- }
- return false;
+ ::SetCapture(hwnd_);
+ return true;
}
bool WinNativeWindow::ReleaseMouse() {
- if (IsValid()) {
- const auto result = ::ReleaseCapture();
- return result != 0;
- }
- return false;
+ const auto result = ::ReleaseCapture();
+ return result != 0;
}
void WinNativeWindow::RequestRepaint() {
- if (IsValid()) {
- log::Debug("A repaint is requested.");
- if (!::InvalidateRect(hwnd_, nullptr, FALSE))
- throw Win32Error(::GetLastError(), "Failed to invalidate window.");
- if (!::UpdateWindow(hwnd_))
- throw Win32Error(::GetLastError(), "Failed to update window.");
- }
+ log::Debug("A repaint is requested.");
+ if (!::InvalidateRect(hwnd_, nullptr, FALSE))
+ throw Win32Error(::GetLastError(), "Failed to invalidate window.");
+ if (!::UpdateWindow(hwnd_))
+ throw Win32Error(::GetLastError(), "Failed to update window.");
}
std::unique_ptr<graph::IPainter> WinNativeWindow::BeginPaint() {
@@ -172,8 +143,6 @@ void WinNativeWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
throw std::runtime_error("Can't use a nullptr as cursor.");
}
- if (!IsValid()) return;
-
cursor_ = CheckPlatform<WinCursor>(cursor, GetPlatformId());
if (!::SetClassLongPtrW(hwnd_, GCLP_HCURSOR,
@@ -358,8 +327,10 @@ void WinNativeWindow::OnDestroyInternal() {
application_->GetWindowManager()->UnregisterWindow(hwnd_);
hwnd_ = nullptr;
destroy_event_.Raise(nullptr);
- if (delete_this_on_destroy_)
- application_->InvokeLater([this] { delete this; });
+ if (!sync_flag_) {
+ sync_flag_ = true;
+ delete this;
+ }
}
void WinNativeWindow::OnPaintInternal() {
@@ -438,4 +409,9 @@ void WinNativeWindow::OnCharInternal(wchar_t c) { CRU_UNUSED(c) }
void WinNativeWindow::OnActivatedInternal() {}
void WinNativeWindow::OnDeactivatedInternal() {}
+
+void WinNativeWindowResolver::Reset() {
+ assert(window_); // already reset, can't reset again
+ window_ = nullptr;
+}
} // namespace cru::platform::native::win