dde-dock/frame/screenspliter/screenspliter_wayland.cpp
tsic404 9de057e2cc refactor: add taskmanager from dde-application-manager
1. taskmanager used to identify which entry should map to window
  in x11 environmrnt, listen to xevent in anohter thread, and handle those event
when window create, destory, changed. use some way to identify which entry(desktopfile)
should mapped to changed window.
  in wayland, connected plsamawindow signal(window created destoried.
2. use taskmanager instead of dbus in old dock code

log: as title
2023-07-18 07:35:19 +00:00

166 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "screenspliter_wayland.h"
#include "appitem.h"
#include <QWindow>
#include <QApplication>
#include <QX11Info>
#include <QtWaylandClient>
#include <DWayland/Client/registry.h>
#include <DWayland/Client/ddeshell.h>
#include <DWayland/Client/event_queue.h>
#include <DWayland/Client/plasmashell.h>
#include <DWayland/Client/compositor.h>
#include <DWayland/Client/clientmanagement.h>
#include <DWayland/Client/connection_thread.h>
SplitWindowManager *ScreenSpliter_Wayland::m_splitManager = nullptr;
/** wayland下的分屏功能
* @brief ScreenSpliter_Wayland::ScreenSpliter_Wayland
* @param parent
*/
ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, QObject *parent)
: ScreenSpliter(appItem, parent)
{
if (!m_splitManager)
m_splitManager = new SplitWindowManager;
}
ScreenSpliter_Wayland::~ScreenSpliter_Wayland()
{
}
void ScreenSpliter_Wayland::startSplit(const QRect &rect)
{
if (!suportSplitScreen())
return;
setMaskVisible(rect, true);
}
void ScreenSpliter_Wayland::setMaskVisible(const QRect &rect, bool visible)
{
static QWidget *desktopWidget = nullptr;
if (!desktopWidget) {
desktopWidget = new QWidget;
DPalette palette = DGuiApplicationHelper::instance()->applicationPalette();
QColor backColor = palette.color(QPalette::Highlight);
backColor.setAlpha(255 * 0.3);
palette.setBrush(QPalette::ColorRole::Window, backColor);
desktopWidget->setPalette(palette);
desktopWidget->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);
}
desktopWidget->setVisible(visible);
desktopWidget->setGeometry(rect);
desktopWidget->raise();
}
bool ScreenSpliter_Wayland::split(SplitDirection direction)
{
setMaskVisible(QRect(), false);
// 如果当前不支持分屏则返回false
if (!suportSplitScreen())
return false;
WindowInfoMap windowInfos = appItem()->windowsInfos();
m_splitManager->requestSplitWindow(windowInfos.first().uuid.toStdString().c_str(), direction);
return true;
}
bool ScreenSpliter_Wayland::windowSupportSplit(const QString &uuid) const
{
return m_splitManager->canSplit(uuid);
}
bool ScreenSpliter_Wayland::suportSplitScreen()
{
// 判断所有打开的窗口列表,只要有一个窗口支持分屏,就认为它支持分屏
const WindowInfoMap &windowsInfo = appItem()->windowsInfos();
for (const WindowInfo &windowInfo : windowsInfo) {
if (windowSupportSplit(windowInfo.uuid))
return true;
}
// 如果所有的窗口都不支持分屏,就认为它不支持分屏,包括没有打开窗口的情况
return false;
}
bool ScreenSpliter_Wayland::releaseSplit()
{
setMaskVisible(QRect(), false);
return true;
}
/**
* @brief SplitWindowManager::SplitWindowManager
* @param wayland下的分屏的管理
*/
SplitWindowManager::SplitWindowManager(QObject *parent)
: QObject(parent)
, m_clientManagement(nullptr)
, m_connectionThread(new QThread(nullptr))
, m_connectionThreadObject(new ConnectionThread)
{
connect(m_connectionThreadObject, &ConnectionThread::connected, this, &SplitWindowManager::onConnectionFinished, Qt::QueuedConnection);
m_connectionThreadObject->moveToThread(m_connectionThread);
m_connectionThread->start();
m_connectionThreadObject->initConnection();
}
SplitWindowManager::~SplitWindowManager()
{
}
bool SplitWindowManager::canSplit(const QString &uuid) const
{
const QVector <ClientManagement::WindowState> &windowStates = m_clientManagement->getWindowStates();
for (const ClientManagement::WindowState &winState : windowStates)
if (winState.uuid == uuid && winState.splitable > 0)
return true;
return false;
}
static ClientManagement::SplitType convertSplitType(ScreenSpliter::SplitDirection direction)
{
static QMap<ScreenSpliter::SplitDirection, ClientManagement::SplitType> direcionMapping = {
{ ScreenSpliter::Left, ClientManagement::SplitType::Left },
{ ScreenSpliter::Right, ClientManagement::SplitType::Right},
{ ScreenSpliter::Top, ClientManagement::SplitType::Top },
{ ScreenSpliter::Bottom, ClientManagement::SplitType::Bottom },
{ ScreenSpliter::LeftTop, ClientManagement::SplitType::LeftTop },
{ ScreenSpliter::RightTop, ClientManagement::SplitType::RightTop },
{ ScreenSpliter::LeftBottom, ClientManagement::SplitType::LeftBottom },
{ ScreenSpliter::RightBottom, ClientManagement::SplitType::RightBottom }
};
return direcionMapping.value(direction, ClientManagement::SplitType::None);
}
void SplitWindowManager::requestSplitWindow(const char *uuid, const ScreenSpliter::SplitDirection &direction)
{
m_clientManagement->requestSplitWindow(uuid, convertSplitType(direction));
}
void SplitWindowManager::onConnectionFinished()
{
EventQueue *eventQueue = new EventQueue(this);
eventQueue->setup(m_connectionThreadObject);
Registry *registry = new Registry(this);
connect(registry, &Registry::clientManagementAnnounced, this, [ this, registry ](quint32 name, quint32 version) {
m_clientManagement = registry->createClientManagement(name, version, this);
});
registry->setEventQueue(eventQueue);
registry->create(m_connectionThreadObject);
registry->setup();
}