Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZWidget Wayland backend improvements (Part 1) #115

Merged
merged 9 commits into from
Jun 18, 2024
2 changes: 1 addition & 1 deletion SurrealEngine/EditorApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ int EditorApp::main(std::vector<std::string> args)
Engine engine(info);

auto editorWindow = std::make_unique<EditorMainWindow>();
editorWindow->SetFrameGeometry(Rect::xywh(0.0, 0.0, 1920.0, 1080.0));
editorWindow->SetFrameGeometry(Rect::xywh(0.0, 0.0, 1024.0, 768.0));
editorWindow->Show();

DisplayWindow::RunLoop();
Expand Down
2 changes: 2 additions & 0 deletions Thirdparty/ZWidget/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ set(ZWIDGET_SOURCES
src/window/stub/stub_open_file_dialog.h
src/window/stub/stub_save_file_dialog.cpp
src/window/stub/stub_save_file_dialog.h
src/window/ztimer/ztimer.h
src/window/ztimer/ztimer.cpp
src/systemdialogs/open_folder_dialog.cpp
src/systemdialogs/open_file_dialog.cpp
src/systemdialogs/save_file_dialog.cpp
Expand Down
160 changes: 110 additions & 50 deletions Thirdparty/ZWidget/src/window/wayland/wayland_display_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,46 @@
#include <cstring>

bool WaylandDisplayWindow::exitRunLoop = false;
Size WaylandDisplayWindow::m_ScreenSize = Size(0, 0);
wayland::display_t WaylandDisplayWindow::m_waylandDisplay = wayland::display_t();
std::list<WaylandDisplayWindow*> WaylandDisplayWindow::s_Windows;
std::list<WaylandDisplayWindow*>::iterator WaylandDisplayWindow::s_WindowsIterator;
Size WaylandDisplayWindow::s_ScreenSize = Size(0, 0);
wayland::display_t WaylandDisplayWindow::s_waylandDisplay = wayland::display_t();
wayland::registry_t WaylandDisplayWindow::s_waylandRegistry;
std::vector<WaylandDisplayWindow*> WaylandDisplayWindow::s_Windows;
std::vector<WaylandDisplayWindow*>::iterator WaylandDisplayWindow::s_WindowsIterator;

WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool popupWindow, WaylandDisplayWindow* owner)
: windowHost(windowHost), m_PopupWindow(popupWindow)
{
if (!m_waylandDisplay)
if (!s_waylandDisplay)
throw std::runtime_error("Wayland Display initialization failed!");

m_waylandRegistry = m_waylandDisplay.get_registry();
s_waylandRegistry = s_waylandDisplay.get_registry();

m_waylandRegistry.on_global() = [&](uint32_t name, std::string interface, uint32_t version) {
s_waylandRegistry.on_global() = [&](uint32_t name, std::string interface, uint32_t version) {
if (interface == wayland::compositor_t::interface_name)
m_waylandRegistry.bind(name, m_waylandCompositor, 3);
s_waylandRegistry.bind(name, m_waylandCompositor, 3);
if (interface == wayland::shm_t::interface_name)
m_waylandRegistry.bind(name, m_waylandSHM, version);
s_waylandRegistry.bind(name, m_waylandSHM, version);
if (interface == wayland::output_t::interface_name)
m_waylandRegistry.bind(name, m_waylandOutput, version);
s_waylandRegistry.bind(name, m_waylandOutput, version);
if (interface == wayland::seat_t::interface_name)
m_waylandRegistry.bind(name, m_waylandSeat, 8);
s_waylandRegistry.bind(name, m_waylandSeat, 8);
if (interface == wayland::data_device_manager_t::interface_name)
m_waylandRegistry.bind(name, m_DataDeviceManager, 3);
s_waylandRegistry.bind(name, m_DataDeviceManager, 3);
if (interface == wayland::xdg_wm_base_t::interface_name)
m_waylandRegistry.bind(name, m_XDGWMBase, 1);
s_waylandRegistry.bind(name, m_XDGWMBase, 1);
if (interface == wayland::zxdg_output_manager_v1_t::interface_name)
m_waylandRegistry.bind(name, m_XDGOutputManager, version);
s_waylandRegistry.bind(name, m_XDGOutputManager, version);
if (interface == wayland::zxdg_exporter_v2_t::interface_name)
m_waylandRegistry.bind(name, m_XDGExporter, 1);
s_waylandRegistry.bind(name, m_XDGExporter, 1);
if (interface == wayland::zwp_pointer_constraints_v1_t::interface_name)
m_waylandRegistry.bind(name, m_PointerConstraints, 1);
s_waylandRegistry.bind(name, m_PointerConstraints, 1);
if (interface == wayland::xdg_activation_v1_t::interface_name)
m_waylandRegistry.bind(name, m_XDGActivation, 1);
s_waylandRegistry.bind(name, m_XDGActivation, 1);
if (interface == wayland::zxdg_decoration_manager_v1_t::interface_name)
m_waylandRegistry.bind(name, m_XDGDecorationManager, 1);
s_waylandRegistry.bind(name, m_XDGDecorationManager, 1);
};

m_waylandDisplay.roundtrip();
s_waylandDisplay.roundtrip();

if (!m_XDGWMBase)
throw std::runtime_error("WaylandDisplayWindow: XDG-Shell is required!");
Expand All @@ -58,9 +59,9 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p
m_AppSurface = m_waylandCompositor.create_surface();

m_waylandOutput.on_mode() = [&] (wayland::output_mode flags, int32_t width, int32_t height, int32_t refresh) {
m_ScreenSize = Size(width, height);
s_ScreenSize = Size(width, height);
};

/*
m_DataDevice = m_DataDeviceManager.get_data_device(m_waylandSeat);

m_DataSource = m_DataDeviceManager.create_data_source();
Expand Down Expand Up @@ -106,7 +107,7 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p

dataOffer.proxy_release();
};

*/
m_XDGWMBase.on_ping() = [&] (uint32_t serial) {
m_XDGWMBase.pong(serial);
};
Expand All @@ -120,7 +121,19 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p
{
wayland::xdg_positioner_t popupPositioner = m_XDGWMBase.create_positioner();

popupPositioner.set_anchor(wayland::xdg_positioner_anchor::bottom_left);
popupPositioner.set_anchor_rect(0, 30, 1, 50);
popupPositioner.set_size(100, 100);

m_XDGPopup = m_XDGSurface.get_popup(owner ? owner->m_XDGSurface : nullptr, popupPositioner);

m_XDGPopup.on_configure() = [&] (int32_t x, int32_t y, int32_t width, int32_t height) {
SetClientFrame(Rect::xywh(x, y, width, height));
};

m_XDGPopup.on_popup_done() = [&] () {
OnExitEvent();
};
}
else
{
Expand All @@ -145,7 +158,7 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p
};

m_XDGOutput.on_logical_size() = [&] (int32_t width, int32_t height) {
m_ScreenSize = Size(width, height);
s_ScreenSize = Size(width, height);
m_NeedsUpdate = true;
windowHost->OnWindowGeometryChanged();
};
Expand All @@ -163,7 +176,7 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p

m_AppSurface.commit();

m_waylandDisplay.roundtrip();
s_waylandDisplay.roundtrip();

// These have to be added after the roundtrip
if (m_XDGToplevel)
Expand All @@ -176,16 +189,6 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p
OnExitEvent();
};
}
else
{
m_XDGPopup.on_configure() = [&] (int32_t x, int32_t y, int32_t width, int32_t height) {
SetClientFrame(Rect(x, y, width, height));
};

m_XDGPopup.on_popup_done() = [&] () {
OnExitEvent();
};
}

