mirror of
https://github.com/linuxdeepin/dde-dock.git
synced 2025-06-03 00:15:21 +00:00

原来的逻辑为在应用没有打开窗口的时候,需要自动打开一个窗口然后来触发分屏的操作; 根据和产品详细讨论,现该逻辑改为:在应用没有打开窗口的时候,无需触发分屏 Log: Influence: 从任务栏拖动一个没有打开窗口的应用,观察是否打开应用(正常情况下不会打开应用),释放鼠标,观察应用图标是否回到任务栏上 Bug: https://pms.uniontech.com/bug-view-154349.html Change-Id: I6d07097a85912caf15ce63952d6b84225b3aeaad
187 lines
6.1 KiB
C++
187 lines
6.1 KiB
C++
/*
|
||
* Copyright (C) 2022 ~ 2022 Deepin Technology Co., Ltd.
|
||
*
|
||
* Author: donghualin <donghualin@uniontech.com>
|
||
*
|
||
* Maintainer: donghualin <donghualin@uniontech.com>
|
||
*
|
||
* This program is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 3 of the License, or
|
||
* any later version.
|
||
*
|
||
* This program is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
#include "screenspliter_wayland.h"
|
||
#include "appitem.h"
|
||
|
||
#include <QWindow>
|
||
#include <QApplication>
|
||
#include <QX11Info>
|
||
#include <QtWaylandClient>
|
||
#define private public
|
||
#include <private/qwaylandintegration_p.h>
|
||
#include <private/qwaylandshellsurface_p.h>
|
||
#include <private/qwaylandwindow_p.h>
|
||
#include <private/qwaylandcursor_p.h>
|
||
#undef private
|
||
|
||
#include <registry.h>
|
||
#include <ddeshell.h>
|
||
#include <event_queue.h>
|
||
#include <plasmashell.h>
|
||
#include <compositor.h>
|
||
#include <clientmanagement.h>
|
||
#include <connection_thread.h>
|
||
|
||
SplitWindowManager *ScreenSpliter_Wayland::m_splitManager = nullptr;
|
||
|
||
/** wayland下的分屏功能
|
||
* @brief ScreenSpliter_Wayland::ScreenSpliter_Wayland
|
||
* @param parent
|
||
*/
|
||
ScreenSpliter_Wayland::ScreenSpliter_Wayland(AppItem *appItem, DockEntryInter *entryInter, QObject *parent)
|
||
: ScreenSpliter(appItem, entryInter, 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::Background, 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 = entryInter()->windowInfos();
|
||
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 = entryInter()->windowInfos();
|
||
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();
|
||
}
|