diff --git a/libraries/ZWidget/include/zwidget/core/widget.h b/libraries/ZWidget/include/zwidget/core/widget.h index a889938c87..69862fdb49 100644 --- a/libraries/ZWidget/include/zwidget/core/widget.h +++ b/libraries/ZWidget/include/zwidget/core/widget.h @@ -177,6 +177,8 @@ private: Widget* CaptureWidget = nullptr; Widget* HoverWidget = nullptr; + StandardCursor CurrentCursor = StandardCursor::arrow; + Widget(const Widget&) = delete; Widget& operator=(const Widget&) = delete; diff --git a/libraries/ZWidget/include/zwidget/window/window.h b/libraries/ZWidget/include/zwidget/window/window.h index 5798e787cd..0539f773f8 100644 --- a/libraries/ZWidget/include/zwidget/window/window.h +++ b/libraries/ZWidget/include/zwidget/window/window.h @@ -162,9 +162,13 @@ public: virtual void ShowCursor(bool enable) = 0; virtual void LockCursor() = 0; virtual void UnlockCursor() = 0; + virtual void CaptureMouse() = 0; + virtual void ReleaseMouseCapture() = 0; virtual void Update() = 0; virtual bool GetKeyState(EInputKey key) = 0; + virtual void SetCursor(StandardCursor cursor) = 0; + virtual Rect GetWindowFrame() const = 0; virtual Size GetClientSize() const = 0; virtual int GetPixelWidth() const = 0; diff --git a/libraries/ZWidget/src/core/widget.cpp b/libraries/ZWidget/src/core/widget.cpp index 56d5e9ef57..9c6dc63190 100644 --- a/libraries/ZWidget/src/core/widget.cpp +++ b/libraries/ZWidget/src/core/widget.cpp @@ -367,14 +367,38 @@ void Widget::UnlockCursor() void Widget::SetCursor(StandardCursor cursor) { + if (CurrentCursor != cursor) + { + CurrentCursor = cursor; + if (HoverWidget == this || CaptureWidget == this) + { + Widget* w = Window(); + if (w) + { + w->DispWindow->SetCursor(CurrentCursor); + } + } + } } void Widget::CaptureMouse() { + Widget* w = Window(); + if (w && w->CaptureWidget != this) + { + w->CaptureWidget = this; + w->DispWindow->CaptureMouse(); + } } void Widget::ReleaseMouseCapture() { + Widget* w = Window(); + if (w && w->CaptureWidget != nullptr) + { + w->CaptureWidget = nullptr; + w->DispWindow->ReleaseMouseCapture(); + } } std::string Widget::GetClipboardText() @@ -487,6 +511,7 @@ void Widget::OnWindowMouseMove(const Point& pos) { if (CaptureWidget) { + DispWindow->SetCursor(CaptureWidget->CurrentCursor); CaptureWidget->OnMouseMove(CaptureWidget->MapFrom(this, pos)); } else @@ -502,6 +527,7 @@ void Widget::OnWindowMouseMove(const Point& pos) HoverWidget = widget; } + DispWindow->SetCursor(widget->CurrentCursor); widget->OnMouseMove(widget->MapFrom(this, pos)); } } diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp index 7806004616..2cb52e2b5b 100644 --- a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.cpp @@ -132,6 +132,18 @@ void SDL2DisplayWindow::UnlockCursor() SDL_ShowCursor(1); } +void SDL2DisplayWindow::CaptureMouse() +{ +} + +void SDL2DisplayWindow::ReleaseMouseCapture() +{ +} + +void SDL2DisplayWindow::SetCursor(StandardCursor cursor) +{ +} + void SDL2DisplayWindow::Update() { SDL_Event event = {}; diff --git a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h index 484ae0a456..fa0e8253cc 100644 --- a/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h +++ b/libraries/ZWidget/src/window/sdl2/sdl2displaywindow.h @@ -24,8 +24,11 @@ public: void ShowCursor(bool enable) override; void LockCursor() override; void UnlockCursor() override; + void CaptureMouse() override; + void ReleaseMouseCapture() override; void Update() override; bool GetKeyState(EInputKey key) override; + void SetCursor(StandardCursor cursor) override; Rect GetWindowFrame() const override; Size GetClientSize() const override; diff --git a/libraries/ZWidget/src/window/win32/win32window.cpp b/libraries/ZWidget/src/window/win32/win32window.cpp index f76df67318..f279bcf3f3 100644 --- a/libraries/ZWidget/src/window/win32/win32window.cpp +++ b/libraries/ZWidget/src/window/win32/win32window.cpp @@ -209,6 +209,16 @@ void Win32Window::UnlockCursor() } } +void Win32Window::CaptureMouse() +{ + SetCapture(WindowHandle); +} + +void Win32Window::ReleaseMouseCapture() +{ + ReleaseCapture(); +} + void Win32Window::Update() { InvalidateRect(WindowHandle, nullptr, FALSE); @@ -219,6 +229,15 @@ bool Win32Window::GetKeyState(EInputKey key) return ::GetKeyState((int)key) & 0x8000; // High bit (0x8000) means key is down, Low bit (0x0001) means key is sticky on (like Caps Lock, Num Lock, etc.) } +void Win32Window::SetCursor(StandardCursor cursor) +{ + if (cursor != CurrentCursor) + { + CurrentCursor = cursor; + UpdateCursor(); + } +} + Rect Win32Window::GetWindowFrame() const { RECT box = {}; @@ -411,7 +430,7 @@ LRESULT Win32Window::OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam) } else { - SetCursor((HCURSOR)LoadImage(0, IDC_ARROW, IMAGE_CURSOR, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED)); + UpdateCursor(); } WindowHost->OnWindowMouseMove(GetLParamPos(lparam)); @@ -511,6 +530,30 @@ LRESULT Win32Window::OnWindowMessage(UINT msg, WPARAM wparam, LPARAM lparam) return DefWindowProc(WindowHandle, msg, wparam, lparam); } +void Win32Window::UpdateCursor() +{ + LPCWSTR cursor = IDC_ARROW; + switch (CurrentCursor) + { + case StandardCursor::arrow: cursor = IDC_ARROW; break; + case StandardCursor::appstarting: cursor = IDC_APPSTARTING; break; + case StandardCursor::cross: cursor = IDC_CROSS; break; + case StandardCursor::hand: cursor = IDC_HAND; break; + case StandardCursor::ibeam: cursor = IDC_IBEAM; break; + case StandardCursor::no: cursor = IDC_NO; break; + case StandardCursor::size_all: cursor = IDC_SIZEALL; break; + case StandardCursor::size_nesw: cursor = IDC_SIZENESW; break; + case StandardCursor::size_ns: cursor = IDC_SIZENS; break; + case StandardCursor::size_nwse: cursor = IDC_SIZENWSE; break; + case StandardCursor::size_we: cursor = IDC_SIZEWE; break; + case StandardCursor::uparrow: cursor = IDC_UPARROW; break; + case StandardCursor::wait: cursor = IDC_WAIT; break; + default: break; + } + + ::SetCursor((HCURSOR)LoadImage(0, cursor, IMAGE_CURSOR, LR_DEFAULTSIZE, LR_DEFAULTSIZE, LR_SHARED)); +} + Point Win32Window::GetLParamPos(LPARAM lparam) const { double dpiscale = GetDpiScale(); diff --git a/libraries/ZWidget/src/window/win32/win32window.h b/libraries/ZWidget/src/window/win32/win32window.h index 74f56f18e2..a0f493c8b2 100644 --- a/libraries/ZWidget/src/window/win32/win32window.h +++ b/libraries/ZWidget/src/window/win32/win32window.h @@ -30,9 +30,14 @@ public: void ShowCursor(bool enable) override; void LockCursor() override; void UnlockCursor() override; + void CaptureMouse() override; + void ReleaseMouseCapture() override; void Update() override; bool GetKeyState(EInputKey key) override; + void SetCursor(StandardCursor cursor) override; + void UpdateCursor(); + Rect GetWindowFrame() const override; Size GetClientSize() const override; int GetPixelWidth() const override; @@ -76,4 +81,6 @@ public: POINT MouseLockPos = {}; HDC PaintDC = 0; + + StandardCursor CurrentCursor = StandardCursor::arrow; };