if (!hasKeyboard)
throw std::runtime_error("No keyboard detected!");
Expand Down Expand Up @@ -254,7 +257,13 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p

OnKeyboardCharEvent(buf);

m_DataDevice.set_selection(m_DataSource, m_KeyboardSerial);
//m_DataDevice.set_selection(m_DataSource, m_KeyboardSerial);
};

m_waylandKeyboard.on_repeat_info() = [&] (int32_t rate, int32_t delay) {
// rate is characters per second, delay is in milliseconds
m_keyboardDelayTimer.SetDuration(ZTimer::Duration(delay));
m_keyboardRepeatTimer.SetDuration(ZTimer::Duration(1000.0 / rate));
};

m_cursorSurface = m_waylandCompositor.create_surface();
Expand Down Expand Up @@ -294,8 +303,28 @@ WaylandDisplayWindow::WaylandDisplayWindow(DisplayWindowHost* windowHost, bool p
OnMouseWheelEvent(InputKey::MouseWheelUp);
};

s_Windows.push_front(this);
s_WindowsIterator = s_Windows.begin();
s_Windows.push_back(this);
s_WindowsIterator = s_Windows.end();

m_keyboardDelayTimer = ZTimer();
m_keyboardRepeatTimer = ZTimer();

m_keyboardDelayTimer.SetCallback([&] () { OnKeyboardDelayEnd(); });
m_keyboardRepeatTimer.SetCallback([&] () { OnKeyboardRepeat(); });

m_keyboardRepeatTimer.SetRepeating(true);

m_previousTime = ZTimer::Clock::now();
m_currentTime = ZTimer::Clock::now();

if (!popupWindow)
{
m_XDGExported = m_XDGExporter.export_toplevel(m_AppSurface);

m_XDGExported.on_handle() = [&] (std::string handleStr) {
OnExportHandleEvent(handleStr);
};
}

