mirror of https://gitee.com/openkylin/kwin.git
tablet: ukui tablet mode basic support
This commit is contained in:
parent
df074a9056
commit
c8e1470339
|
@ -96,6 +96,7 @@ AbstractClient::AbstractClient()
|
|||
connect(ApplicationMenu::self(), &ApplicationMenu::applicationMenuEnabledChanged, this, [this] {
|
||||
Q_EMIT hasApplicationMenuChanged(hasApplicationMenu());
|
||||
});
|
||||
m_bTabletToPcRestoreFlag = false;
|
||||
}
|
||||
|
||||
AbstractClient::~AbstractClient()
|
||||
|
@ -1129,6 +1130,9 @@ void AbstractClient::handleInteractiveMoveResize(int x, int y, int x_root, int y
|
|||
if (isWaitingForInteractiveMoveResizeSync())
|
||||
return; // we're still waiting for the client or the timeout
|
||||
|
||||
if (workspace()->isInTabletMode())
|
||||
return;
|
||||
|
||||
const Gravity gravity = interactiveMoveResizeGravity();
|
||||
if ((gravity == Gravity::None && !isMovableAcrossScreens())
|
||||
|| (gravity != Gravity::None && (isShade() || !isResizable()))) {
|
||||
|
@ -2387,6 +2391,11 @@ bool AbstractClient::processDecorationButtonPress(QMouseEvent *event, bool ignor
|
|||
if (!wantsInput()) // we cannot be active, use it anyway
|
||||
active = true;
|
||||
|
||||
if(workspace()->isInTabletMode()) {
|
||||
Workspace::self()->performWindowOperation(this, Options::NoOp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// check whether it is a double click
|
||||
if (event->button() == Qt::LeftButton && titlebarPositionUnderMouse()) {
|
||||
if (m_decoration.doubleClickTimer.isValid()) {
|
||||
|
|
|
@ -371,6 +371,14 @@ public:
|
|||
return m_icon;
|
||||
}
|
||||
|
||||
void setTabletToPcRestoreFlag(bool bTabletToPcRestoreFlag){
|
||||
m_bTabletToPcRestoreFlag = bTabletToPcRestoreFlag;
|
||||
}
|
||||
|
||||
bool getTabletToPcRestoreFlag() const {
|
||||
return m_bTabletToPcRestoreFlag;
|
||||
}
|
||||
|
||||
bool isZombie() const;
|
||||
bool isActive() const {
|
||||
return m_active;
|
||||
|
@ -1239,6 +1247,7 @@ private:
|
|||
bool m_keepBelow = false;
|
||||
bool m_demandsAttention = false;
|
||||
bool m_minimized = false;
|
||||
bool m_bTabletToPcRestoreFlag; //平板切换pc后,如果此时窗口处于最小化,则该标志置为true,激活后用于将最大化窗口还原,再次为false
|
||||
QTimer *m_autoRaiseTimer = nullptr;
|
||||
QTimer *m_shadeHoverTimer = nullptr;
|
||||
ShadeMode m_shadeMode = ShadeNone;
|
||||
|
|
|
@ -171,6 +171,29 @@ void DecorationBridge::init()
|
|||
QStringLiteral("org.kde.KGlobalSettings"),
|
||||
QStringLiteral("slotFontChange"),
|
||||
this, SLOT(fontUpdate(int, QString)));
|
||||
|
||||
m_bTabletMode = false;
|
||||
//kwin启动时获取运行模式: 0:PC模式, 1:平板模式
|
||||
QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface",
|
||||
"/",
|
||||
"com.kylin.statusmanager.interface",
|
||||
"get_current_tabletmode");
|
||||
|
||||
QDBusMessage response = QDBusConnection::sessionBus().call(message);
|
||||
|
||||
if (response.type() == QDBusMessage::ReplyMessage) {
|
||||
m_bTabletMode = response.arguments().takeFirst().toBool();
|
||||
//printf("TabletMode = %d\n", m_bTabletMode);
|
||||
} else {
|
||||
printf("TabletMode qdus invalid\n");
|
||||
}
|
||||
//通过dbus监听PC-平板模式切换
|
||||
QDBusConnection::sessionBus().connect("com.kylin.statusmanager.interface",
|
||||
"/",
|
||||
"com.kylin.statusmanager.interface",
|
||||
"mode_change_signal",
|
||||
this,
|
||||
SLOT(slotSetSurface(bool)));
|
||||
}
|
||||
|
||||
void DecorationBridge::slotThemeUpdate(int themeId)
|
||||
|
@ -189,6 +212,15 @@ void DecorationBridge::fontUpdate(int nfont, QString strFamily)
|
|||
Q_EMIT sig_updateFont(font);
|
||||
}
|
||||
|
||||
void DecorationBridge::slotSetSurface(bool bSurface)
|
||||
{
|
||||
if(m_bTabletMode == bSurface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_bTabletMode = bSurface;
|
||||
}
|
||||
|
||||
void DecorationBridge::initPlugin()
|
||||
{
|
||||
const KPluginMetaData metaData = KPluginMetaData::findPluginById(s_pluginName, m_plugin);
|
||||
|
@ -326,6 +358,7 @@ KDecoration2::Decoration *DecorationBridge::createDecoration(AbstractClient *cli
|
|||
args.insert(QStringLiteral("themeId"), m_themeId); //针对UKUI定制的主题id
|
||||
args.insert(QStringLiteral("systemFontSize"), m_nFont); //标题栏字体大小
|
||||
args.insert(QStringLiteral("systemFont"), m_strFontFamily); //标题栏字体类型
|
||||
args.insert(QStringLiteral("tabletMode"), m_bTabletMode);
|
||||
auto deco = m_factory->create<KDecoration2::Decoration>(client, QVariantList({args}));
|
||||
deco->setSettings(m_settings);
|
||||
deco->init();
|
||||
|
|
|
@ -71,6 +71,7 @@ Q_SIGNALS:
|
|||
public Q_SLOTS:
|
||||
void slotThemeUpdate(int);
|
||||
void fontUpdate(int nfont, QString strFamily);
|
||||
void slotSetSurface(bool bSurface);
|
||||
|
||||
private:
|
||||
QString readPlugin();
|
||||
|
@ -93,6 +94,7 @@ private:
|
|||
int m_themeId; //主题id
|
||||
int m_nFont;
|
||||
QString m_strFontFamily;
|
||||
bool m_bTabletMode;
|
||||
|
||||
KWIN_SINGLETON(DecorationBridge)
|
||||
};
|
||||
|
|
|
@ -834,6 +834,10 @@ void Workspace::quickTileWindow(QuickTileMode mode)
|
|||
return;
|
||||
}
|
||||
|
||||
if(m_bTabletMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the user invokes two of these commands in a one second period, try to
|
||||
// combine them together to enable easy and intuitive corner tiling
|
||||
#define FLAG(name) QuickTileMode(QuickTileFlag::name)
|
||||
|
|
|
@ -1363,6 +1363,9 @@ void Workspace::slotWindowToPrevScreen()
|
|||
*/
|
||||
void Workspace::slotWindowMaximize()
|
||||
{
|
||||
if(m_bTabletMode)
|
||||
return;
|
||||
|
||||
if (USABLE_ACTIVE_CLIENT)
|
||||
performWindowOperation(active_client, Options::MaximizeOp);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ Workspace::Workspace()
|
|||
, set_active_client_recursion(0)
|
||||
, block_stacking_updates(0)
|
||||
, m_sessionManager(new SessionManager(this))
|
||||
, m_bTabletMode(false)
|
||||
{
|
||||
// If KWin was already running it saved its configuration after loosing the selection -> Reread
|
||||
QFuture<void> reparseConfigFuture = QtConcurrent::run(options, &Options::reparseConfiguration);
|
||||
|
@ -278,6 +279,28 @@ void Workspace::init()
|
|||
connect(server, &WaylandServer::shellClientRemoved, this, &Workspace::removeShellClient);
|
||||
}
|
||||
|
||||
//kwin启动时获取运行模式: 0:PC模式, 1:平板模式
|
||||
QDBusMessage message = QDBusMessage::createMethodCall("com.kylin.statusmanager.interface",
|
||||
"/",
|
||||
"com.kylin.statusmanager.interface",
|
||||
"get_current_tabletmode");
|
||||
|
||||
QDBusMessage response = QDBusConnection::sessionBus().call(message);
|
||||
|
||||
if (response.type() == QDBusMessage::ReplyMessage) {
|
||||
m_bTabletMode = response.arguments().takeFirst().toBool();
|
||||
slotSwitchTabletMode(m_bTabletMode);
|
||||
} else {
|
||||
printf("TabletMode qdus invalid\n");
|
||||
}
|
||||
//通过dbus监听PC-平板模式切换
|
||||
QDBusConnection::sessionBus().connect("com.kylin.statusmanager.interface",
|
||||
"/",
|
||||
"com.kylin.statusmanager.interface",
|
||||
"mode_change_signal",
|
||||
this,
|
||||
SLOT(slotSwitchTabletMode(bool)));
|
||||
|
||||
// SELI TODO: This won't work with unreasonable focus policies,
|
||||
// and maybe in rare cases also if the selected client doesn't
|
||||
// want focus
|
||||
|
@ -289,6 +312,58 @@ void Workspace::init()
|
|||
// TODO: ungrabXServer()
|
||||
}
|
||||
|
||||
void Workspace::slotSwitchTabletMode(bool bSurfaceMode)
|
||||
{
|
||||
if (m_bTabletMode == bSurfaceMode)
|
||||
return;
|
||||
m_bTabletMode = bSurfaceMode;
|
||||
switchTablet(m_bTabletMode);
|
||||
}
|
||||
|
||||
void Workspace::switchTablet(bool bOn)
|
||||
{
|
||||
bool bTopClientMaximize = true; //顶层窗口最大化标志
|
||||
for (int i = stacking_order.count() - 1; i > -1; --i) {
|
||||
AbstractClient *c = qobject_cast<AbstractClient*>(stacking_order.at(i));
|
||||
if (!c || c->isDock() || c->isDesktop())
|
||||
continue;
|
||||
|
||||
//m_bTabletMode为true,表示pc切平板
|
||||
if (m_bTabletMode) {
|
||||
if (c->maximizeMode() == MaximizeRestore) {
|
||||
c->setTabletToPcRestoreFlag(true); //切平板前,如果是还原状态,则记录
|
||||
}
|
||||
|
||||
//并且该窗口不是最小化时
|
||||
if(!c->isMinimized()) {
|
||||
if(bTopClientMaximize) {
|
||||
bTopClientMaximize = false;
|
||||
c->maximize(MaximizeFull); //序号越大,越在顶层,只需要将既不是任务栏又不是桌面的最顶层次未最小化的窗口最大化
|
||||
|
||||
if (false == c->isResizable()) {
|
||||
if (!showingDesktop()) {
|
||||
// 如果是固定大小的窗口,需要将窗口放到屏幕的正中间
|
||||
Placement::self()->placeCentered(c, workspace()->activeOutput()->geometry());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("Workspace::switchTablet, minimize unminimized caption:%s\n", c->caption().toStdString().c_str());
|
||||
c->minimize(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//m_bTabletMode为false,表示平板切pc,顶层最大化窗口如果之前是还原状态,则需还原
|
||||
if (MaximizeFull == c->maximizeMode() && true == bTopClientMaximize) {
|
||||
bTopClientMaximize = false;
|
||||
if (c->getTabletToPcRestoreFlag()) { //如果pc切平板前,记录的之前是还原状态,则当前激活窗口在切回pc后,需还原,否则,不需要处理
|
||||
c->maximize(MaximizeRestore);
|
||||
c->setTabletToPcRestoreFlag(false); //切回pc后,由于当前激活窗口已还原,则以后该窗口无需再做还原处理
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::initializeX11()
|
||||
{
|
||||
if (!kwinApp()->x11Connection()) {
|
||||
|
@ -656,6 +731,9 @@ X11Client *Workspace::createClient(xcb_window_t w, bool is_mapped)
|
|||
return nullptr;
|
||||
}
|
||||
addClient(c);
|
||||
|
||||
if(m_bTabletMode) //当是平板模式时,窗口默认最大化,其他窗口最小化/*,并且设置平板标签*/
|
||||
c->makeOthersMinimize();
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -2238,6 +2316,17 @@ void Workspace::updateClientArea()
|
|||
}
|
||||
}
|
||||
|
||||
//当屏幕旋转时,那些固定大小的窗口需要再次进行一次居中设置(除了任务栏和桌面)
|
||||
if (m_bTabletMode) {
|
||||
for (auto it = m_x11Clients.constBegin(); it != m_x11Clients.constEnd(); ++it) {
|
||||
if (true == (*it)->isResizable() || true == (*it)->isDock() || true == (*it)->isDesktop()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Placement::self()->placeCentered(*it, workspace()->activeOutput()->geometry());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_workAreas != workAreas || m_restrictedAreas != restrictedAreas || m_screenAreas != screenAreas) {
|
||||
m_workAreas = workAreas;
|
||||
m_screenAreas = screenAreas;
|
||||
|
|
|
@ -416,6 +416,9 @@ public:
|
|||
*/
|
||||
void removeInternalClient(InternalClient *client);
|
||||
|
||||
bool isInTabletMode() {return m_bTabletMode;}
|
||||
void switchTablet(bool bOn);
|
||||
|
||||
public Q_SLOTS:
|
||||
void performWindowOperation(KWin::AbstractClient* c, Options::WindowOperation op);
|
||||
// Keybindings
|
||||
|
@ -431,6 +434,8 @@ public Q_SLOTS:
|
|||
void slotWindowToPrevScreen();
|
||||
void slotToggleShowDesktop();
|
||||
|
||||
void slotSwitchTabletMode(bool bSurfaceMode);
|
||||
|
||||
void slotWindowMaximize();
|
||||
void slotWindowMaximizeVertical();
|
||||
void slotWindowMaximizeHorizontal();
|
||||
|
@ -662,6 +667,7 @@ private:
|
|||
static Workspace* _self;
|
||||
|
||||
bool workspaceInit;
|
||||
bool m_bTabletMode;
|
||||
|
||||
QScopedPointer<KStartupInfo> m_startup;
|
||||
QScopedPointer<ColorMapper> m_colorMapper;
|
||||
|
|
|
@ -1946,6 +1946,50 @@ QStringList X11Client::activities() const
|
|||
return AbstractClient::activities();
|
||||
}
|
||||
|
||||
|
||||
//使工作区其他X11窗口最小化
|
||||
void X11Client::makeOthersMinimize()
|
||||
{
|
||||
printf("X11Client::makeOthersMinimize, takefocus windowType(0):%d, caption:%s, isModal:%d, isMaximizable:%d\n", windowType(), this->caption().toStdString().c_str(), isModal(), isMaximizable());
|
||||
//平板模式下,如果是isModal窗口(如xournal应用); 或者是瞬态的对话框(如归档管理器的新建窗口); 则没必要最小化其他所有未最小化的窗口,或者是新激活的桌面开始菜单和Dock窗口(比如onboard),也不要最小化其他窗口
|
||||
if (true == this->isUtility()
|
||||
|| true == this->isModal()
|
||||
|| (true == this->isDialog() && true == this->isTransient())
|
||||
|| true == this->isDesktop()
|
||||
|| true == this->isDock()
|
||||
|| caption() == "sogouImeService"
|
||||
)
|
||||
{
|
||||
bUnMakeOthersMinimizeFlag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(this->getSpecialFlags() == static_cast<unsigned int>(SpecialFlags::DoNotMaximize))) {
|
||||
this->maximize(MaximizeFull);
|
||||
}
|
||||
|
||||
printf("X11Client::makeOthersMinimize, takefocus windowType(1):%d, caption:%s, isdialog:%d, isMaximizable:%d\n", windowType(), this->caption().toStdString().c_str(), isDialog(), isMaximizable());
|
||||
|
||||
//锁屏时,如果当前是屏保窗口,对其他窗口不要最小化。解决在平板模式打开应用,锁屏后再进入桌面,应用窗口最小化问题
|
||||
if (this->resourceClass() == "ukui-screensaver-default") {
|
||||
return;
|
||||
}
|
||||
|
||||
for (X11Client *c : workspace()->clientList()) {
|
||||
bool isIgnoreWindow = (this == c || c->isDock() || skipTaskbar() || c->isDialog() || c->isDesktop());
|
||||
bool isTabletBgWindow = (c->isUtility() && c->caption() == "ukui-kwin_tablet_background" && c->keepBelow());
|
||||
//除了自己,dock和对话框也没必要最小化
|
||||
if (isIgnoreWindow || isTabletBgWindow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (false == c->isMinimized()){
|
||||
printf("X11Client::makeOthersMinimize, minimize unminimized caption:%s\n", c->caption().toStdString().c_str());
|
||||
c->minimize(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the actual focusing of the window using XSetInputFocus and WM_TAKE_FOCUS
|
||||
*/
|
||||
|
@ -1969,6 +2013,21 @@ bool X11Client::takeFocus()
|
|||
}
|
||||
workspace()->setShouldGetFocus(this);
|
||||
|
||||
//如果是平板模式,则其他所有窗口均最小化
|
||||
if (Workspace::self()->isInTabletMode()){
|
||||
// 平板模式下,当窗口获得焦点时,如果是固定大小的窗口(除了任务栏),需要将窗口放到屏幕的正中间
|
||||
if (false == this->isResizable() && false == isDock() && false == isDesktop()) {
|
||||
Placement::self()->placeCentered(this, workspace()->activeOutput()->geometry());
|
||||
}
|
||||
makeOthersMinimize();
|
||||
} else {
|
||||
//如果pc切平板前,该窗口是还原状态,平板切pc后的窗口激活时,需将该窗口从最大化切换还原
|
||||
if (getTabletToPcRestoreFlag()) {
|
||||
setTabletToPcRestoreFlag(false);
|
||||
this->maximize(MaximizeRestore);
|
||||
}
|
||||
}
|
||||
|
||||
bool breakShowingDesktop = !keepAbove();
|
||||
if (breakShowingDesktop) {
|
||||
const auto members = group()->members();
|
||||
|
|
|
@ -45,6 +45,10 @@ enum class Predicate {
|
|||
InputIdMatch,
|
||||
};
|
||||
|
||||
enum class SpecialFlags {
|
||||
DoNotMaximize = 0x1 << 0
|
||||
};
|
||||
|
||||
/**
|
||||
* @todo Remove when the X11 platform support is dropped. This decoration renderer
|
||||
* will be used if compositing is off.
|
||||
|
@ -181,6 +185,7 @@ public:
|
|||
bool isCloseable() const override; ///< May be closed by the user (May have a close button)
|
||||
|
||||
bool takeFocus() override;
|
||||
void makeOthersMinimize(); //使工作区其他X11窗口最小化
|
||||
|
||||
void invalidateDecoration() override;
|
||||
|
||||
|
@ -302,6 +307,9 @@ public:
|
|||
|
||||
static void cleanupX11();
|
||||
|
||||
void setSpecialFlags(unsigned int specialFlags) {m_specialFlags = specialFlags;}
|
||||
unsigned int getSpecialFlags() {return m_specialFlags;}
|
||||
|
||||
public Q_SLOTS:
|
||||
void closeWindow() override;
|
||||
void updateCaption() override;
|
||||
|
@ -528,6 +536,10 @@ private:
|
|||
QRect m_lastFrameGeometry;
|
||||
QRect m_lastClientGeometry;
|
||||
QScopedPointer<X11DecorationRenderer> m_decorationRenderer;
|
||||
|
||||
bool bUnMakeOthersMinimizeFlag; //不最小化其他窗体标志
|
||||
unsigned int m_specialFlags = 0;
|
||||
|
||||
};
|
||||
|
||||
inline xcb_window_t X11Client::wrapperId() const
|
||||
|
|
Loading…
Reference in New Issue