_wayland big refactor

This commit is contained in:
2025-01-28 01:16:59 +02:00
parent bd83e00dbe
commit 72828a9e58
7 changed files with 851 additions and 1470 deletions

View File

@@ -20,23 +20,13 @@
#include <SDL3/SDL_system.h>
#include <SDL3/SDL_version.h>
#include <SDL3/SDL_locale.h>
#include <SDL3/SDL_timer.h>
#if PLATFORM_LINUX
#include "Engine/Engine/CommandLine.h"
#include "Engine/Platform/MessageBox.h"
#include <SDL3/SDL_messagebox.h>
#endif
#define DefaultDPI 96
Window* draggedWindow = nullptr;
#if PLATFORM_WINDOWS
extern Float2 draggedWindowStartPosition;
extern Float2 draggedWindowMousePosition;
#endif
uint32 SDLPlatform::DraggedWindowId = 0;
namespace
{
int32 SystemDpi = 96;
@@ -83,7 +73,7 @@ bool SDLPlatform::Init()
SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "1");
//if (InitPlatform())
//if (InitInternal())
// return true;
if (!SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
@@ -106,7 +96,7 @@ bool SDLPlatform::Init()
}
SDL_free(locales);
if (InitPlatform())
if (InitInternal())
return true;
if (UsesWindows() || UsesX11())
@@ -143,139 +133,11 @@ void SDLPlatform::LogInfo()
LOG(Info, "SDL video driver: {}", String(SDL_GetCurrentVideoDriver()));
}
bool SDLPlatform::CheckWindowDragging(Window* window, WindowHitCodes hit)
{
bool handled = false;
window->OnLeftButtonHit(hit, handled);
if (handled)
DraggedWindowId = window->_windowId;
return handled;
}
void SDLPlatform::Tick()
{
SDLInput::Update();
#if false
if (DraggedWindowId != 0)
{
Float2 mousePos;
auto buttons = SDL_GetGlobalMouseState(&mousePos.X, &mousePos.Y);
if (!(buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)))
{
Window* window = nullptr;
WindowsManager::WindowsLocker.Lock();
for (int32 i = 0; i < WindowsManager::Windows.Count(); i++)
{
if (WindowsManager::Windows[i]->_windowId == DraggedWindowId)
{
window = WindowsManager::Windows[i];
break;
}
}
WindowsManager::WindowsLocker.Unlock();
if (window != nullptr)
{
int top, left, bottom, right;
SDL_GetWindowBordersSize(window->_window, &top, &left, &bottom, &right);
mousePos += Float2(static_cast<float>(left), static_cast<float>(-top));
Input::Mouse->OnMouseUp(mousePos, MouseButton::Left, window);
}
DraggedWindowId = 0;
}
else
{
#if PLATFORM_LINUX
String dockHintWindow("DockHint.Window");
Window* window = nullptr;
WindowsManager::WindowsLocker.Lock();
for (int32 i = 0; i < WindowsManager::Windows.Count(); i++)
{
if (WindowsManager::Windows[i]->_title.Compare(dockHintWindow) == 0)
//if (WindowsManager::Windows[i]->_windowId == DraggedWindowId)
{
window = WindowsManager::Windows[i];
break;
}
}
WindowsManager::WindowsLocker.Unlock();
if (window != nullptr)
{
int top, left, bottom, right;
SDL_GetWindowBordersSize(window->_window, &top, &left, &bottom, &right);
mousePos += Float2(static_cast<float>(left), static_cast<float>(-top));
Input::Mouse->OnMouseMove(mousePos, window);
}
#endif
}
}
#endif
#if PLATFORM_WINDOWS
auto watch = [](void* userdata, SDL_Event* event) -> bool
{
Window* draggedWindow = *(Window**)userdata;
if (draggedWindow == nullptr)
return true;
// When the window is being dragged on Windows, the internal message loop is blocking
// the SDL event queue. We need to handle all relevant events in this event watch callback
// to ensure dragging related functionality doesn't break due to engine not getting updated.
// This also happens to fix the engine freezing during the dragging operation.
SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
if (event->type == SDL_EVENT_WINDOW_EXPOSED)
{
// The internal timer is sending exposed events every ~16ms
Engine::OnUpdate();//Scripting::Update(); // For docking updates
Engine::OnDraw();
return false;
}
else if (event->type == SDL_EVENT_MOUSE_BUTTON_DOWN)
{
SDLWindow* window = SDLWindow::GetWindowFromEvent(*event);
if (window)
{
bool result = false;
window->OnLeftButtonHit(WindowHitCodes::Caption, result);
//if (result)
// return false;
window->HandleEvent(*event);
}
return false;
}
else if (event->type == SDL_EVENT_WINDOW_MOVED)
{
Float2 start = draggedWindowStartPosition;
Float2 newPos = Float2(static_cast<float>(event->window.data1), static_cast<float>(event->window.data2));
Float2 offset = newPos - start;
Float2 mousePos = draggedWindowMousePosition;
SDL_Event mouseMovedEvent { 0 };
mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION;
mouseMovedEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow());
mouseMovedEvent.motion.timestamp = SDL_GetTicksNS();
mouseMovedEvent.motion.state = SDL_BUTTON_LEFT;
mouseMovedEvent.motion.x = mousePos.X;
mouseMovedEvent.motion.y = mousePos.Y;
if (window)
window->HandleEvent(mouseMovedEvent);
if (window)
window->HandleEvent(*event);
return false;
}
if (window)
window->HandleEvent(*event);
return true;
};
SDL_AddEventWatch(watch, &draggedWindow);
#endif
PreHandleEvents();
SDL_PumpEvents();
SDL_Event events[32];
@@ -288,34 +150,10 @@ void SDLPlatform::Tick()
else if (events[i].type >= SDL_EVENT_JOYSTICK_AXIS_MOTION && events[i].type <= SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED)
SDLInput::HandleEvent(nullptr, events[i]);
else
SDLPlatform::HandleEvent(events[i]);
HandleEvent(events[i]);
}
#if PLATFORM_WINDOWS
SDL_RemoveEventWatch(watch, &draggedWindow);
#endif
// Handle Windows and X11 window dragging release
if (draggedWindow != nullptr)
{
Float2 mousePosition;
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
bool buttonReleased = (buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) == 0;
if (buttonReleased || UsesWindows())
{
// Send simulated mouse up event
SDL_Event buttonUpEvent { 0 };
buttonUpEvent.motion.type = SDL_EVENT_MOUSE_BUTTON_UP;
buttonUpEvent.button.down = false;
buttonUpEvent.motion.windowID = SDL_GetWindowID(draggedWindow->GetSDLWindow());
buttonUpEvent.motion.timestamp = SDL_GetTicksNS();
buttonUpEvent.motion.state = SDL_BUTTON_LEFT;
buttonUpEvent.button.clicks = 1;
buttonUpEvent.motion.x = mousePosition.X;
buttonUpEvent.motion.y = mousePosition.Y;
draggedWindow->HandleEvent(buttonUpEvent);
draggedWindow = nullptr;
}
}
PostHandleEvents();
}
bool SDLPlatform::HandleEvent(SDL_Event& event)
@@ -428,162 +266,4 @@ Window* SDLPlatform::CreateWindow(const CreateWindowSettings& settings)
return New<SDLWindow>(settings);
}
#if PLATFORM_LINUX
DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
StringAnsi textAnsi(text);
StringAnsi captionAnsi(caption);
SDL_MessageBoxData data;
SDL_MessageBoxButtonData dataButtons[3];
data.window = parent ? static_cast<SDLWindow*>(parent)->_window : nullptr;
data.title = captionAnsi.GetText();
data.message = textAnsi.GetText();
data.colorScheme = nullptr;
switch (icon)
{
case MessageBoxIcon::Error:
case MessageBoxIcon::Hand:
case MessageBoxIcon::Stop:
data.flags |= SDL_MESSAGEBOX_ERROR;
break;
case MessageBoxIcon::Asterisk:
case MessageBoxIcon::Information:
case MessageBoxIcon::Question:
data.flags |= SDL_MESSAGEBOX_INFORMATION;
break;
case MessageBoxIcon::Exclamation:
case MessageBoxIcon::Warning:
data.flags |= SDL_MESSAGEBOX_WARNING;
break;
default:
break;
}
switch (buttons)
{
case MessageBoxButtons::AbortRetryIgnore:
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::Abort,
"Abort"
};
dataButtons[1] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
(int)DialogResult::Retry,
"Retry"
};
dataButtons[2] =
{
0,
(int)DialogResult::Ignore,
"Ignore"
};
data.numbuttons = 3;
break;
case MessageBoxButtons::OK:
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::OK,
"OK"
};
data.numbuttons = 1;
break;
case MessageBoxButtons::OKCancel:
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
(int)DialogResult::OK,
"OK"
};
dataButtons[1] =
{
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::Cancel,
"Cancel"
};
data.numbuttons = 2;
break;
case MessageBoxButtons::RetryCancel:
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
(int)DialogResult::Retry,
"Retry"
};
dataButtons[1] =
{
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::Cancel,
"Cancel"
};
data.numbuttons = 2;
break;
case MessageBoxButtons::YesNo:
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
(int)DialogResult::Yes,
"Yes"
};
dataButtons[1] =
{
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::No,
"No"
};
data.numbuttons = 2;
break;
case MessageBoxButtons::YesNoCancel:
{
dataButtons[0] =
{
SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT,
(int)DialogResult::Yes,
"Yes"
};
dataButtons[1] =
{
0,
(int)DialogResult::No,
"No"
};
dataButtons[2] =
{
SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT,
(int)DialogResult::Cancel,
"Cancel"
};
data.numbuttons = 3;
break;
}
default:
break;
}
data.buttons = dataButtons;
int result = -1;
if (!SDL_ShowMessageBox(&data, &result))
{
#if PLATFORM_LINUX
// Fallback to native messagebox implementation in case some system fonts are missing
if (SDLPlatform::UsesX11())
{
LOG(Warning, "Failed to show SDL message box: {0}", String(SDL_GetError()));
return ShowFallback(parent, text, caption, buttons, icon);
}
#endif
LOG(Error, "Failed to show SDL message box: {0}", String(SDL_GetError()));
return DialogResult::Abort;
}
if (result < 0)
return DialogResult::None;
return (DialogResult)result;
}
#endif
#endif