From ac93b02abc938cb1ced45c7e131fbe3fd3431740 Mon Sep 17 00:00:00 2001 From: zhangjiaping Date: Wed, 20 Jan 2021 15:33:49 +0800 Subject: [PATCH] feat(frontend): Adapt ukui-kwin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: 适配窗管的无边框策略 Log: 适配窗管的无边框策略 --- libsearch/file-utils.cpp | 14 +- libsearch/global-settings.cpp | 5 +- src/control/search-list-view.cpp | 7 +- src/main.cpp | 8 ++ src/mainwindow.cpp | 7 +- src/res/icons/commonuse.svg | 16 --- src/resource.qrc | 1 - src/src.pro | 8 +- src/xatom-helper.cpp | 215 +++++++++++++++++++++++++++++++ src/xatom-helper.h | 111 ++++++++++++++++ 10 files changed, 360 insertions(+), 32 deletions(-) delete mode 100644 src/res/icons/commonuse.svg create mode 100644 src/xatom-helper.cpp create mode 100644 src/xatom-helper.h diff --git a/libsearch/file-utils.cpp b/libsearch/file-utils.cpp index 193a957..24a4c94 100644 --- a/libsearch/file-utils.cpp +++ b/libsearch/file-utils.cpp @@ -123,15 +123,21 @@ QIcon FileUtils::getSettingIcon(const QString& setting, const bool& is_white) { /** * @brief FileUtils::getFileName 获取文件名 - * @param uri 文件的url,格式为"file:///home/xxx/xxx/xxxx.txt" + * @param uri 格式为"file:///home/xxx/xxx/xxxx.txt" * @return */ QString FileUtils::getFileName(const QString& uri) { - QUrl url = uri; - if (url.fileName().isEmpty()) { + QFileInfo info(uri); + if (info.exists()) { + return info.fileName(); + } else { return "Unknown File"; } - return url.fileName(); +// QUrl url = uri; +// if (url.fileName().isEmpty()) { +// return "Unknown File"; +// } +// return url.fileName(); } /** diff --git a/libsearch/global-settings.cpp b/libsearch/global-settings.cpp index 2e40935..4b72865 100644 --- a/libsearch/global-settings.cpp +++ b/libsearch/global-settings.cpp @@ -31,10 +31,9 @@ GlobalSettings::GlobalSettings(QObject *parent) : QObject(parent) qApp->paletteChanged(qApp->palette()); } }); + m_cache.remove(TRANSPARENCY_KEY); + m_cache.insert(TRANSPARENCY_KEY, m_gsettings->get(TRANSPARENCY_KEY).toDouble()); } - m_cache.remove(TRANSPARENCY_KEY); - m_cache.insert(TRANSPARENCY_KEY, m_gsettings->get(TRANSPARENCY_KEY).toDouble()); - } GlobalSettings::~GlobalSettings() diff --git a/src/control/search-list-view.cpp b/src/control/search-list-view.cpp index 46f4be7..273a9c3 100644 --- a/src/control/search-list-view.cpp +++ b/src/control/search-list-view.cpp @@ -4,6 +4,7 @@ SearchListView::SearchListView(QWidget * parent, const QStringList& list, const int& type) : QTreeView(parent) { + this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setSelectionBehavior(QAbstractItemView::SelectRows); setSelectionMode(QAbstractItemView::SingleSelection); m_model = new SearchItemModel; @@ -15,7 +16,7 @@ SearchListView::SearchListView(QWidget * parent, const QStringList& list, const this->setColumnWidth(0, 20); this->setColumnWidth(1, 80); rowheight = this->rowHeight(this->model()->index(0, 0, QModelIndex())) + 1; - this->setFixedHeight(list.count() * rowheight + 2); + this->setFixedHeight(list.count() * rowheight + 4); this->setAttribute(Qt::WA_TranslucentBackground, true); this->setAutoFillBackground(false); this->setStyleSheet("QWidget{background:transparent;}"); @@ -47,7 +48,7 @@ SearchListView::~SearchListView() void SearchListView::appendItem(QString path) { m_model->appendItem(path); rowheight = this->rowHeight(this->model()->index(0, 0, QModelIndex())) + 1; - this->setFixedHeight(m_item->getCurrentSize() * rowheight + 3); + this->setFixedHeight(m_item->getCurrentSize() * rowheight + 4); } /** @@ -57,7 +58,7 @@ void SearchListView::setList(QStringList list) { m_model->appendList(list); rowheight = this->rowHeight(this->model()->index(0, 0, QModelIndex())); - this->setFixedHeight(m_item->getCurrentSize() * rowheight + 3); + this->setFixedHeight(m_item->getCurrentSize() * rowheight + 4); } /** diff --git a/src/main.cpp b/src/main.cpp index 1d03b8a..0bb548e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,7 @@ //#include "inotify-manager.h" #include "libsearch.h" #include "global-settings.h" +#include "xatom-helper.h" void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { @@ -159,6 +160,13 @@ int main(int argc, char *argv[]) QStringList arguments = QCoreApplication::arguments(); centerToScreen(w); + //使用窗管的无边框策略 + MotifWmHints hints; + hints.flags = MWM_HINTS_FUNCTIONS|MWM_HINTS_DECORATIONS; + hints.functions = MWM_FUNC_ALL; + hints.decorations = MWM_DECOR_BORDER; + XAtomHelper::getInstance()->setWindowMotifHint(w->winId(), hints); + app.setActivationWindow(w); // if(arguments.size()>1) // w->searchContent(arguments.at(1)); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 8d7a422..740a7e3 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -61,7 +61,9 @@ MainWindow::MainWindow(QWidget *parent) : // im->start(); /*-------------Inotify Test End-----------------*/ - this->setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); +// this->setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); +// this->setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint); + this->setWindowIcon(QIcon::fromTheme("kylin-search")); this->setAttribute(Qt::WA_TranslucentBackground, true); this->setAutoFillBackground(false); this->setFocusPolicy(Qt::StrongFocus); @@ -161,7 +163,8 @@ void MainWindow::initUi() m_titleLabel->setText(tr("Search")); m_menuBtn = new QPushButton(m_titleFrame); m_menuBtn->setFixedSize(24, 24); - m_menuBtn->setIcon(QIcon(":/res/icons/commonuse.svg")); +// m_menuBtn->setIcon(QIcon(":/res/icons/commonuse.svg")); + m_menuBtn->setIcon(QIcon::fromTheme("document-properties-symbolic")); m_menuBtn->setStyleSheet("QPushButton{background: transparent;}" "QPushButton:hover:!pressed{background: transparent;}"); connect(m_menuBtn, &QPushButton::clicked, this, [ = ]() { diff --git a/src/res/icons/commonuse.svg b/src/res/icons/commonuse.svg deleted file mode 100644 index 09afb9e..0000000 --- a/src/res/icons/commonuse.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - diff --git a/src/resource.qrc b/src/resource.qrc index 37060e7..604a395 100644 --- a/src/resource.qrc +++ b/src/resource.qrc @@ -1,6 +1,5 @@ - res/icons/commonuse.svg res/icons/edit-find-symbolic.svg res/icons/desktop.png res/icons/close.svg diff --git a/src/src.pro b/src/src.pro index 5611ba7..a4a1ada 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,4 +1,4 @@ -QT += core gui dbus KWindowSystem xml +QT += core gui dbus KWindowSystem xml x11extras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -8,7 +8,7 @@ TEMPLATE = app PKGCONFIG += gio-2.0 glib-2.0 gio-unix-2.0 CONFIG += c++11 link_pkgconfig no_keywords lrelease -LIBS += -lxapian -lgsettings-qt -lquazip5 +LIBS += -lxapian -lgsettings-qt -lquazip5 -lX11 # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the @@ -31,6 +31,7 @@ SOURCES += \ mainwindow.cpp \ search-result.cpp \ settings-widget.cpp \ + xatom-helper.cpp HEADERS += \ @@ -38,7 +39,8 @@ HEADERS += \ input-box.h \ mainwindow.h \ search-result.h \ - settings-widget.h + settings-widget.h \ + xatom-helper.h # Default rules for deployment. diff --git a/src/xatom-helper.cpp b/src/xatom-helper.cpp new file mode 100644 index 0000000..1dae3a2 --- /dev/null +++ b/src/xatom-helper.cpp @@ -0,0 +1,215 @@ +/* + * KWin Style UKUI + * + * Copyright (C) 2020, KylinSoft Co., Ltd. + * + * 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 + * (at your option) 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 . + * + * Authors: Yue Lan + * + */ + +#include "xatom-helper.h" + +#include + +#include + +#include +#include +#include + +static XAtomHelper *global_instance = nullptr; + +XAtomHelper *XAtomHelper::getInstance() +{ + if (!global_instance) + global_instance = new XAtomHelper; + return global_instance; +} + +bool XAtomHelper::isFrameLessWindow(int winId) +{ + auto hints = getInstance()->getWindowMotifHint(winId); + if (hints.flags == MWM_HINTS_DECORATIONS && hints.functions == 1) { + return true; + } + return false; +} + +bool XAtomHelper::isWindowDecorateBorderOnly(int winId) +{ + return isWindowMotifHintDecorateBorderOnly(getInstance()->getWindowMotifHint(winId)); +} + +bool XAtomHelper::isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint) +{ + bool isDeco = false; + if (hint.flags & MWM_HINTS_DECORATIONS && hint.flags != MWM_HINTS_DECORATIONS) { + if (hint.decorations == MWM_DECOR_BORDER) + isDeco = true; + } + return isDeco; +} + +bool XAtomHelper::isUKUICsdSupported() +{ + // fixme: + return false; +} + +bool XAtomHelper::isUKUIDecorationWindow(int winId) +{ + if (m_ukuiDecorationAtion == None) + return false; + + Atom type; + int format; + ulong nitems; + ulong bytes_after; + uchar *data; + + bool isUKUIDecoration = false; + + XGetWindowProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, + 0, LONG_MAX, false, + m_ukuiDecorationAtion, &type, + &format, &nitems, + &bytes_after, &data); + + if (type == m_ukuiDecorationAtion) { + if (nitems == 1) { + isUKUIDecoration = data[0]; + } + } + + return isUKUIDecoration; +} + +UnityCorners XAtomHelper::getWindowBorderRadius(int winId) +{ + UnityCorners corners; + + Atom type; + int format; + ulong nitems; + ulong bytes_after; + uchar *data; + + if (m_unityBorderRadiusAtom != None) { + XGetWindowProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, + 0, LONG_MAX, false, + XA_CARDINAL, &type, + &format, &nitems, + &bytes_after, &data); + + if (type == XA_CARDINAL) { + if (nitems == 4) { + corners.topLeft = static_cast(data[0]); + corners.topRight = static_cast(data[1*sizeof (ulong)]); + corners.bottomLeft = static_cast(data[2*sizeof (ulong)]); + corners.bottomRight = static_cast(data[3*sizeof (ulong)]); + } + XFree(data); + } + } + + return corners; +} + +void XAtomHelper::setWindowBorderRadius(int winId, const UnityCorners &data) +{ + if (m_unityBorderRadiusAtom == None) + return; + + ulong corners[4] = {data.topLeft, data.topRight, data.bottomLeft, data.bottomRight}; + + XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL, + 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0])); +} + +void XAtomHelper::setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight) +{ + if (m_unityBorderRadiusAtom == None) + return; + + ulong corners[4] = {(ulong)topLeft, (ulong)topRight, (ulong)bottomLeft, (ulong)bottomRight}; + + XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL, + 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &corners, sizeof (corners)/sizeof (corners[0])); +} + +void XAtomHelper::setUKUIDecoraiontHint(int winId, bool set) +{ + if (m_ukuiDecorationAtion == None) + return; + + XChangeProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, m_ukuiDecorationAtion, 32, XCB_PROP_MODE_REPLACE, (const unsigned char *) &set, 1); +} + +void XAtomHelper::setWindowMotifHint(int winId, const MotifWmHints &hints) +{ + if (m_unityBorderRadiusAtom == None) + return; + + XChangeProperty(QX11Info::display(), winId, m_motifWMHintsAtom, m_motifWMHintsAtom, + 32, XCB_PROP_MODE_REPLACE, (const unsigned char *)&hints, sizeof (MotifWmHints)/ sizeof (ulong)); +} + +MotifWmHints XAtomHelper::getWindowMotifHint(int winId) +{ + MotifWmHints hints; + + if (m_unityBorderRadiusAtom == None) + return hints; + + uchar *data; + Atom type; + int format; + ulong nitems; + ulong bytes_after; + + XGetWindowProperty(QX11Info::display(), winId, m_motifWMHintsAtom, + 0, sizeof (MotifWmHints)/sizeof (long), false, AnyPropertyType, &type, + &format, &nitems, &bytes_after, &data); + + if (type == None) { + return hints; + } else { + hints = *(MotifWmHints *)data; + XFree(data); + } + return hints; +} + +XAtomHelper::XAtomHelper(QObject *parent) : QObject(parent) +{ + if (!QX11Info::isPlatformX11()) + return; + + m_motifWMHintsAtom = XInternAtom(QX11Info::display(), "_MOTIF_WM_HINTS", true); + m_unityBorderRadiusAtom = XInternAtom(QX11Info::display(), "_UNITY_GTK_BORDER_RADIUS", false); + m_ukuiDecorationAtion = XInternAtom(QX11Info::display(), "_KWIN_UKUI_DECORAION", false); +} + +Atom XAtomHelper::registerUKUICsdNetWmSupportAtom() +{ + // fixme: + return None; +} + +void XAtomHelper::unregisterUKUICsdNetWmSupportAtom() +{ + // fixme: +} diff --git a/src/xatom-helper.h b/src/xatom-helper.h new file mode 100644 index 0000000..c8d1701 --- /dev/null +++ b/src/xatom-helper.h @@ -0,0 +1,111 @@ +/* + * KWin Style UKUI + * + * Copyright (C) 2020, KylinSoft Co., Ltd. + * + * 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 + * (at your option) 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 . + * + * Authors: Yue Lan + * + */ + +#ifndef XATOMHELPER_H +#define XATOMHELPER_H + +#include + +#include +#include + +struct UnityCorners { + ulong topLeft = 0; + ulong topRight = 0; + ulong bottomLeft = 0; + ulong bottomRight = 0; +}; + +typedef struct { + ulong flags = 0; + ulong functions = 0; + ulong decorations = 0; + long input_mode = 0; + ulong status = 0; +} MotifWmHints, MwmHints; + +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) + +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) + +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) + +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 +#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL + +#define MWM_TEAROFF_WINDOW (1L<<0) + +namespace UKUI { +class Decoration; +} + +class XAtomHelper : public QObject +{ + // friend class UKUI::Decoration; + Q_OBJECT +public: + static XAtomHelper *getInstance(); + + static bool isFrameLessWindow(int winId); + + static bool isWindowDecorateBorderOnly(int winId); + static bool isWindowMotifHintDecorateBorderOnly(const MotifWmHints &hint); + bool isUKUICsdSupported(); + bool isUKUIDecorationWindow(int winId); + + UnityCorners getWindowBorderRadius(int winId); + void setWindowBorderRadius(int winId, const UnityCorners &data); + void setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight); + void setUKUIDecoraiontHint(int winId, bool set = true); + + void setWindowMotifHint(int winId, const MotifWmHints &hints); + MotifWmHints getWindowMotifHint(int winId); + +private: + explicit XAtomHelper(QObject *parent = nullptr); + + Atom registerUKUICsdNetWmSupportAtom(); + void unregisterUKUICsdNetWmSupportAtom(); + + Atom m_motifWMHintsAtom = None; + Atom m_unityBorderRadiusAtom = None; + Atom m_ukuiDecorationAtion = None; +}; + +#endif // XATOMHELPER_H