This commit is contained in:
2025-01-28 01:17:16 +02:00
parent 72828a9e58
commit 55de3f8fd3
6 changed files with 236 additions and 251 deletions

View File

@@ -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
@@ -33,45 +32,49 @@
#endif
#elif PLATFORM_LINUX
#include "Engine/Platform/Linux/IncludeX11.h"
#include "Engine/Core/Collections/Dictionary.h"
#include <wayland/xdg-toplevel-drag-v1.h>
#include <wayland/xdg-shell.h>
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 bool waylandDraggingActive;
extern bool waylandDraggingWindow;
extern StringView waylandDraggingData;
#endif
extern Window* draggedWindow;
#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);
bool IsPopupWindow(WindowType type)
{
return type == WindowType::Popup || type == WindowType::Tooltip;
}
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(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)
, _handle(nullptr)
@@ -186,28 +189,6 @@ SDLWindow::SDLWindow(const CreateWindowSettings& settings)
#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(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;
}
SDL_Window* SDLWindow::GetSDLWindow() const
{
return _window;
@@ -528,11 +509,6 @@ void SDLWindow::Hide()
SDL_HideWindow(_window);
#if PLATFORM_LINUX
//if (SDLPlatform::UsesWayland() && _dragOver)
// StopDragging();
#endif
WindowBase::Hide();
}
@@ -544,26 +520,18 @@ void SDLWindow::Minimize()
SDL_MinimizeWindow(_window);
}
#if !PLATFORM_WINDOWS
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
}
#endif
void SDLWindow::SetBorderless(bool isBorderless, bool maximized)
{
if (IsFullscreen())
@@ -577,47 +545,24 @@ 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();
}
#if !PLATFORM_WINDOWS
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
}
#endif
bool SDLWindow::IsClosed() const
{
return _handle == nullptr;
@@ -637,7 +582,7 @@ void SDLWindow::BringToFront(bool force)
SDL_RaiseWindow(_window);
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, activateWhenRaised);
#endif
if (SDLPlatform::UsesX11())
//if (SDLPlatform::UsesX11())
{
auto activateWhenRaised = SDL_GetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED);
SDL_SetHint(SDL_HINT_WINDOW_ACTIVATE_WHEN_RAISED, "0");
@@ -649,12 +594,11 @@ void SDLWindow::BringToFront(bool force)
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);
}
@@ -688,9 +632,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);
}
@@ -710,12 +654,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)
@@ -806,25 +750,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));
@@ -992,35 +926,5 @@ void SDLWindow::UpdateCursor()
SDL_SetCursor(Cursors[index]);
}
//bool draggingActive = false;
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
{
// TODO: this needs to be non-blocking in all platforms
Float2 dragOffset = offset;
if (_settings.HasBorder)
{
#if PLATFORM_LINUX
if (SDLPlatform::UsesWayland() && dragSourceWindow == this)
{
// Wayland includes the decorations in the client-space coordinates, adjust the offset for it.
// Assume the title decoration is 25px thick...
float topOffset = 25.0f;
dragOffset += Float2(0.0f, topOffset);
}
#endif
}
#if PLATFORM_LINUX
if (SDLPlatform::UsesWayland())
DoDragDropWayland(String("notawindow"), dragSourceWindow, dragOffset);
else
#endif
{
Show();
}
return DragDropEffect::None;
}
#endif