New menu
This commit is contained in:
parent
ea3cf393a5
commit
e91e56e11a
10 changed files with 227 additions and 63 deletions
|
@ -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
|
||||||
|
|
|
@ -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
43
qml/DockMenu.qml
Normal 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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
129
src/popupwindow.cpp
Normal 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
46
src/popupwindow.h
Normal 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
|
|
@ -1,7 +0,0 @@
|
||||||
#include "toplevelmenu.h"
|
|
||||||
|
|
||||||
TopLevelMenu::TopLevelMenu(QQuickView *parent)
|
|
||||||
: QQuickView(parent)
|
|
||||||
{
|
|
||||||
setFlags(Qt::Popup);
|
|
||||||
}
|
|
|
@ -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
|
|
Loading…
Reference in a new issue