Implement new window dragging system
This commit is contained in:
@@ -429,7 +429,7 @@ public:
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Starts drag and drop operation
|
||||
/// Starts a drag and drop operation.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>The result.</returns>
|
||||
@@ -438,6 +438,18 @@ public:
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a window drag and drop operation.
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <param name="offset">The offset for positioning the window from cursor.</param>
|
||||
/// <param name="dragSourceWindow">The window where dragging started.</param>
|
||||
/// <returns>The result.</returns>
|
||||
API_FUNCTION() virtual DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the mouse tracking.
|
||||
/// </summary>
|
||||
|
||||
@@ -1427,11 +1427,7 @@ DragDropEffect Window::DoDragDrop(const StringView& data)
|
||||
StringAnsi dataAnsi(data);
|
||||
LinuxDropTextData dropData;
|
||||
dropData.Text = data;
|
||||
#if !PLATFORM_SDL
|
||||
unsigned long mainWindow = _window;
|
||||
#else
|
||||
unsigned long mainWindow = (unsigned long)_handle;
|
||||
#endif
|
||||
|
||||
// Begin dragging
|
||||
auto screen = X11::XDefaultScreen(xDisplay);
|
||||
|
||||
@@ -405,19 +405,24 @@ public:
|
||||
auto windowHandle = static_cast<SDLWindow*>(window)->_window;
|
||||
if (relativeMode)
|
||||
{
|
||||
oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
||||
relativeModeWindow = window;
|
||||
SDL_GetMouseState(&oldPosition.X, &oldPosition.Y);
|
||||
if (!SDL_CursorVisible())
|
||||
{
|
||||
// Trap the cursor in current location
|
||||
SDL_Rect clipRect = { (int)oldPosition.X, (int)oldPosition.Y, 1, 1 };
|
||||
oldScreenRect = SDL_GetWindowMouseRect(windowHandle);
|
||||
SDL_SetWindowMouseRect(windowHandle, &clipRect);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_SetWindowMouseRect(windowHandle, oldScreenRect);
|
||||
if (relativeModeWindow != window)
|
||||
{
|
||||
// FIXME: When floating game window is focused and editor viewport activated, the relative mode gets stuck
|
||||
return;
|
||||
}
|
||||
SDL_SetWindowMouseRect(windowHandle, nullptr);//oldScreenRect);
|
||||
SDL_WarpMouseInWindow(windowHandle, oldPosition.X, oldPosition.Y);
|
||||
oldScreenRect = nullptr;
|
||||
relativeModeWindow = nullptr;
|
||||
@@ -519,17 +524,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
@@ -1,16 +1,36 @@
|
||||
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
||||
|
||||
|
||||
#if PLATFORM_SDL && PLATFORM_WINDOWS
|
||||
|
||||
#define BORDERLESS_MAXIMIZE_WORKAROUND 2
|
||||
|
||||
#include "SDLPlatform.h"
|
||||
#include "SDLInput.h"
|
||||
|
||||
#include "Engine/Core/Collections/Array.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
|
||||
#include "Engine/Input/Mouse.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <SDL3/SDL_timer.h>
|
||||
|
||||
#if USE_EDITOR
|
||||
#include <oleidl.h>
|
||||
#endif
|
||||
|
||||
#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
|
||||
|
||||
namespace WinImpl
|
||||
{
|
||||
Window* DraggedWindow;
|
||||
Float2 DraggedWindowStartPosition = Float2::Zero;
|
||||
Float2 DraggedWindowMousePosition = Float2::Zero;
|
||||
}
|
||||
|
||||
// The events for releasing the mouse during window dragging are missing, handle the mouse release event here
|
||||
bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
@@ -35,18 +55,59 @@ bool SDLCALL SDLPlatform::EventMessageHook(void* userdata, MSG* msg)
|
||||
{
|
||||
Window* window;
|
||||
GET_WINDOW_WITH_HWND(window, msg->hwnd);
|
||||
|
||||
auto hit = static_cast<WindowHitCodes>(msg->wParam);
|
||||
if (SDLPlatform::CheckWindowDragging(window, hit))
|
||||
return false;
|
||||
WinImpl::DraggedWindow = window;
|
||||
|
||||
WinImpl::DraggedWindowStartPosition = WinImpl::DraggedWindow->GetClientPosition();
|
||||
Float2 mousePos(static_cast<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam))), static_cast<float>(static_cast<LONG>(WINDOWS_GET_Y_LPARAM(msg->lParam))));
|
||||
WinImpl::DraggedWindowMousePosition = mousePos;
|
||||
WinImpl::DraggedWindowMousePosition -= WinImpl::DraggedWindowStartPosition;
|
||||
|
||||
bool result = false;
|
||||
WindowHitCodes hit = static_cast<WindowHitCodes>(msg->wParam);
|
||||
window->OnHitTest(mousePos, hit, result);
|
||||
//if (result && hit != WindowHitCodes::Caption)
|
||||
// return false;
|
||||
|
||||
if (hit == WindowHitCodes::Caption)
|
||||
{
|
||||
SDL_Event event{ 0 };
|
||||
event.button.type = SDL_EVENT_MOUSE_BUTTON_DOWN;
|
||||
event.button.down = true;
|
||||
event.button.timestamp = SDL_GetTicksNS();
|
||||
event.button.windowID = SDL_GetWindowID(window->GetSDLWindow());
|
||||
event.button.button = SDL_BUTTON_LEFT;
|
||||
event.button.clicks = 1;
|
||||
event.button.x = WinImpl::DraggedWindowMousePosition.X;
|
||||
event.button.y = WinImpl::DraggedWindowMousePosition.Y;
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}
|
||||
}
|
||||
/*else if (msg->message == WM_NCLBUTTONUP || msg->message == WM_CAPTURECHANGED)
|
||||
{
|
||||
windowDragging = false;
|
||||
Window* window;
|
||||
GET_WINDOW_WITH_HWND(window, msg->hwnd);
|
||||
|
||||
SDL_Event event{ 0 };
|
||||
event.button.type = SDL_EVENT_MOUSE_BUTTON_UP;
|
||||
event.button.down = false;
|
||||
event.button.timestamp = SDL_GetTicksNS();
|
||||
event.button.windowID = SDL_GetWindowID(window->GetSDLWindow());
|
||||
event.button.button = SDL_BUTTON_LEFT;
|
||||
event.button.clicks = 1;
|
||||
event.button.x = static_cast<float>(static_cast<LONG>(WINDOWS_GET_X_LPARAM(msg->lParam)));
|
||||
event.button.y = static_cast<float>(static_cast<LONG>(WINDOWS_GET_Y_LPARAM(msg->lParam)));
|
||||
|
||||
SDL_PushEvent(&event);
|
||||
}*/
|
||||
return true;
|
||||
#undef GET_WINDOW_WITH_HWND
|
||||
}
|
||||
|
||||
bool SDLPlatform::InitPlatform()
|
||||
bool SDLPlatform::InitInternal()
|
||||
{
|
||||
// Workaround required for handling window dragging events properly for DockHintWindow
|
||||
// Workaround required for handling window dragging events properly
|
||||
SDL_SetWindowsMessageHook(&EventMessageHook, nullptr);
|
||||
|
||||
if (WindowsPlatform::Init())
|
||||
@@ -55,10 +116,177 @@ bool SDLPlatform::InitPlatform()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDLPlatform::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 = WinImpl::DraggedWindowStartPosition;
|
||||
Float2 newPos = Float2(static_cast<float>(event->window.data1), static_cast<float>(event->window.data2));
|
||||
Float2 offset = newPos - start;
|
||||
Float2 mousePos = WinImpl::DraggedWindowMousePosition;
|
||||
|
||||
SDL_Event mouseMovedEvent { 0 };
|
||||
mouseMovedEvent.motion.type = SDL_EVENT_MOUSE_MOTION;
|
||||
mouseMovedEvent.motion.windowID = SDL_GetWindowID(WinImpl::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, &WinImpl::DraggedWindow);
|
||||
}
|
||||
|
||||
void SDLPlatform::PostHandleEvents()
|
||||
{
|
||||
SDL_RemoveEventWatch(EventFilterCallback, &WinImpl::DraggedWindow);
|
||||
|
||||
// Handle window dragging release here
|
||||
if (WinImpl::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(WinImpl::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;
|
||||
WinImpl::DraggedWindow->HandleEvent(buttonUpEvent);
|
||||
WinImpl::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_MOUSE_BUTTON_UP:
|
||||
{
|
||||
if (WinImpl::DraggedWindow != nullptr && WinImpl::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 = WinImpl::DraggedWindow->ScreenToClient(mousePos);
|
||||
|
||||
SDL_Event event2 = event;
|
||||
event2.button.windowID = WinImpl::DraggedWindow->_windowId;
|
||||
event2.button.x = clientPos.X;
|
||||
event2.button.y = clientPos.Y;
|
||||
|
||||
SDLInput::HandleEvent(WinImpl::DraggedWindow, event2);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDLPlatform::UsesWindows()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDLPlatform::UsesWayland()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDLPlatform::UsesX11()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SDLWindow::Focus()
|
||||
{
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "1");
|
||||
|
||||
// Forcing the window to focus causes issues with opening context menus while window is maximized
|
||||
//auto forceRaiseWindow = SDL_GetHint(SDL_HINT_FORCE_RAISEWINDOW);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, "1");
|
||||
|
||||
SDL_RaiseWindow(_window);
|
||||
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, forceRaiseWindow);
|
||||
}
|
||||
|
||||
void SDLPlatform::SetHighDpiAwarenessEnabled(bool enable)
|
||||
{
|
||||
// Other supported values: "permonitor", "permonitorv2"
|
||||
SDL_SetHint("SDL_WINDOWS_DPI_AWARENESS", enable ? "system" : "unaware");
|
||||
}
|
||||
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
Show();
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Engine/Platform/BatteryInfo.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
#include "Engine/Platform/SDL/SDLInput.h"
|
||||
#include "Engine/Engine/Engine.h"
|
||||
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <SDL3/SDL_init.h>
|
||||
@@ -22,14 +23,10 @@
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
#include "Engine/Platform/MessageBox.h"
|
||||
#include <SDL3/SDL_messagebox.h>
|
||||
#endif
|
||||
|
||||
#define DefaultDPI 96
|
||||
|
||||
uint32 SDLPlatform::DraggedWindowId = 0;
|
||||
|
||||
namespace
|
||||
{
|
||||
int32 SystemDpi = 96;
|
||||
@@ -44,7 +41,12 @@ bool SDLPlatform::Init()
|
||||
else if (CommandLine::Options.Wayland)
|
||||
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
|
||||
else
|
||||
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
|
||||
{
|
||||
// Override the X11 preference when running in Wayland session
|
||||
String waylandDisplayEnv;
|
||||
if (!GetEnvironmentVariable(String("WAYLAND_DISPLAY"), waylandDisplayEnv))
|
||||
SDL_SetHintWithPriority(SDL_HINT_VIDEO_DRIVER, "wayland", SDL_HINT_OVERRIDE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
@@ -69,21 +71,15 @@ bool SDLPlatform::Init()
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION, "0");
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, "1"); // Needed for tracking mode
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0"); //
|
||||
SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "8"); // Reduce the default mouse double-click radius
|
||||
|
||||
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); // Disables raw mouse input
|
||||
SDL_SetHint(SDL_HINT_WINDOWS_RAW_KEYBOARD, "1");
|
||||
|
||||
SDL_SetHint(SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY, "1");
|
||||
|
||||
// Disable SDL clipboard support
|
||||
SDL_SetEventEnabled(SDL_EVENT_CLIPBOARD_UPDATE, false);
|
||||
|
||||
// Disable SDL drag and drop support
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_BEGIN, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_COMPLETE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_POSITION, false);
|
||||
//if (InitInternal())
|
||||
// return true;
|
||||
|
||||
if (!SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD))
|
||||
Platform::Fatal(String::Format(TEXT("Failed to initialize SDL: {0}."), String(SDL_GetError())));
|
||||
@@ -104,10 +100,23 @@ bool SDLPlatform::Init()
|
||||
}
|
||||
}
|
||||
SDL_free(locales);
|
||||
|
||||
if (InitPlatform())
|
||||
|
||||
if (InitInternal())
|
||||
return true;
|
||||
|
||||
if (UsesWindows() || UsesX11())
|
||||
{
|
||||
// Disable SDL clipboard support
|
||||
SDL_SetEventEnabled(SDL_EVENT_CLIPBOARD_UPDATE, false);
|
||||
|
||||
// Disable SDL drag and drop support
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_TEXT, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_BEGIN, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_COMPLETE, false);
|
||||
SDL_SetEventEnabled(SDL_EVENT_DROP_POSITION, false);
|
||||
}
|
||||
|
||||
SDLInput::Init();
|
||||
|
||||
SystemDpi = (int)(SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay()) * DefaultDPI);
|
||||
@@ -129,74 +138,12 @@ 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 (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
|
||||
}
|
||||
}
|
||||
|
||||
PreHandleEvents();
|
||||
|
||||
SDL_PumpEvents();
|
||||
SDL_Event events[32];
|
||||
int count = SDL_PeepEvents(events, SDL_arraysize(events), SDL_GETEVENT, SDL_EVENT_FIRST, SDL_EVENT_LAST);
|
||||
@@ -208,8 +155,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]);
|
||||
}
|
||||
|
||||
PostHandleEvents();
|
||||
}
|
||||
|
||||
bool SDLPlatform::HandleEvent(SDL_Event& event)
|
||||
@@ -264,7 +213,18 @@ void SDLPlatform::OpenUrl(const StringView& url)
|
||||
Float2 SDLPlatform::GetMousePosition()
|
||||
{
|
||||
Float2 pos;
|
||||
SDL_GetGlobalMouseState(&pos.X, &pos.Y);
|
||||
if (UsesWayland())
|
||||
{
|
||||
// Wayland doesn't support reporting global mouse position,
|
||||
// use the last known reported position we got from received window events.
|
||||
pos = Input::GetMouseScreenPosition();
|
||||
//if (!SDL_GetGlobalMouseState(&pos.X, &pos.Y))
|
||||
// LOG(Error, "SDL_GetGlobalMouseState() failed");
|
||||
}
|
||||
else if (UsesX11())
|
||||
SDL_GetGlobalMouseState(&pos.X, &pos.Y);
|
||||
else
|
||||
pos = Input::GetMouseScreenPosition();
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -313,176 +273,4 @@ Window* SDLPlatform::CreateWindow(const CreateWindowSettings& settings)
|
||||
return New<SDLWindow>(settings);
|
||||
}
|
||||
|
||||
#if !PLATFORM_LINUX
|
||||
|
||||
bool SDLPlatform::UsesWayland()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDLPlatform::UsesX11()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#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,25 +35,25 @@ 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);
|
||||
static bool SDLPlatform::EventFilterCallback(void* userdata, SDL_Event* event);
|
||||
#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
|
||||
static bool UsesWindows();
|
||||
static bool UsesWayland();
|
||||
static bool UsesX11();
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "Engine/Input/Input.h"
|
||||
#include "Engine/Input/Keyboard.h"
|
||||
#include "Engine/Input/Mouse.h"
|
||||
#include "Engine/Platform/IGuiData.h"
|
||||
#include "Engine/Platform/WindowsManager.h"
|
||||
|
||||
#define NOGDI
|
||||
@@ -26,8 +25,6 @@
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
#include "Engine/Platform/Win32/IncludeWindowsHeaders.h"
|
||||
#define STYLE_RESIZABLE (WS_THICKFRAME | WS_MAXIMIZEBOX)
|
||||
#define BORDERLESS_MAXIMIZE_WORKAROUND 2
|
||||
#if USE_EDITOR
|
||||
#include <oleidl.h>
|
||||
#endif
|
||||
@@ -37,57 +34,44 @@
|
||||
|
||||
#define DefaultDPI 96
|
||||
|
||||
namespace
|
||||
namespace WindowImpl
|
||||
{
|
||||
SDLWindow* LastEventWindow = nullptr;
|
||||
static SDL_Cursor* Cursors[SDL_SYSTEM_CURSOR_COUNT] = { nullptr };
|
||||
#if BORDERLESS_MAXIMIZE_WORKAROUND == 2
|
||||
int SkipMaximizeEventsCount = 0;
|
||||
#endif
|
||||
}
|
||||
using namespace WindowImpl;
|
||||
|
||||
void* GetNativeWindowPointer(SDL_Window* window);
|
||||
SDL_HitTestResult OnWindowHitTest(SDL_Window* win, const SDL_Point* area, void* data);
|
||||
void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset);
|
||||
Int2 GetSDLWindowScreenPosition(const SDLWindow* window);
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y);
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const Int2 position);
|
||||
|
||||
class SDLDropFilesData : public IGuiData
|
||||
bool IsPopupWindow(WindowType type)
|
||||
{
|
||||
public:
|
||||
Array<String> Files;
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
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
|
||||
void* GetNativeWindowPointer(SDL_Window* window)
|
||||
{
|
||||
public:
|
||||
StringView Text;
|
||||
|
||||
Type GetType() const override
|
||||
{
|
||||
return Type::Text;
|
||||
}
|
||||
String GetAsText() const override
|
||||
{
|
||||
return String(Text);
|
||||
}
|
||||
void GetAsFiles(Array<String>* files) const override
|
||||
{
|
||||
}
|
||||
};
|
||||
void* windowPtr;
|
||||
auto props = SDL_GetWindowProperties(window);
|
||||
#if PLATFORM_WINDOWS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif PLATFORM_LINUX
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (windowPtr == nullptr)
|
||||
windowPtr = (void*)SDL_GetNumberProperty(props, SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#elif PLATFORM_MAC
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_ANDROID
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_IOS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
#else
|
||||
static_assert(false, "unsupported platform");
|
||||
#endif
|
||||
return windowPtr;
|
||||
}
|
||||
|
||||
SDLWindow::SDLWindow(const CreateWindowSettings& settings)
|
||||
: WindowBase(settings)
|
||||
@@ -130,8 +114,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));
|
||||
@@ -190,10 +174,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
|
||||
@@ -203,32 +183,10 @@ 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
|
||||
}
|
||||
|
||||
void* GetNativeWindowPointer(SDL_Window* window)
|
||||
{
|
||||
void* windowPtr;
|
||||
auto props = SDL_GetWindowProperties(window);
|
||||
#if PLATFORM_WINDOWS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr);
|
||||
#elif PLATFORM_LINUX
|
||||
windowPtr = SDL_GetPointerProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
if (windowPtr == nullptr)
|
||||
windowPtr = (void*)SDL_GetNumberProperty(SDL_GetWindowProperties(window), SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
||||
#elif PLATFORM_MAC
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_COCOA_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_ANDROID
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_ANDROID_WINDOW_POINTER, nullptr);
|
||||
#elif PLATFORM_IOS
|
||||
windowPtr = SDL_GetPointerProperty(props, SDL_PROP_WINDOW_UIKIT_WINDOW_POINTER, nullptr);
|
||||
#else
|
||||
static_assert(false, "unsupported platform");
|
||||
#endif
|
||||
return windowPtr;
|
||||
}
|
||||
|
||||
SDL_Window* SDLWindow::GetSDLWindow() const
|
||||
{
|
||||
return _window;
|
||||
@@ -265,7 +223,7 @@ SDLWindow::~SDLWindow()
|
||||
|
||||
if (_window == nullptr)
|
||||
return;
|
||||
|
||||
|
||||
SDL_StopTextInput(_window);
|
||||
SDL_DestroyWindow(_window);
|
||||
|
||||
@@ -366,6 +324,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:
|
||||
@@ -375,16 +337,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);
|
||||
@@ -413,16 +365,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)
|
||||
SDLPlatform::CheckWindowDragging(this, WindowHitCodes::Caption);
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_WINDOW_HIT_TEST:
|
||||
@@ -440,46 +382,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;
|
||||
@@ -543,68 +450,6 @@ void SDLWindow::HandleEvent(SDL_Event& event)
|
||||
}
|
||||
return;
|
||||
}
|
||||
#if false
|
||||
case SDL_EVENT_DROP_BEGIN:
|
||||
{
|
||||
Focus();
|
||||
Float2 mousePosition;
|
||||
SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
mousePosition = ScreenToClient(mousePosition);
|
||||
|
||||
DragDropEffect effect;
|
||||
SDLDropTextData dropData;
|
||||
OnDragEnter(&dropData, mousePosition, effect);
|
||||
OnDragOver(&dropData, mousePosition, effect);
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_POSITION:
|
||||
{
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
|
||||
SDLDropTextData dropData;
|
||||
OnDragOver(&dropData, Float2(static_cast<float>(event.drop.x), static_cast<float>(event.drop.y)), effect);
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_FILE:
|
||||
{
|
||||
SDLDropFilesData dropData;
|
||||
dropData.Files.Add(StringAnsi(event.drop.data).ToString()); // TODO: collect multiple files at once?
|
||||
|
||||
Focus();
|
||||
|
||||
Float2 mousePosition;
|
||||
SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
mousePosition = ScreenToClient(mousePosition);
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
OnDragDrop(&dropData, mousePosition, effect);
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_TEXT:
|
||||
{
|
||||
SDLDropTextData dropData;
|
||||
String str = StringAnsi(event.drop.data).ToString();
|
||||
dropData.Text = StringView(str);
|
||||
|
||||
Focus();
|
||||
Float2 mousePosition;
|
||||
SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
mousePosition = ScreenToClient(mousePosition);
|
||||
DragDropEffect effect = DragDropEffect::None;
|
||||
OnDragDrop(&dropData, mousePosition, effect);
|
||||
return;
|
||||
}
|
||||
case SDL_EVENT_DROP_COMPLETE:
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
{
|
||||
#if !PLATFORM_WINDOWS
|
||||
OnDragLeave(); // Check for release of mouse button too?
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -639,9 +484,9 @@ void SDLWindow::Show()
|
||||
else if (_settings.Parent == nullptr)
|
||||
BringToFront();
|
||||
|
||||
// Reused top-most windows (DockHintWindow) doesn't stay on top for some reason
|
||||
if (_settings.IsTopmost && _settings.Type != WindowType::Tooltip)
|
||||
SDL_SetWindowAlwaysOnTop(_window, true);
|
||||
// Reused top-most windows doesn't stay on top for some reason
|
||||
if (_settings.IsTopmost && !IsPopupWindow(_settings.Type))
|
||||
SetIsAlwaysOnTop(true);
|
||||
|
||||
if (_isTrackingMouse)
|
||||
{
|
||||
@@ -678,19 +523,7 @@ void SDLWindow::Maximize()
|
||||
if (!_settings.AllowMaximize)
|
||||
return;
|
||||
|
||||
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_MaximizeWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_MaximizeWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDLWindow::SetBorderless(bool isBorderless, bool maximized)
|
||||
@@ -706,45 +539,18 @@ void SDLWindow::SetBorderless(bool isBorderless, bool maximized)
|
||||
|
||||
BringToFront();
|
||||
|
||||
if (isBorderless)
|
||||
{
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
{
|
||||
Maximize();
|
||||
}
|
||||
else
|
||||
Focus();
|
||||
}
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
Maximize();
|
||||
else
|
||||
{
|
||||
SDL_SetWindowBordered(_window, !isBorderless ? true : false);
|
||||
if (maximized)
|
||||
{
|
||||
Maximize();
|
||||
}
|
||||
else
|
||||
Focus();
|
||||
}
|
||||
|
||||
Focus();
|
||||
|
||||
CheckForWindowResize();
|
||||
}
|
||||
|
||||
void SDLWindow::Restore()
|
||||
{
|
||||
#if PLATFORM_WINDOWS && BORDERLESS_MAXIMIZE_WORKAROUND == 1
|
||||
// Workaround for "SDL_BORDERLESS_RESIZABLE_STYLE" hint not working as expected when maximizing windows
|
||||
auto style = ::GetWindowLong((HWND)_handle, GWL_STYLE);
|
||||
style &= ~STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
|
||||
SDL_RestoreWindow(_window);
|
||||
|
||||
style = ::GetWindowLong((HWND)_handle, GWL_STYLE) | STYLE_RESIZABLE;
|
||||
::SetWindowLong((HWND)_handle, GWL_STYLE, style);
|
||||
#else
|
||||
SDL_RestoreWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDLWindow::IsClosed() const
|
||||
@@ -760,28 +566,19 @@ bool SDLWindow::IsForegroundWindow() const
|
||||
|
||||
void SDLWindow::BringToFront(bool force)
|
||||
{
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "0");
|
||||
SDL_RaiseWindow(_window);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
}
|
||||
|
||||
void SDLWindow::SetClientBounds(const Rectangle& clientArea)
|
||||
{
|
||||
int newX = static_cast<int>(clientArea.GetLeft());
|
||||
int newY = static_cast<int>(clientArea.GetTop());
|
||||
Int2 newPos = Int2(clientArea.GetTopLeft());
|
||||
int newW = static_cast<int>(clientArea.GetWidth());
|
||||
int newH = static_cast<int>(clientArea.GetHeight());
|
||||
|
||||
SetSDLWindowScreenPosition(this, newX, newY);
|
||||
SetSDLWindowScreenPosition(this, newPos);
|
||||
SDL_SetWindowSize(_window, newW, newH);
|
||||
}
|
||||
|
||||
bool IsPopupWindow(WindowType type)
|
||||
{
|
||||
return type == WindowType::Popup || type == WindowType::Tooltip;
|
||||
}
|
||||
|
||||
void GetRelativeWindowOffset(WindowType type, SDLWindow* parentWindow, Int2& positionOffset)
|
||||
{
|
||||
if (!IsPopupWindow(type))
|
||||
@@ -812,9 +609,9 @@ Int2 GetSDLWindowScreenPosition(const SDLWindow* window)
|
||||
return position - relativeOffset;
|
||||
}
|
||||
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const int x, const int y)
|
||||
void SetSDLWindowScreenPosition(const SDLWindow* window, const Int2 position)
|
||||
{
|
||||
Int2 relativePosition(x, y);
|
||||
Int2 relativePosition = position;
|
||||
GetRelativeWindowOffset(window->GetSettings().Type, window->GetSettings().Parent, relativePosition);
|
||||
SDL_SetWindowPosition(window->GetSDLWindow(), relativePosition.X, relativePosition.Y);
|
||||
}
|
||||
@@ -834,12 +631,12 @@ void SDLWindow::SetPosition(const Float2& position)
|
||||
screenPosition += Int2(monitorBounds.GetTopLeft());
|
||||
}
|
||||
|
||||
SetSDLWindowScreenPosition(this, screenPosition.X, screenPosition.Y);
|
||||
SetSDLWindowScreenPosition(this, screenPosition);
|
||||
}
|
||||
|
||||
void SDLWindow::SetClientPosition(const Float2& position)
|
||||
{
|
||||
SetSDLWindowScreenPosition(this, static_cast<int>(position.X), static_cast<int>(position.Y));
|
||||
SetSDLWindowScreenPosition(this, Int2(position));
|
||||
}
|
||||
|
||||
void SDLWindow::SetIsFullscreen(bool isFullscreen)
|
||||
@@ -848,7 +645,7 @@ void SDLWindow::SetIsFullscreen(bool isFullscreen)
|
||||
if (!isFullscreen)
|
||||
{
|
||||
// The window is set to always-on-top for some reason when leaving fullscreen
|
||||
SDL_SetWindowAlwaysOnTop(_window, false);
|
||||
SetIsAlwaysOnTop(false);
|
||||
}
|
||||
|
||||
WindowBase::SetIsFullscreen(isFullscreen);
|
||||
@@ -930,25 +727,15 @@ void SDLWindow::SetOpacity(const float opacity)
|
||||
LOG(Warning, "SDL_SetWindowOpacity failed: {0}", String(SDL_GetError()));
|
||||
}
|
||||
|
||||
#if !PLATFORM_WINDOWS
|
||||
|
||||
void SDLWindow::Focus()
|
||||
{
|
||||
#if PLATFORM_WINDOWS
|
||||
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "1");
|
||||
|
||||
// Forcing the window to focus causes issues with opening context menus while window is maximized
|
||||
//auto forceRaiseWindow = SDL_GetHint(SDL_HINT_FORCE_RAISEWINDOW);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, "1");
|
||||
|
||||
SDL_RaiseWindow(_window);
|
||||
|
||||
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
|
||||
//SDL_SetHint(SDL_HINT_FORCE_RAISEWINDOW, forceRaiseWindow);
|
||||
#else
|
||||
SDL_RaiseWindow(_window);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
String SDLWindow::GetTitle() const
|
||||
{
|
||||
return String(SDL_GetWindowTitle(_window));
|
||||
|
||||
@@ -57,11 +57,12 @@ 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();
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
DragDropEffect DoDragDropWayland(const StringView& data);
|
||||
DragDropEffect DoDragDropWayland(const StringView& data, Window* dragSourceWindow = nullptr, Float2 dragOffset = Float2::Zero);
|
||||
DragDropEffect DoDragDropX11(const StringView& data);
|
||||
#endif
|
||||
|
||||
@@ -104,6 +105,7 @@ public:
|
||||
String GetTitle() const override;
|
||||
void SetTitle(const StringView& title) override;
|
||||
DragDropEffect DoDragDrop(const StringView& data) override;
|
||||
DragDropEffect DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow) override;
|
||||
void StartTrackingMouse(bool useMouseScreenOffset) override;
|
||||
void EndTrackingMouse() override;
|
||||
void StartClippingCursor(const Rectangle& bounds) override;
|
||||
|
||||
Reference in New Issue
Block a user