aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/cru/platform/gui/Input.h1
-rw-r--r--include/cru/platform/gui/sdl/Input.h12
-rw-r--r--include/cru/platform/gui/sdl/Window.h8
-rw-r--r--src/platform/gui/sdl/CMakeLists.txt1
-rw-r--r--src/platform/gui/sdl/Input.cpp25
-rw-r--r--src/platform/gui/sdl/Window.cpp97
6 files changed, 140 insertions, 4 deletions
diff --git a/include/cru/platform/gui/Input.h b/include/cru/platform/gui/Input.h
index 1dbba850..d731cefa 100644
--- a/include/cru/platform/gui/Input.h
+++ b/include/cru/platform/gui/Input.h
@@ -16,6 +16,7 @@ struct MouseButtons {
constexpr static MouseButton Left = MouseButton::FromOffset(1);
constexpr static MouseButton Middle = MouseButton::FromOffset(2);
constexpr static MouseButton Right = MouseButton::FromOffset(3);
+ constexpr static MouseButton Unknown = MouseButton::FromOffset(4);
};
// Because of the complexity of keyboard layout, I only add code in US keyboard
diff --git a/include/cru/platform/gui/sdl/Input.h b/include/cru/platform/gui/sdl/Input.h
new file mode 100644
index 00000000..c6b97727
--- /dev/null
+++ b/include/cru/platform/gui/sdl/Input.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include <cru/platform/gui/Input.h>
+
+#include <SDL3/SDL_mouse.h>
+#include <SDL3/SDL_keyboard.h>
+
+namespace cru::platform::gui::sdl {
+MouseButton ConvertMouseButton(Uint8 button);
+KeyModifier ConvertKeyModifier(SDL_Keymod keymod);
+KeyModifier GetKeyModifier();
+} // namespace cru::platform::gui::sdl
diff --git a/include/cru/platform/gui/sdl/Window.h b/include/cru/platform/gui/sdl/Window.h
index c9d6505b..9947a1b9 100644
--- a/include/cru/platform/gui/sdl/Window.h
+++ b/include/cru/platform/gui/sdl/Window.h
@@ -4,6 +4,7 @@
#include <cru/platform/GraphicsBase.h>
#include <cru/platform/gui/Window.h>
+#include <SDL3/SDL_events.h>
#include <SDL3/SDL_video.h>
#include <optional>
@@ -53,6 +54,11 @@ class SdlWindow : public SdlResource, public virtual INativeWindow {
*/
void SetWindowRect(const Rect& rect) override;
+ /**
+ * Note: SDL3 doesn't have an API to solely set focus without raising the
+ * window. So this method actually calls SDL_RaiseWindow to raise and set
+ * focus to the window.
+ */
bool RequestFocus() override;
Point GetMousePosition() override;
@@ -85,6 +91,8 @@ class SdlWindow : public SdlResource, public virtual INativeWindow {
void DoUpdateStyleFlag();
void DoUpdateTitle();
+ bool HandleEvent(const SDL_Event* event);
+
private:
SdlUiApplication* application_;
SDL_Window* sdl_window_;
diff --git a/src/platform/gui/sdl/CMakeLists.txt b/src/platform/gui/sdl/CMakeLists.txt
index 3d128580..fa4a6397 100644
--- a/src/platform/gui/sdl/CMakeLists.txt
+++ b/src/platform/gui/sdl/CMakeLists.txt
@@ -1,5 +1,6 @@
add_library(CruPlatformGuiSdl
Base.cpp
+ Input.cpp
UiApplication.cpp
Window.cpp
)
diff --git a/src/platform/gui/sdl/Input.cpp b/src/platform/gui/sdl/Input.cpp
new file mode 100644
index 00000000..1c7b4475
--- /dev/null
+++ b/src/platform/gui/sdl/Input.cpp
@@ -0,0 +1,25 @@
+#include "cru/platform/gui/sdl/Input.h"
+
+namespace cru::platform::gui::sdl {
+MouseButton ConvertMouseButton(Uint8 button) {
+ switch (button) {
+ case SDL_BUTTON_LEFT:
+ return MouseButtons::Left;
+ case SDL_BUTTON_MIDDLE:
+ return MouseButtons::Middle;
+ case SDL_BUTTON_RIGHT:
+ return MouseButtons::Right;
+ }
+ return MouseButtons::Unknown;
+}
+
+KeyModifier ConvertKeyModifier(SDL_Keymod keymod) {
+ KeyModifier result;
+ if (keymod & SDL_KMOD_SHIFT) result |= KeyModifiers::Shift;
+ if (keymod & SDL_KMOD_CTRL) result |= KeyModifiers::Ctrl;
+ if (keymod & SDL_KMOD_ALT) result |= KeyModifiers::Alt;
+ return result;
+}
+
+KeyModifier GetKeyModifier() { return ConvertKeyModifier(SDL_GetModState()); }
+} // namespace cru::cru::platform::gui::sdl
diff --git a/src/platform/gui/sdl/Window.cpp b/src/platform/gui/sdl/Window.cpp
index 659c5246..93c89cbd 100644
--- a/src/platform/gui/sdl/Window.cpp
+++ b/src/platform/gui/sdl/Window.cpp
@@ -5,8 +5,10 @@
#include "cru/platform/graphics/Painter.h"
#include "cru/platform/gui/Window.h"
#include "cru/platform/gui/sdl/Base.h"
+#include "cru/platform/gui/sdl/Input.h"
#include "cru/platform/gui/sdl/UiApplication.h"
+#include <SDL3/SDL_events.h>
#include <SDL3/SDL_video.h>
#include <cassert>
#include <memory>
@@ -129,19 +131,25 @@ void SdlWindow::SetWindowRect(const Rect& rect) {
bool SdlWindow::RequestFocus() {
if (!sdl_window_) return false;
- NotImplemented();
+ auto result = SDL_RaiseWindow(sdl_window_);
+ CheckSdlReturn(SDL_SyncWindow(sdl_window_));
+ return result;
}
Point SdlWindow::GetMousePosition() { NotImplemented(); }
bool SdlWindow::CaptureMouse() {
if (!sdl_window_) return false;
- NotImplemented();
+ // SDL_SetWindowMouseGrab confines mouse in the window, should we really call
+ // it?
+ return true;
}
bool SdlWindow::ReleaseMouse() {
if (!sdl_window_) return false;
- NotImplemented();
+ // SDL_SetWindowMouseGrab confines mouse in the window, should we really call
+ // it?
+ return true;
}
void SdlWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
@@ -151,7 +159,8 @@ void SdlWindow::SetCursor(std::shared_ptr<ICursor> cursor) {
void SdlWindow::SetToForeground() {
SetVisibility(WindowVisibilityType::Show);
- NotImplemented();
+ CheckSdlReturn(SDL_RaiseWindow(sdl_window_));
+ CheckSdlReturn(SDL_SyncWindow(sdl_window_));
}
void SdlWindow::RequestRepaint() {
@@ -205,6 +214,8 @@ void SdlWindow::DoCreateWindow() {
throw SdlException("Failed to create window.");
}
+ CreateEvent_.Raise(nullptr);
+
CheckSdlReturn(
SDL_SetWindowPosition(sdl_window_, client_rect_.left, client_rect_.top));
CheckSdlReturn(SDL_SetWindowParent(
@@ -241,4 +252,82 @@ void SdlWindow::DoUpdateTitle() {
CheckSdlReturn(SDL_SyncWindow(sdl_window_));
}
+namespace {
+NativeMouseButtonEventArgs ConvertMouseButtonEvent(
+ const SDL_MouseButtonEvent& event) {
+ return {
+ ConvertMouseButton(event.button), {event.x, event.y}, GetKeyModifier()};
+}
+} // namespace
+
+bool SdlWindow::HandleEvent(const SDL_Event* event) {
+ switch (event->type) {
+ case SDL_EVENT_WINDOW_MOVED: {
+ client_rect_.left = event->window.data1;
+ client_rect_.top = event->window.data2;
+ return true;
+ }
+ case SDL_EVENT_WINDOW_RESIZED: {
+ client_rect_.width = event->window.data1;
+ client_rect_.height = event->window.data2;
+ ResizeEvent_.Raise(client_rect_.GetSize());
+ return true;
+ }
+ case SDL_EVENT_WINDOW_SHOWN: {
+ VisibilityChangeEvent_.Raise(WindowVisibilityType::Show);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_HIDDEN: {
+ VisibilityChangeEvent_.Raise(WindowVisibilityType::Hide);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_MINIMIZED: {
+ VisibilityChangeEvent_.Raise(WindowVisibilityType::Minimize);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_FOCUS_GAINED: {
+ FocusEvent_.Raise(FocusChangeType::Gain);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_FOCUS_LOST: {
+ FocusEvent_.Raise(FocusChangeType::Lose);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_MOUSE_ENTER: {
+ MouseEnterLeaveEvent_.Raise(MouseEnterLeaveType::Enter);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_MOUSE_LEAVE: {
+ MouseEnterLeaveEvent_.Raise(MouseEnterLeaveType::Leave);
+ return true;
+ }
+ case SDL_EVENT_WINDOW_DESTROYED: {
+ VisibilityChangeEvent_.Raise(WindowVisibilityType::Hide);
+ DestroyEvent_.Raise(nullptr);
+ sdl_window_ = nullptr;
+ return true;
+ }
+ case SDL_EVENT_MOUSE_BUTTON_DOWN: {
+ MouseDownEvent_.Raise(ConvertMouseButtonEvent(event->button));
+ return true;
+ }
+ case SDL_EVENT_MOUSE_BUTTON_UP: {
+ MouseUpEvent_.Raise(ConvertMouseButtonEvent(event->button));
+ return true;
+ }
+ case SDL_EVENT_MOUSE_WHEEL: {
+ const auto& we = event->wheel;
+ if (we.x != 0) {
+ MouseWheelEvent_.Raise({we.x, {we.mouse_x, we.mouse_y}, GetKeyModifier(), true});
+ }
+ if (we.y != 0) {
+ MouseWheelEvent_.Raise({we.y, {we.mouse_x, we.mouse_y}, GetKeyModifier(), false});
+ }
+ return true;
+ }
+ // TODO: Keyboard event.
+ }
+ return false;
+}
+
} // namespace cru::platform::gui::sdl