_stink
This commit is contained in:
@@ -63,8 +63,6 @@ class LinuxDropTextData : public IGuiData
|
||||
{
|
||||
public:
|
||||
StringView Text;
|
||||
SDLWindow* Window;
|
||||
int64* dragOver;
|
||||
|
||||
Type GetType() const override
|
||||
{
|
||||
@@ -234,17 +232,16 @@ namespace WaylandImpl
|
||||
{
|
||||
public:
|
||||
int64 StartFlag = 0;
|
||||
int64 WaitFlag = 0;
|
||||
int64 ExitFlag = 0;
|
||||
StringView data = nullptr;
|
||||
SDLWindow* window = nullptr;
|
||||
SDLWindow* dragSourceWindow = nullptr;
|
||||
Float2 dragOffset = Float2::Zero;
|
||||
int64 waitFlag = 0;
|
||||
SDLWindow* Window = nullptr;
|
||||
SDLWindow* DragSourceWindow = nullptr;
|
||||
Float2 DragOffset = Float2::Zero;
|
||||
|
||||
// [ThreadPoolTask]
|
||||
bool Run() override
|
||||
{
|
||||
bool dragWindow = data == String("notawindow");
|
||||
bool dragWindow = DraggingWindow;
|
||||
uint32 grabSerial = GrabSerial;
|
||||
|
||||
if (EventQueue == nullptr)
|
||||
@@ -261,21 +258,22 @@ namespace WaylandImpl
|
||||
wl_event_queue_destroy(EventQueue);
|
||||
EventQueue = wl_display_create_queue(WaylandDisplay);
|
||||
|
||||
WrappedDataDeviceManager = (wl_data_device_manager*)wl_proxy_create_wrapper(DataDeviceManager);
|
||||
wl_proxy_set_queue((wl_proxy*)WrappedDataDeviceManager, EventQueue);
|
||||
WrappedDataDeviceManager = static_cast<wl_data_device_manager*>(wl_proxy_create_wrapper(DataDeviceManager));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(WrappedDataDeviceManager), EventQueue);
|
||||
|
||||
DataDevice = wl_data_device_manager_get_data_device(WrappedDataDeviceManager, Seat);
|
||||
wl_data_device_add_listener(DataDevice, &DataDeviceListener, nullptr);
|
||||
wl_display_roundtrip(WaylandDisplay);
|
||||
wl_data_device_set_user_data(DataDevice, dragWindow ? dragSourceWindow : window);
|
||||
WrappedDataDevice = (wl_data_device*)wl_proxy_create_wrapper(DataDevice);
|
||||
wl_proxy_set_queue((wl_proxy*)WrappedDataDevice, EventQueue);
|
||||
wl_data_device_set_user_data(DataDevice, dragWindow ? DragSourceWindow : Window);
|
||||
|
||||
WrappedDataDevice = static_cast<wl_data_device*>(wl_proxy_create_wrapper(DataDevice));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(WrappedDataDevice), EventQueue);
|
||||
}
|
||||
|
||||
// Offer data for consumption, the data source is destroyed elsewhere
|
||||
wl_data_source* dataSource = wl_data_device_manager_create_data_source(WrappedDataDeviceManager);
|
||||
wl_data_source* wrappedDataSource = (wl_data_source*)wl_proxy_create_wrapper(dataSource);
|
||||
wl_proxy_set_queue((wl_proxy*)wrappedDataSource, EventQueue);
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(wrappedDataSource), EventQueue);
|
||||
if (dragWindow)
|
||||
{
|
||||
wl_data_source_offer(dataSource, "flaxengine/window");
|
||||
@@ -288,16 +286,14 @@ namespace WaylandImpl
|
||||
wl_data_source_offer(dataSource, "text/plain;charset=utf-8");
|
||||
wl_data_source_set_actions(dataSource, WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY);
|
||||
}
|
||||
|
||||
LinuxDropTextData textData;
|
||||
textData.Text = *data;
|
||||
textData.Window = window;
|
||||
textData.dragOver = &DragOverFlag;
|
||||
textData.Text = *DraggingData;
|
||||
wl_data_source_add_listener(dataSource, &DataSourceListener, &textData);
|
||||
|
||||
auto _window = window->GetSDLWindow();
|
||||
auto _mainwindow = dragSourceWindow != nullptr ? dragSourceWindow->GetSDLWindow() : _window;
|
||||
wl_surface* originSurface = (wl_surface*)SDL_GetPointerProperty(SDL_GetWindowProperties(_mainwindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr);
|
||||
// Begin dragging operation
|
||||
auto draggedWindow = Window->GetSDLWindow();
|
||||
auto dragStartWindow = DragSourceWindow != nullptr ? DragSourceWindow->GetSDLWindow() : draggedWindow;
|
||||
wl_surface* originSurface = static_cast<wl_surface*>(SDL_GetPointerProperty(SDL_GetWindowProperties(dragStartWindow), SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr));
|
||||
wl_surface* iconSurface = nullptr;
|
||||
wl_data_device_start_drag(WrappedDataDevice, dataSource, originSurface, iconSurface, grabSerial);
|
||||
|
||||
@@ -305,35 +301,35 @@ namespace WaylandImpl
|
||||
|
||||
xdg_toplevel_drag_v1* toplevelDrag = nullptr;
|
||||
xdg_toplevel* wrappedToplevel = nullptr;
|
||||
|
||||
|
||||
while (Platform::AtomicRead(&ExitFlag) == 0)
|
||||
{
|
||||
// Start dispatching events to keep data offers alive
|
||||
if (wl_display_dispatch_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_dispatch_queue failed, errno: {}", errno);
|
||||
if (wl_display_roundtrip_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_roundtrip_queue failed, errno: {}", errno);
|
||||
|
||||
if (wrappedToplevel == nullptr && dragWindow)
|
||||
// Wait until window has showed up
|
||||
if (wrappedToplevel == nullptr && dragWindow && Platform::AtomicRead(&WaitFlag) != 0)
|
||||
{
|
||||
if (Platform::AtomicRead(&waitFlag) != 0)
|
||||
auto toplevel = static_cast<xdg_toplevel*>(SDL_GetPointerProperty(SDL_GetWindowProperties(draggedWindow), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr));
|
||||
if (toplevel != nullptr)
|
||||
{
|
||||
auto toplevel = (xdg_toplevel*)SDL_GetPointerProperty(SDL_GetWindowProperties(_window), SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, nullptr);
|
||||
if (toplevel != nullptr)
|
||||
{
|
||||
wrappedToplevel = (xdg_toplevel*)wl_proxy_create_wrapper(toplevel);
|
||||
wl_proxy_set_queue((wl_proxy*)wrappedToplevel, EventQueue);
|
||||
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
|
||||
// Attach the window to the ongoing drag operation
|
||||
wrappedToplevel = static_cast<xdg_toplevel*>(wl_proxy_create_wrapper(toplevel));
|
||||
wl_proxy_set_queue(reinterpret_cast<wl_proxy*>(wrappedToplevel), EventQueue);
|
||||
toplevelDrag = xdg_toplevel_drag_manager_v1_get_xdg_toplevel_drag(DragManager, dataSource);
|
||||
|
||||
Float2 scaledOffset = dragOffset / window->GetDpiScale();
|
||||
xdg_toplevel_drag_v1_attach(toplevelDrag, wrappedToplevel, (int32)scaledOffset.X, (int32)scaledOffset.Y);
|
||||
}
|
||||
Float2 scaledOffset = DragOffset / Window->GetDpiScale();
|
||||
xdg_toplevel_drag_v1_attach(toplevelDrag, wrappedToplevel, static_cast<int32>(scaledOffset.X), static_cast<int32>(scaledOffset.Y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wl_display_roundtrip_queue(WaylandDisplay, EventQueue) == -1)
|
||||
LOG(Warning, "wl_display_roundtrip_queue failed, errno: {}", errno);
|
||||
|
||||
|
||||
if (toplevelDrag != nullptr)
|
||||
{
|
||||
wl_proxy_wrapper_destroy(wrappedToplevel);
|
||||
@@ -362,17 +358,13 @@ namespace WaylandImpl
|
||||
};
|
||||
}
|
||||
|
||||
namespace Impl
|
||||
{
|
||||
Window* draggedWindow = nullptr;
|
||||
}
|
||||
using namespace Impl;
|
||||
|
||||
// X11
|
||||
Delegate<void*> LinuxPlatform::xEventReceived;
|
||||
|
||||
namespace X11Impl
|
||||
{
|
||||
Window* DraggedWindow = nullptr;
|
||||
|
||||
struct Property
|
||||
{
|
||||
unsigned char* data;
|
||||
@@ -542,7 +534,6 @@ namespace X11Impl
|
||||
return Float2((float)x, (float)y);
|
||||
}
|
||||
}
|
||||
//using namespace X11Impl;
|
||||
|
||||
DragDropEffect Window::DoDragDrop(const StringView& data)
|
||||
{
|
||||
@@ -560,23 +551,22 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
// For drag-and-drop, we need to run another event queue in a separate thread to avoid racing issues
|
||||
// while SDL is dispatching the main Wayland event queue when receiving the data offer from us.
|
||||
|
||||
// Show()?
|
||||
{
|
||||
if (!_visible)
|
||||
{
|
||||
if (_showAfterFirstPaint)
|
||||
{
|
||||
if (RenderTask)
|
||||
RenderTask->Enabled = true;
|
||||
}
|
||||
else
|
||||
SDL_ShowWindow(_window);
|
||||
}
|
||||
WindowBase::Show();
|
||||
}
|
||||
// Show the window without changing the focus
|
||||
//Show();
|
||||
|
||||
//while (true)
|
||||
if (!_visible)
|
||||
{
|
||||
if (_showAfterFirstPaint)
|
||||
{
|
||||
if (RenderTask)
|
||||
RenderTask->Enabled = true;
|
||||
}
|
||||
else
|
||||
SDL_ShowWindow(_window);
|
||||
}
|
||||
WindowBase::Show();
|
||||
|
||||
/*{
|
||||
const double time = Platform::GetTimeSeconds();
|
||||
|
||||
// Update game logic
|
||||
@@ -591,40 +581,37 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
Engine::OnDraw();
|
||||
|
||||
Platform::Sleep(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
WaylandImpl::DraggingActive = true;
|
||||
WaylandImpl::DraggingWindow = data == String("notawindow");
|
||||
WaylandImpl::DraggingData = StringView(data.Get(), data.Length());
|
||||
WaylandImpl::DragOverFlag = 0;
|
||||
|
||||
auto task = New<WaylandImpl::DragDropJob>();
|
||||
task->data = data;
|
||||
task->window = this;
|
||||
task->dragSourceWindow = dragSourceWindow; // Needs to be the parent window when dragging a tab to window
|
||||
task->dragOffset = dragOffset;
|
||||
task->grabSerial = WaylandImpl::GrabSerial;
|
||||
task->Window = this;
|
||||
task->DragSourceWindow = dragSourceWindow; // Needs to be the parent window when dragging a tab to window
|
||||
task->DragOffset = dragOffset;
|
||||
Task::StartNew(task);
|
||||
while (task->GetState() == TaskState::Queued)
|
||||
Platform::Sleep(1);
|
||||
|
||||
while (Platform::AtomicRead(&task->StartFlag) == 0)
|
||||
{
|
||||
Platform::Sleep(1);
|
||||
}
|
||||
|
||||
while (Platform::AtomicRead(&WaylandImpl::DragOverFlag) == 0)
|
||||
{
|
||||
SDLPlatform::Tick();
|
||||
Engine::OnUpdate();//Scripting::Update(); // For docking updates
|
||||
Engine::OnDraw();
|
||||
//if (Platform::AtomicRead(&task->WaitFlag) == 1)
|
||||
Engine::OnDraw();
|
||||
|
||||
// The window needs to be finished showing up before we can start dragging it
|
||||
if (IsVisible() && Platform::AtomicRead(&task->WaitFlag) == 0)
|
||||
{
|
||||
Platform::AtomicStore(&task->WaitFlag, 1);
|
||||
}
|
||||
|
||||
Platform::Sleep(1);
|
||||
|
||||
if (IsVisible() && Platform::AtomicRead(&task->waitFlag) == 0)
|
||||
{
|
||||
Platform::AtomicStore(&task->waitFlag, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The mouse up event was ignored earlier, release the button now
|
||||
@@ -632,9 +619,8 @@ DragDropEffect Window::DoDragDropWayland(const StringView& data, Window* dragSou
|
||||
|
||||
Platform::AtomicStore(&task->ExitFlag, 1);
|
||||
task->Wait();
|
||||
|
||||
|
||||
WaylandImpl::DraggingActive = false;
|
||||
WaylandImpl::DraggingWindow = false;
|
||||
WaylandImpl::DraggingData = nullptr;
|
||||
|
||||
return DragDropEffect::None;
|
||||
@@ -964,7 +950,7 @@ void SDLPlatform::PreHandleEvents()
|
||||
void SDLPlatform::PostHandleEvents()
|
||||
{
|
||||
// Handle window dragging release here
|
||||
if (draggedWindow != nullptr)
|
||||
if (X11Impl::DraggedWindow != nullptr)
|
||||
{
|
||||
Float2 mousePosition;
|
||||
auto buttons = SDL_GetGlobalMouseState(&mousePosition.X, &mousePosition.Y);
|
||||
@@ -975,14 +961,14 @@ void SDLPlatform::PostHandleEvents()
|
||||
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.windowID = SDL_GetWindowID(X11Impl::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;
|
||||
X11Impl::DraggedWindow->HandleEvent(buttonUpEvent);
|
||||
X11Impl::DraggedWindow = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -998,13 +984,13 @@ bool SDLWindow::HandleEventInternal(SDL_Event& event)
|
||||
// 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)
|
||||
if ((buttons & SDL_BUTTON_MASK(SDL_BUTTON_LEFT)) != 0 && X11Impl::DraggedWindow == nullptr)
|
||||
{
|
||||
// TODO: verify mouse position, window focus
|
||||
bool result = false;
|
||||
OnLeftButtonHit(WindowHitCodes::Caption, result);
|
||||
if (result)
|
||||
draggedWindow = this;
|
||||
X11Impl::DraggedWindow = this;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1474,6 +1460,29 @@ bool SDLPlatform::UsesX11()
|
||||
return X11Impl::xDisplay != nullptr;
|
||||
}
|
||||
|
||||
DragDropEffect SDLWindow::DoDragDrop(const StringView& data, const Float2& offset, Window* dragSourceWindow)
|
||||
{
|
||||
if (SDLPlatform::UsesWayland())
|
||||
{
|
||||
Float2 dragOffset = offset;
|
||||
if (_settings.HasBorder && 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);
|
||||
}
|
||||
|
||||
WaylandImpl::DraggingWindow = true;
|
||||
DoDragDropWayland(String(""), dragSourceWindow, dragOffset);
|
||||
WaylandImpl::DraggingWindow = false;
|
||||
//Show();
|
||||
}
|
||||
else
|
||||
Show();
|
||||
return DragDropEffect::None;
|
||||
}
|
||||
|
||||
DialogResult MessageBox::Show(Window* parent, const StringView& text, const StringView& caption, MessageBoxButtons buttons, MessageBoxIcon icon)
|
||||
{
|
||||
StringAnsi textAnsi(text);
|
||||
|
||||
Reference in New Issue
Block a user