this->DrawSurface();
}
Expand All @@ -308,7 +337,7 @@ WaylandDisplayWindow::~WaylandDisplayWindow()
if (m_KeyboardState)
xkb_state_unref(m_KeyboardState);

s_Windows.erase(s_WindowsIterator);
s_WindowsIterator = s_Windows.erase(s_WindowsIterator);
}

void WaylandDisplayWindow::SetWindowTitle(const std::string& text)
Expand All @@ -319,8 +348,6 @@ void WaylandDisplayWindow::SetWindowTitle(const std::string& text)

void WaylandDisplayWindow::SetWindowFrame(const Rect& box)
{
//m_XDGSurface.set_window_geometry((int32_t)box.left(), (int32_t)box.top(),
// (int32_t)box.width, (int32_t)box.height);
// Resizing will be shown on the next commit
CreateBuffers(box.width, box.height);
windowHost->OnWindowGeometryChanged();
Expand Down Expand Up @@ -516,17 +543,21 @@ Point WaylandDisplayWindow::MapToGlobal(const Point& pos) const

void WaylandDisplayWindow::ProcessEvents()
{
while (m_waylandDisplay.dispatch() > 0 )
while (s_waylandDisplay.dispatch() > 0)
{
}
}

void WaylandDisplayWindow::RunLoop()
{
exitRunLoop = false;

while (!exitRunLoop)
{
CheckNeedsUpdate();
if (m_waylandDisplay.dispatch() == -1)
for (auto window: s_Windows)
window->UpdateTimers();
if (s_waylandDisplay.dispatch() == -1)
break;
}
}
Expand All @@ -538,7 +569,7 @@ void WaylandDisplayWindow::ExitLoop()

Size WaylandDisplayWindow::GetScreenSize()
{
return m_ScreenSize;
return s_ScreenSize;
}

void * WaylandDisplayWindow::StartTimer(int timeoutMilliseconds, std::function<void ()> onTimer)
Expand All @@ -562,6 +593,16 @@ void WaylandDisplayWindow::CheckNeedsUpdate()
}
}

void WaylandDisplayWindow::UpdateTimers()
{
m_currentTime = ZTimer::Clock::now();

m_keyboardDelayTimer.Update(m_currentTime - m_previousTime);
m_keyboardRepeatTimer.Update(m_currentTime - m_previousTime);

m_previousTime = m_currentTime;
}

void WaylandDisplayWindow::OnXDGToplevelConfigureEvent(int32_t width, int32_t height)
{
Rect rect = GetWindowFrame();
Expand All @@ -579,17 +620,37 @@ void WaylandDisplayWindow::OnKeyboardKeyEvent(xkb_keysym_t xkbKeySym, wayland::k
{
inputKeyStates[inputKey] = true;
windowHost->OnWindowKeyDown(inputKey);
previousKey = inputKey;
m_keyboardDelayTimer.Start();
}
if (state == wayland::keyboard_key_state::released)
{
inputKeyStates[inputKey] = false;
windowHost->OnWindowKeyUp(inputKey);
m_keyboardDelayTimer.Stop();
m_keyboardRepeatTimer.Stop();
}
}

void WaylandDisplayWindow::OnKeyboardCharEvent(const char* ch)
{
windowHost->OnWindowKeyChar(std::string(ch));
previousChars = std::string(ch);
windowHost->OnWindowKeyChar(previousChars);
}

void WaylandDisplayWindow::OnKeyboardDelayEnd()
{
if (inputKeyStates[previousKey])
m_keyboardRepeatTimer.Start();
}

void WaylandDisplayWindow::OnKeyboardRepeat()
{
if (inputKeyStates[previousKey])
{
windowHost->OnWindowKeyDown(previousKey);
windowHost->OnWindowKeyChar(previousChars);
}
}

void WaylandDisplayWindow::OnMouseEnterEvent(uint32_t serial)
Expand Down Expand Up @@ -626,6 +687,11 @@ void WaylandDisplayWindow::OnMouseWheelEvent(InputKey button)
windowHost->OnWindowMouseWheel(MapToGlobal(m_SurfaceMousePos), button);
}

void WaylandDisplayWindow::OnExportHandleEvent(std::string exportedHandle)
{
m_windowID = exportedHandle;
}

void WaylandDisplayWindow::OnExitEvent()
{
windowHost->OnWindowClose();
Expand Down Expand Up @@ -696,12 +762,6 @@ std::string WaylandDisplayWindow::GetWaylandCursorName(StandardCursor cursor)

std::string WaylandDisplayWindow::GetWaylandWindowID()
{
m_XDGExported.on_handle() = [&] (std::string handleStr) {
m_windowID = handleStr;
};

m_XDGExported = m_XDGExporter.export_toplevel(m_AppSurface);

return m_windowID;
}

Expand Down
Loading
Loading