_wayland big refactor
This commit is contained in:
@@ -519,17 +519,6 @@ bool SDLInput::HandleEvent(SDLWindow* window, SDL_Event& event)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/*case SDL_EVENT_DROP_POSITION:
|
||||
{
|
||||
// We are not receiving mouse motion events during drag-and-drop
|
||||
auto dpiScale = window->GetDpiScale();
|
||||
//const Float2 mousePos(event.drop.x * dpiScale, event.drop.y * dpiScale);// = window->ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
Float2 mousePos = window->ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
if (window != Engine::MainWindow)
|
||||
mousePos = window->GetPosition() - mousePos;
|
||||
Input::Mouse->OnMouseMove(mousePos, window);
|
||||
return true;
|
||||
}*/
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
{
|
||||
Input::Mouse->OnMouseLeave(window);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -98,7 +98,7 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
#undef GET_WINDOW_WITH_HWND
|
||||
}
|
||||
|
||||
bool SDLPlatform::InitPlatform()
|
||||
bool SDLPlatform::InitInternal()
|
||||
{
|
||||
// Workaround required for handling window dragging events properly
|
||||
SDL_SetWindowsMessageHook(&EventMessageHook, nullptr);
|
||||
@@ -109,6 +109,179 @@ bool SDLPlatform::InitPlatform()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventFilterCallback(void* userdata, SDL_Event* event)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void SDLPlatform::PreHandleEvents()
|
||||
{
|
||||
SDL_AddEventWatch(EventFilterCallback, &draggedWindow);
|
||||
}
|
||||
|
||||
void SDLPlatform::PostHandleEvents()
|
||||
{
|
||||
SDL_RemoveEventWatch(watch, &draggedWindow);
|
||||
|
||||
// Handle window dragging release here
|
||||
if (draggedWindow != nullptr)
|
||||
{
|
||||
Float2 mousePosition;
|
||||
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
bool SDLWindow::HandleEventInternal(SDL_Event& event)
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_WINDOW_DESTROYED:
|
||||
{
|
||||
#if USE_EDITOR
|
||||
// Disable file dropping
|
||||
if (_settings.AllowDragAndDrop)
|
||||
{
|
||||
const auto result = RevokeDragDrop((HWND)_handle);
|
||||
if (result != S_OK)
|
||||
LOG(Warning, "Window drag and drop service error: 0x{0:x}:{1}", result, 2);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||
{
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
if (SkipMaximizeEventsCount > 0)
|
||||
{
|
||||
SkipMaximizeEventsCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_settings.HasBorder && _settings.HasSizingFrame)
|
||||
{
|
||||
// Restore the window back to previous state
|
||||
SDL_RestoreWindow(_window);
|
||||
|
||||
// Remove the resizable flags from borderless windows and maximize the window again
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_MaximizeWindow(_window);
|
||||
|
||||
// Re-enable the resizable borderless flags
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
// The next SDL_EVENT_WINDOW_RESTORED and SDL_EVENT_WINDOW_MAXIMIZED events should be ignored
|
||||
SkipMaximizeEventsCount = 2;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
{
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
if (SkipMaximizeEventsCount > 0)
|
||||
{
|
||||
SkipMaximizeEventsCount--;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
{
|
||||
if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID)
|
||||
{
|
||||
// Send the button event to dragged window as well
|
||||
Float2 mousePos = ClientToScreen({ event.button.x, event.button.y });
|
||||
Float2 clientPos = draggedWindow->ScreenToClient(mousePos);
|
||||
|
||||
SDL_Event event2 = event;
|
||||
event2.button.windowID = draggedWindow->_windowId;
|
||||
event2.button.x = clientPos.X;
|
||||
event2.button.y = clientPos.Y;
|
||||
|
||||
SDLInput::HandleEvent(draggedWindow, event2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDLPlatform::UsesWindows()
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -7,21 +7,18 @@
|
||||
#include "Engine/Platform/Base/Enums.h"
|
||||
#if PLATFORM_WINDOWS
|
||||
#include "Engine/Platform/Windows/WindowsPlatform.h"
|
||||
typedef struct tagMSG MSG;
|
||||
#elif PLATFORM_LINUX
|
||||
#include "Engine/Platform/Linux/LinuxPlatform.h"
|
||||
union _XEvent;
|
||||
#else
|
||||
#endif
|
||||
|
||||
class SDLWindow;
|
||||
union SDL_Event;
|
||||
#if PLATFORM_WINDOWS
|
||||
typedef struct tagMSG MSG;
|
||||
#elif PLATFORM_LINUX
|
||||
union _XEvent;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// The Windows platform implementation and application management utilities.
|
||||
/// The SDL platform implementation and application management utilities.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API SDLPlatform
|
||||
#if PLATFORM_WINDOWS
|
||||
@@ -38,22 +35,20 @@ class FLAXENGINE_API SDLPlatform
|
||||
friend SDLWindow;
|
||||
|
||||
private:
|
||||
static uint32 DraggedWindowId;
|
||||
|
||||
private:
|
||||
static bool InitPlatform();
|
||||
static bool InitInternal();
|
||||
#if PLATFORM_LINUX
|
||||
static bool InitPlatformX11(void* display);
|
||||
static bool InitX11(void* display);
|
||||
#endif
|
||||
static bool HandleEvent(SDL_Event& event);
|
||||
#if PLATFORM_WINDOWS
|
||||
static bool __cdecl EventMessageHook(void* userdata, MSG* msg);
|
||||
static bool EventMessageHook(void* userdata, MSG* msg);
|
||||
#elif PLATFORM_LINUX
|
||||
static bool __cdecl X11EventHook(void *userdata, _XEvent *xevent);
|
||||
static bool X11EventHook(void* userdata, _XEvent* xevent);
|
||||
#endif
|
||||
static void PreHandleEvents();
|
||||
static void PostHandleEvents();
|
||||
|
||||
public:
|
||||
static bool CheckWindowDragging(Window* window, WindowHitCodes hit);
|
||||
#if PLATFORM_LINUX
|
||||
static void* GetXDisplay();
|
||||
#endif
|
||||
|
||||
@@ -37,14 +37,12 @@
|
||||
#include <wayland/xdg-toplevel-drag-v1.h>
|
||||
#include <wayland/xdg-shell.h>
|
||||
|
||||
extern Dictionary<wl_surface*, SDLWindow*> SurfaceToWindowMap;
|
||||
extern SDLWindow* LastPointerWindow;
|
||||
extern Int2 LastPointerPosition;
|
||||
extern uint32 ImplicitGrabSerial;
|
||||
extern xdg_toplevel_drag_manager_v1* DragManager;
|
||||
extern wl_seat* WaylandSeat;
|
||||
extern wl_data_device_manager* WaylandDataDeviceManager;
|
||||
extern xdg_wm_base* WaylandXdgWmBase;
|
||||
extern bool waylandDraggingActive;
|
||||
extern bool waylandDraggingWindow;
|
||||
extern StringView waylandDraggingData;
|
||||
@@ -74,43 +72,6 @@ bool IsPopupWindow(WindowType type)
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
class SDLDropFilesData : public IGuiData
|
||||
{
|
||||
public:
|
||||
Array<String> Files;
|
||||
|
||||
Type GetType() const override
|
||||
{
|
||||
return Type::Files;
|
||||
}
|
||||
String GetAsText() const override
|
||||
{
|
||||
return String::Empty;
|
||||
}
|
||||
void GetAsFiles(Array<String>* files) const override
|
||||
{
|
||||
files->Add(Files);
|
||||
}
|
||||
};
|
||||
|
||||
class SDLDropTextData : public IGuiData
|
||||
{
|
||||
public:
|
||||
StringView Text;
|
||||
|
||||
Type GetType() const override
|
||||
{
|
||||
return Type::Text;
|
||||
}
|
||||
String GetAsText() const override
|
||||
{
|
||||
return String(Text);
|
||||
}
|
||||
void GetAsFiles(Array<String>* files) const override
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
: WindowBase(settings)
|
||||
, _handle(nullptr)
|
||||
@@ -152,8 +113,8 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
flags |= SDL_WINDOW_TRANSPARENT;
|
||||
|
||||
// Disable parenting of child windows as those are always on top of the parent window and never show up in taskbar
|
||||
//if (_settings.Parent != nullptr && (_settings.Type != WindowType::Tooltip && _settings.Type != WindowType::Popup))
|
||||
// _settings.Parent = nullptr;
|
||||
if (_settings.Parent != nullptr && (_settings.Type != WindowType::Tooltip && _settings.Type != WindowType::Popup))
|
||||
_settings.Parent = nullptr;
|
||||
|
||||
// The window position needs to be relative to the parent window
|
||||
Int2 relativePosition(Math::TruncToInt(settings.Position.X), Math::TruncToInt(settings.Position.Y));
|
||||
@@ -212,10 +173,6 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
if (xdndAware != 0)
|
||||
X11::XChangeProperty(xDisplay, (X11::Window)_handle, xdndAware, (X11::Atom)4, 32, PropModeReplace, (unsigned char*)&xdndVersion, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Wayland
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -225,7 +182,7 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
#if PLATFORM_LINUX
|
||||
// Initialize using the shared Display instance from SDL
|
||||
if (SDLPlatform::UsesX11() && SDLPlatform::GetXDisplay() == nullptr)
|
||||
SDLPlatform::InitPlatformX11(GetX11Display());
|
||||
SDLPlatform::InitX11(GetX11Display());
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -287,10 +244,7 @@ SDLWindow::~SDLWindow()
|
||||
|
||||
if (_window == nullptr)
|
||||
return;
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
SurfaceToWindowMap.RemoveValue(this);
|
||||
#endif
|
||||
|
||||
SDL_StopTextInput(_window);
|
||||
SDL_DestroyWindow(_window);
|
||||
|
||||
@@ -391,6 +345,10 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
if (_isClosing)
|
||||
return;
|
||||
|
||||
// Platform specific event handling
|
||||
if (HandleEventInternal(event))
|
||||
return;
|
||||
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED:
|
||||
@@ -400,16 +358,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
}
|
||||
case SDL_EVENT_WINDOW_DESTROYED:
|
||||
{
|
||||
#if USE_EDITOR && PLATFORM_WINDOWS
|
||||
// Disable file dropping
|
||||
if (_settings.AllowDragAndDrop)
|
||||
{
|
||||
const auto result = RevokeDragDrop((HWND)_handle);
|
||||
if (result != S_OK)
|
||||
LOG(Warning, "Window drag and drop service error: 0x{0:x}:{1}", result, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Quit
|
||||
#if PLATFORM_WINDOWS
|
||||
PostQuitMessage(0);
|
||||
@@ -438,22 +386,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
{
|
||||
_cachedClientRectangle.Location = Float2(static_cast<float>(event.window.data1), static_cast<float>(event.window.data2));
|
||||
#if PLATFORM_LINUX
|
||||
if (SDLPlatform::UsesX11())
|
||||
{
|
||||
// X11 doesn't report any mouse events when mouse is over the caption area, send a simulated event instead...
|
||||
Float2 mousePosition;
|
||||
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0 && draggedWindow == nullptr)
|
||||
{
|
||||
// TODO: verify mouse position, window focus
|
||||
bool result = false;
|
||||
OnLeftButtonHit(WindowHitCodes::Caption, result);
|
||||
if (result)
|
||||
draggedWindow = this;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_HIT_TEST:
|
||||
@@ -471,46 +403,11 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
_minimized = false;
|
||||
_maximized = true;
|
||||
|
||||
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
if (SkipMaximizeEventsCount > 0)
|
||||
{
|
||||
SkipMaximizeEventsCount--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_settings.HasBorder && _settings.HasSizingFrame)
|
||||
{
|
||||
// Restore the window back to previous state
|
||||
SDL_RestoreWindow(_window);
|
||||
|
||||
// Remove the resizable flags from borderless windows and maximize the window again
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_MaximizeWindow(_window);
|
||||
|
||||
// Re-enable the resizable borderless flags
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
// The next SDL_EVENT_WINDOW_RESTORED and SDL_EVENT_WINDOW_MAXIMIZED events should be ignored
|
||||
SkipMaximizeEventsCount = 2;
|
||||
}
|
||||
#endif
|
||||
CheckForWindowResize();
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
{
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
if (SkipMaximizeEventsCount > 0)
|
||||
{
|
||||
SkipMaximizeEventsCount--;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_maximized)
|
||||
{
|
||||
_maximized = false;
|
||||
@@ -574,173 +471,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if PLATFORM_LINUX
|
||||
case SDL_EVENT_CLIPBOARD_UPDATE:
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_CLIPBOARD_UPDATE");
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_BEGIN:
|
||||
case SDL_EVENT_DROP_POSITION:
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
case SDL_EVENT_DROP_TEXT:
|
||||
case SDL_EVENT_DROP_COMPLETE:
|
||||
{
|
||||
if (SDLPlatform::UsesWayland())
|
||||
{
|
||||
static Float2 dragStartPosition = Float2::Zero;
|
||||
|
||||
auto dpiScale = GetDpiScale();
|
||||
//const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
const Float2 mousePos = dragStartPosition + Float2(event.drop.x * dpiScale, event.drop.y * dpiScale);
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
String text(event.drop.data);
|
||||
|
||||
SDLDropTextData dropData;
|
||||
dropData.Text = text;
|
||||
|
||||
if (event.type == SDL_EVENT_DROP_BEGIN || event.type == SDL_EVENT_DROP_POSITION)
|
||||
{
|
||||
// We don't have the drag data during these events...
|
||||
dropData.Text = waylandDraggingData;
|
||||
}
|
||||
|
||||
|
||||
if (event.type == SDL_EVENT_DROP_BEGIN)
|
||||
{
|
||||
dragStartPosition = waylandDraggingWindow ? GetPosition() : Float2::Zero;//Platform::GetMousePosition();
|
||||
LOG(Info, "SDL_EVENT_DROP_BEGIN: {}, mousepos: {}", dragStartPosition, mousePos);
|
||||
OnDragEnter(&dropData, mousePos, effect);
|
||||
}
|
||||
else if (event.type == SDL_EVENT_DROP_POSITION)
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_DROP_POSITION: {}", mousePos);
|
||||
Input::Mouse->OnMouseMove(mousePos, this);
|
||||
OnDragOver(&dropData, mousePos, effect);
|
||||
}
|
||||
else if (event.type == SDL_EVENT_DROP_FILE)
|
||||
OnDragDrop(&dropData, mousePos, effect);
|
||||
else if (event.type == SDL_EVENT_DROP_TEXT)
|
||||
OnDragDrop(&dropData, mousePos, effect);
|
||||
else if (event.type == SDL_EVENT_DROP_COMPLETE)
|
||||
OnDragLeave();
|
||||
/*Focus();
|
||||
Float2 mousePosition;
|
||||
SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
mousePosition = ScreenToClient(mousePosition);
|
||||
|
||||
DragDropEffect effect;
|
||||
SDLDropTextData dropData;
|
||||
OnDragEnter(&dropData, mousePosition, effect);
|
||||
OnDragOver(&dropData, mousePosition, effect);*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*case SDL_EVENT_DROP_POSITION:
|
||||
{
|
||||
auto dpiScale = GetDpiScale();
|
||||
//const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
const Float2 mousePos(event.drop.x * dpiScale, event.drop.y * dpiScale);
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
auto daata = event.drop.data;
|
||||
|
||||
SDLDropTextData dropData;
|
||||
OnDragOver(&dropData, mousePos, effect);
|
||||
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_DROP_FILE");
|
||||
auto dpiScale = GetDpiScale();
|
||||
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
auto daata = event.drop.data;
|
||||
|
||||
SDLDropTextData dropData;
|
||||
OnDragDrop(&dropData, mousePos, effect);
|
||||
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_TEXT:
|
||||
{
|
||||
auto dpiScale = GetDpiScale();
|
||||
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
auto daata = event.drop.data;
|
||||
auto str = String(event.drop.data);
|
||||
|
||||
LOG(Info, "SDL_EVENT_DROP_TEXT: {}", str);
|
||||
|
||||
SDLDropTextData dropData;
|
||||
OnDragDrop(&dropData, mousePos, effect);
|
||||
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_COMPLETE:
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_DROP_COMPLETE");
|
||||
auto dpiScale = GetDpiScale();
|
||||
const Float2 mousePos = ClientToScreen({ event.drop.x * dpiScale, event.drop.y * dpiScale});
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
auto daata = event.drop.data;
|
||||
|
||||
OnDragLeave();
|
||||
|
||||
if (SDLPlatform::UsesWayland())
|
||||
{
|
||||
//_dragOver = false;
|
||||
}
|
||||
return;
|
||||
}*/
|
||||
#endif
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
{
|
||||
#if !PLATFORM_WINDOWS
|
||||
OnDragLeave(); // Check for release of mouse button too?
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
//#if PLATFORM_LINUX
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_MOUSE_BUTTON_DOWN");
|
||||
break;
|
||||
}
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
{
|
||||
#if PLATFORM_LINUX
|
||||
if (SDLPlatform::UsesWayland() && waylandDraggingActive)
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP, dragging");
|
||||
// We are dragging a window, keep the button held down
|
||||
return;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
LOG(Info, "SDL_EVENT_MOUSE_BUTTON_UP: {}", GetTitle());
|
||||
#if PLATFORM_WINDOWS
|
||||
if (draggedWindow != nullptr && draggedWindow->_windowId != event.button.windowID)
|
||||
{
|
||||
// Send the button event to dragged window as well
|
||||
Float2 mousePos = ClientToScreen({ event.button.x, event.button.y });
|
||||
Float2 clientPos = draggedWindow->ScreenToClient(mousePos);
|
||||
|
||||
SDL_Event event2 = event;
|
||||
event2.button.windowID = draggedWindow->_windowId;
|
||||
event2.button.x = clientPos.X;
|
||||
event2.button.y = clientPos.Y;
|
||||
|
||||
SDLInput::HandleEvent(draggedWindow, event2);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
//#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1266,7 +996,6 @@ void SDLWindow::UpdateCursor()
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
// TODO: this needs to be non-blocking in all platforms
|
||||
LOG(Info, "StartDragging {}", offset);
|
||||
|
||||
Float2 dragOffset = offset;
|
||||
if (_settings.HasBorder)
|
||||
@@ -1289,38 +1018,6 @@ DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offse
|
||||
#endif
|
||||
{
|
||||
Show();
|
||||
|
||||
//draggingActive = true;
|
||||
|
||||
/*auto watch = [](void* userdata, SDL_Event* event) -> bool
|
||||
{
|
||||
if (event->window.type == SDL_EVENT_WINDOW_EXPOSED)
|
||||
{
|
||||
LOG(Info, "exposedo");
|
||||
}
|
||||
else
|
||||
LOG(Info, "eventy");*/
|
||||
/*SDLPlatform::Tick();
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();*//*
|
||||
return true;
|
||||
};
|
||||
|
||||
SDL_AddEventWatch(watch, nullptr);*/
|
||||
|
||||
/*while (draggingActive)
|
||||
{
|
||||
SDLPlatform::Tick();
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();
|
||||
|
||||
Platform::Sleep(1);
|
||||
}*/
|
||||
|
||||
//SDL_RemoveEventWatch(watch, nullptr);
|
||||
|
||||
// The mouse up event was ignored earlier, release the button now
|
||||
//Input::Mouse->OnMouseUp(Platform::GetMousePosition(), MouseButton::Left, this);
|
||||
}
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ private:
|
||||
static SDLWindow* GetWindowFromEvent(const SDL_Event& event);
|
||||
static SDLWindow* GetWindowWithSDLWindow(SDL_Window* window);
|
||||
void HandleEvent(SDL_Event& event);
|
||||
bool HandleEventInternal(SDL_Event& event);
|
||||
void CheckForWindowResize();
|
||||
void UpdateCursor();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user