Skip to content

Commit

Permalink
feat: Adapt to TreeLand's Titlebar protocol
Browse files Browse the repository at this point in the history
Resolve the issues of DTK application crashing and dual title bar in treeland.

Log: Adapt to TreeLand's Titlebar protocol
  • Loading branch information
mhduiy committed Oct 18, 2024
1 parent 8cf037d commit 0ebf8f4
Show file tree
Hide file tree
Showing 14 changed files with 250 additions and 584 deletions.
2 changes: 1 addition & 1 deletion debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Build-Depends: debhelper-compat (= 12), pkg-config,
qtbase5-private-dev, qtbase5-dev-tools, doxygen, graphviz, qttools5-dev,
libdtkcore-dev, librsvg2-dev, libfreeimage-dev, libraw-dev, libgtest-dev, libgmock-dev,
libqt5xdg-dev, libqt5xdgiconloader-dev, cmake, qt5-image-formats-plugins, libqt5waylandclient5-dev,
extra-cmake-modules, qtwayland5-dev-tools, qtwayland5-private-dev, libkf5wayland-dev
extra-cmake-modules, qtwayland5-dev-tools, qtwayland5-private-dev, libkf5wayland-dev, treeland-protocols
Standards-Version: 3.9.8

Package: libdtkgui5
Expand Down
3 changes: 2 additions & 1 deletion include/kernel/dguiapplicationhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ class DGuiApplicationHelper : public QObject, public DCORE_NAMESPACE::DObject
IsXWindowPlatform = ReadOnlyLimit << 2,
IsTableEnvironment = ReadOnlyLimit << 3,
IsDeepinEnvironment = ReadOnlyLimit << 4,
IsSpecialEffectsEnvironment = ReadOnlyLimit << 5
IsSpecialEffectsEnvironment = ReadOnlyLimit << 5,
IsTreelandPlatform = ReadOnlyLimit << 6
};
Q_ENUM(Attribute)
Q_DECLARE_FLAGS(Attributes, Attribute)
Expand Down
48 changes: 28 additions & 20 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ else()
find_package(Qt5 REQUIRED COMPONENTS WaylandClient XkbCommonSupport)
endif()

option(DTK_DISABLE_TREELAND "Disable TreeLand Protocols" OFF)
find_package(TreeLandProtocols)
set(TreeLandProtocols_FOUND ${TreeLandProtocols_FOUND})

add_library(${LIB_NAME} SHARED)

include(dbus/dbus.cmake)
Expand All @@ -12,30 +16,34 @@ include(kernel/kernel.cmake)
include(private/private.cmake)
include(util/util.cmake)

if("${QT_VERSION_MAJOR}" STREQUAL "6")
qt6_generate_wayland_protocol_client_sources(${LIB_NAME} FILES
${CMAKE_CURRENT_SOURCE_DIR}/wayland/protocol/treeland-personalization-manager-v1.xml
)
else()
# ECM setup
include(FeatureSummary)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}")
find_package(QtWaylandScanner)
ecm_add_qtwayland_client_protocol(${LIB_NAME}
PROTOCOL ${CMAKE_CURRENT_SOURCE_DIR}/wayland/protocol/treeland-personalization-manager-v1.xml
BASENAME treeland-personalization-manager-v1
)
if(NOT DTK_DISABLE_TREELAND AND TreeLandProtocols_FOUND)
message("Support Treeland!")
if("${QT_VERSION_MAJOR}" STREQUAL "6")
qt6_generate_wayland_protocol_client_sources(${LIB_NAME} FILES
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
)
else()
# ECM setup
include(FeatureSummary)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}")
find_package(QtWaylandScanner)
ecm_add_qtwayland_client_protocol(${LIB_NAME}
PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
BASENAME treeland-personalization-manager-v1
)
target_sources(${LIB_NAME} PRIVATE
${CLIENT_LIB_SRCS}
)
endif()
include(wayland/wayland.cmake)
target_sources(${LIB_NAME} PRIVATE
${CLIENT_LIB_SRCS}
${wayland_SRC}
)
else()
target_compile_definitions(${LIB_NAME} PRIVATE DTK_DISABLE_TREELAND)
endif()

include(wayland/wayland.cmake)
target_sources(${LIB_NAME} PRIVATE
${wayland_SRC}
)

target_sources(${LIB_NAME} PRIVATE
${dbus_SRC}
${filedrag_SRC}
Expand Down
4 changes: 4 additions & 0 deletions src/kernel/dguiapplicationhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,10 @@ bool DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::Attribute attri
case IsSpecialEffectsEnvironment: {
return qgetenv("DTK_DISABLED_SPECIAL_EFFECTS").toInt() != 1;
}
case IsTreelandPlatform: {
return qgetenv("DDE_CURRENT_COMPOSITOR") == "TreeLand"
&& qApp->platformName() == QByteArrayLiteral("wayland");
}
default:
return DGuiApplicationHelperPrivate::attributes.testFlag(attribute);
}
Expand Down
73 changes: 37 additions & 36 deletions src/kernel/dplatformhandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
#include "dplatformhandle.h"
#include "dplatformtheme.h"
#include "dwindowmanagerhelper.h"
#include "wayland/dcontextshellwindow.h"
#ifndef DTK_DISABLE_TREELAND
#include "wayland/personalizationwaylandclientextension.h"
#endif
#include <private/qwaylandwindow_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>

