This commit is contained in:
cutefishd 2021-03-22 17:10:08 +08:00
parent ea3cf393a5
commit e91e56e11a
10 changed files with 227 additions and 63 deletions

View file

@ -10,8 +10,8 @@ set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(QT Core Widgets Concurrent Quick QuickControls2 X11Extras DBus Svg LinguistTools) find_package(Qt5 CONFIG REQUIRED Widgets DBus X11Extras Concurrent Svg LinguistTools QuickControls2)
find_package(Qt5 REQUIRED ${QT})
find_package(KF5WindowSystem REQUIRED) find_package(KF5WindowSystem REQUIRED)
find_package(dbusmenu-qt5 REQUIRED) find_package(dbusmenu-qt5 REQUIRED)
find_package(MeuiKit REQUIRED) find_package(MeuiKit REQUIRED)
@ -33,7 +33,7 @@ set(SRCS
src/volumemanager.cpp src/volumemanager.cpp
src/utils.cpp src/utils.cpp
src/xwindowinterface.cpp src/xwindowinterface.cpp
src/toplevelmenu.cpp src/popupwindow.cpp
src/appearance.cpp src/appearance.cpp
src/fakewindow.cpp src/fakewindow.cpp
@ -68,7 +68,7 @@ qt5_add_dbus_adaptor(SRCS src/systemtray/org.kde.StatusNotifierWatcher.xml
src/systemtray/statusnotifierwatcher.h StatusNotifierWatcher) src/systemtray/statusnotifierwatcher.h StatusNotifierWatcher)
add_executable(${PROJECT_NAME} ${SRCS} ${DBUS_SRCS} ${RESOURCES}) add_executable(${PROJECT_NAME} ${SRCS} ${DBUS_SRCS} ${RESOURCES})
target_link_libraries(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PRIVATE
Qt5::Core Qt5::Core
Qt5::Widgets Qt5::Widgets
Qt5::Quick Qt5::Quick

View file

@ -23,7 +23,7 @@ DockItem {
onPositionChanged: updateGeometry() onPositionChanged: updateGeometry()
onPressed: updateGeometry() onPressed: updateGeometry()
onClicked: appModel.clicked(model.appId) onClicked: appModel.clicked(model.appId)
onRightClicked: if (model.appId !== "cutefish-launcher") contextMenu.open() onRightClicked: if (model.appId !== "cutefish-launcher") contextMenu.show()
dropArea.onEntered: { dropArea.onEntered: {
if (drag.source) if (drag.source)
@ -37,7 +37,7 @@ DockItem {
updateGeometry() updateGeometry()
} }
TopLevelMenu { DockMenu {
id: contextMenu id: contextMenu
MenuItem { MenuItem {

43
qml/DockMenu.qml Normal file
View file

@ -0,0 +1,43 @@
import QtQuick 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls 2.12
import Cutefish.Dock 1.0
import MeuiKit 1.0 as Meui
PopupWindow {
id: control
default property alias content : _mainLayout.data
Rectangle {
id: _background
anchors.fill: parent
opacity: 0.6
color: Meui.Theme.backgroundColor
radius: Meui.Theme.mediumRadius
Meui.WindowShadow {
view: control
geometry: Qt.rect(control.x, control.y, control.width, control.height)
radius: _background.radius
}
Meui.WindowBlur {
view: control
geometry: Qt.rect(control.x, control.y, control.width, control.height)
windowRadius: _background.radius
enabled: true
}
}
ColumnLayout {
id: _mainLayout
anchors.fill: parent
anchors.topMargin: 8
anchors.bottomMargin: 8
}
function open() {
control.show()
}
}

View file

@ -1,32 +0,0 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
Window {
id: control
visible: false
width: _mainLayout.implicitWidth
height: _mainLayout.implicitHeight
flags: Qt.Popup
onActiveChanged: {
if (!active)
control.close()
}
default property alias content: _mainLayout.data
function open() {
control.visible = true
control.x = 500
control.y = 500
}
ColumnLayout {
id: _mainLayout
anchors.fill: parent
}
}

View file

@ -102,6 +102,6 @@
<file>svg/light/dark-mode.svg</file> <file>svg/light/dark-mode.svg</file>
<file>svg/dark/dark-mode.svg</file> <file>svg/dark/dark-mode.svg</file>
<file>svg/dark/bluetooth-symbolic.svg</file> <file>svg/dark/bluetooth-symbolic.svg</file>
<file>qml/TopLevelMenu.qml</file> <file>qml/DockMenu.qml</file>
</qresource> </qresource>
</RCC> </RCC>

View file

@ -33,6 +33,7 @@
#include "systemtray/systemtraymodel.h" #include "systemtray/systemtraymodel.h"
#include "appearance.h" #include "appearance.h"
#include "iconitem.h" #include "iconitem.h"
#include "popupwindow.h"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
@ -47,6 +48,7 @@ int main(int argc, char *argv[])
qmlRegisterType<SystemTrayModel>("Cutefish.Dock", 1, 0, "SystemTrayModel"); qmlRegisterType<SystemTrayModel>("Cutefish.Dock", 1, 0, "SystemTrayModel");
qmlRegisterType<Appearance>("Cutefish.Dock", 1, 0, "Appearance"); qmlRegisterType<Appearance>("Cutefish.Dock", 1, 0, "Appearance");
qmlRegisterType<IconItem>("Cutefish.Dock", 1, 0, "IconItem"); qmlRegisterType<IconItem>("Cutefish.Dock", 1, 0, "IconItem");
qmlRegisterType<PopupWindow>("Cutefish.Dock", 1, 0, "PopupWindow");
QString qmFilePath = QString("%1/%2.qm").arg("/usr/share/cutefish-dock/translations/").arg(QLocale::system().name()); QString qmFilePath = QString("%1/%2.qm").arg("/usr/share/cutefish-dock/translations/").arg(QLocale::system().name());
if (QFile::exists(qmFilePath)) { if (QFile::exists(qmFilePath)) {

129
src/popupwindow.cpp Normal file
View file

@ -0,0 +1,129 @@
#include "popupwindow.h"
#include <QGuiApplication>
#include <QQuickRenderControl>
#include <QQuickItem>
#include <QScreen>
PopupWindow::PopupWindow(QQuickWindow *parent)
: QQuickWindow(parent)
, m_parentItem(0)
, m_contentItem(0)
, m_mouseMoved(false)
, m_dismissed(false)
{
setFlags(Qt::Popup);
setColor(Qt::transparent);
connect(qApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)),
this, SLOT(applicationStateChanged(Qt::ApplicationState)));
}
void PopupWindow::applicationStateChanged(Qt::ApplicationState state)
{
if (state != Qt::ApplicationActive)
dismissPopup();
}
void PopupWindow::show()
{
QPoint pos = QCursor::pos();
int w = m_contentItem->implicitWidth();
int h = m_contentItem->implicitHeight() + 16;
int posx = pos.x();
int posy = pos.y();
QWindow *pw = transientParent();
if (!pw && parentItem())
pw = parentItem()->window();
if (!pw)
pw = this;
QRect g = pw->screen()->availableGeometry();
if (posx + w > g.right()) {
if (qobject_cast<PopupWindow *>(transientParent())) {
// reposition submenu window on the parent menu's left side
int submenuOverlap = pw->x() + pw->width() - posx;
posx -= pw->width() + w - 2 * submenuOverlap;
} else {
posx = g.right() - w;
}
} else {
posx = qMax(posx, g.left());
}
posy = qBound(g.top(), posy, g.bottom() - h);
setGeometry(posx, posy, w, h);
QQuickWindow::show();
setMouseGrabEnabled(true);
setKeyboardGrabEnabled(true);
}
void PopupWindow::setParentItem(QQuickItem *item)
{
m_parentItem = item;
if (m_parentItem)
setTransientParent(m_parentItem->window());
}
void PopupWindow::setPopupContentItem(QQuickItem *contentItem)
{
if (!contentItem)
return;
contentItem->setParentItem(this->contentItem());
m_contentItem = contentItem;
}
void PopupWindow::dismissPopup()
{
m_dismissed = true;
emit popupDismissed();
hide();
}
void PopupWindow::mouseMoveEvent(QMouseEvent *e)
{
QQuickWindow::mouseMoveEvent(e);
}
void PopupWindow::mousePressEvent(QMouseEvent *e)
{
QRect rect = QRect(QPoint(), size());
if (rect.contains(e->pos())) {
QQuickWindow::mousePressEvent(e);
} else {
dismissPopup();
}
}
void PopupWindow::mouseReleaseEvent(QMouseEvent *e)
{
QQuickWindow::mouseReleaseEvent(e);
dismissPopup();
}
bool PopupWindow::event(QEvent *event)
{
//QTBUG-45079
//This is a workaround for popup menu not being closed when using touch input.
//Currently mouse synthesized events are not created for touch events which are
//outside the qquickwindow.
if (event->type() == QEvent::TouchBegin && !qobject_cast<PopupWindow*>(transientParent())) {
QRect rect = QRect(QPoint(), size());
QTouchEvent *touch = static_cast<QTouchEvent*>(event);
QTouchEvent::TouchPoint point = touch->touchPoints().first();
if ((point.state() == Qt::TouchPointPressed) && !rect.contains(point.pos().toPoint())) {
//first default handling
bool result = QQuickWindow::event(event);
//now specific broken case
if (!m_dismissed)
dismissPopup();
return result;
}
}
return QQuickWindow::event(event);
}

46
src/popupwindow.h Normal file
View file

@ -0,0 +1,46 @@
#ifndef TOPLEVELMENU_H
#define TOPLEVELMENU_H
#include <QQuickWindow>
class PopupWindow : public QQuickWindow
{
Q_OBJECT
Q_PROPERTY(QQuickItem *popupContentItem READ popupContentItem WRITE setPopupContentItem)
Q_CLASSINFO("DefaultProperty", "popupContentItem")
Q_PROPERTY(QQuickItem *parentItem READ parentItem WRITE setParentItem)
public:
PopupWindow(QQuickWindow *parent = nullptr);
QQuickItem *popupContentItem() const { return m_contentItem; }
void setPopupContentItem(QQuickItem *popupContentItem);
QQuickItem *parentItem() const { return m_parentItem; }
virtual void setParentItem(QQuickItem *);
public slots:
void show();
void dismissPopup();
signals:
void popupDismissed();
void geometryChanged();
protected:
void mousePressEvent(QMouseEvent *) override;
void mouseReleaseEvent(QMouseEvent *) override;
void mouseMoveEvent(QMouseEvent *) override;
bool event(QEvent *) override;
protected slots:
void applicationStateChanged(Qt::ApplicationState state);
private:
QQuickItem *m_parentItem;
QPointer<QQuickItem> m_contentItem;
bool m_mouseMoved;
bool m_dismissed;
};
#endif // POPUPWINDOW_H

View file

@ -1,7 +0,0 @@
#include "toplevelmenu.h"
TopLevelMenu::TopLevelMenu(QQuickView *parent)
: QQuickView(parent)
{
setFlags(Qt::Popup);
}

View file

@ -1,17 +0,0 @@
#ifndef TOPLEVELMENU_H
#define TOPLEVELMENU_H
#include <QQuickView>
class TopLevelMenu : public QQuickView
{
Q_OBJECT
public:
explicit TopLevelMenu(QQuickView *parent = nullptr);
signals:
};
#endif // TOPLEVELMENU_H