#include <QWindow>
#include <QGuiApplication>
Expand Down Expand Up @@ -97,11 +100,6 @@ static void setWindowProperty(QWindow *window, const char *name, const QVariant
reinterpret_cast<void(*)(QWindow *, const char *, const QVariant &)>(setWindowProperty)(window, name, value);
}

static bool isTreeLand()
{
return qEnvironmentVariable("DDE_CURRENT_COMPOSITOR") == "TreeLand";
};

/*!
\class Dtk::Gui::DPlatformHandle
\inmodule dtkgui
Expand Down Expand Up @@ -623,37 +621,42 @@ class Q_DECL_HIDDEN CreatorWindowEventFile : public QObject {
if (event->type() == QEvent::PlatformSurface) {
QPlatformSurfaceEvent *se = static_cast<QPlatformSurfaceEvent*>(event);
if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信号, 则 WinID 已被创建
initWindowRadius(qobject_cast<QWindow *>(watched));
auto window = qobject_cast<QWindow *>(watched);
initWindowRadius(window);

#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTreelandPlatform)) {
PersonalizationManager::instance()->setEnableTitleBar(window, false);
}
#endif
deleteLater();
}
}

if (auto *w = qobject_cast<QWindow *>(watched); w && isTreeLand()) {
if(DContextShellWindow *window = DContextShellWindow::get(qobject_cast<QWindow *>(watched))) {
bool is_mouse_move = event->type() == QEvent::MouseMove && static_cast<QMouseEvent*>(event)->buttons() == Qt::LeftButton;
if (auto *w = qobject_cast<QWindow *>(watched); w && DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTreelandPlatform)) {
bool is_mouse_move = event->type() == QEvent::MouseMove && static_cast<QMouseEvent*>(event)->buttons() == Qt::LeftButton;

if (event->type() == QEvent::MouseButtonRelease) {
m_windowMoving = false;
}
if (event->type() == QEvent::MouseButtonRelease) {
m_windowMoving = false;
}

// workaround for kwin: Qt receives no release event when kwin finishes MOVE operation,
// which makes app hang in windowMoving state. when a press happens, there's no sense of
// keeping the moving state, we can just reset ti back to normal.
if (event->type() == QEvent::MouseButtonPress) {
m_windowMoving = false;
}
// workaround for kwin: Qt receives no release event when kwin finishes MOVE operation,
// which makes app hang in windowMoving state. when a press happens, there's no sense of
// keeping the moving state, we can just reset ti back to normal.
if (event->type() == QEvent::MouseButtonPress) {
m_windowMoving = false;
}

// FIXME: We need to check whether the event is accepted.
// Only when the upper control does not accept the event,
// the window should be moved through the window.
// But every event here has been accepted. I don't know what happened.
if (is_mouse_move && w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPos())) {
if (!m_windowMoving) {
m_windowMoving = true;

// FIXME: We need to check whether the event is accepted.
// Only when the upper control does not accept the event,
// the window should be moved through the window.
// But every event here has been accepted. I don't know what happened.
if (is_mouse_move && w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPos())) {
if (!m_windowMoving && window->noTitlebar()) {
m_windowMoving = true;

event->accept();
static_cast<QtWaylandClient::QWaylandWindow *>(w->handle())->startSystemMove();
}
event->accept();
static_cast<QPlatformWindow *>(w->handle())->startSystemMove();
}
}
}
Expand All @@ -679,17 +682,15 @@ bool DPlatformHandle::setEnabledNoTitlebarForWindow(QWindow *window, bool enable
auto isDWaylandPlatform = [] {
return qApp->platformName() == "dwayland" || qApp->property("_d_isDwayland").toBool();
};
if (!(isDXcbPlatform() || isDWaylandPlatform() || isTreeLand()))
if (!(isDXcbPlatform() || isDWaylandPlatform() || DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTreelandPlatform)))
return false;

if (window && isTreeLand()) {
DContextShellWindow *contextWindow = DContextShellWindow::get(window);
if (contextWindow->noTitlebar() == enable)
return true;
contextWindow->setNoTitlebar(enable);
#ifndef DTK_DISABLE_TREELAND
if (window && DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTreelandPlatform)) {
window->installEventFilter(new CreatorWindowEventFile(window));
return true;
}
#endif

if (isEnabledNoTitlebar(window) == enable)
return true;
Expand Down
90 changes: 0 additions & 90 deletions src/wayland/dcontextshellwindow.cpp

This file was deleted.

34 changes: 0 additions & 34 deletions src/wayland/dcontextshellwindow.h

This file was deleted.

Loading

0 comments on commit 0ebf8f4

Please sign in to comment.