Restore global menu support
This brings back global menu support in KWin. The DBusMenu infrastructure is different that we just read the DBus service name and menu object path from the windows rather than passing around window IDs on DBus which won't work on Wayland. Differential Revision: https://phabricator.kde.org/D3089
This commit is contained in:
parent
e616925fb0
commit
93938d60b8
24 changed files with 454 additions and 5 deletions
|
@ -435,6 +435,7 @@ set(kwin_KDEINIT_SRCS
|
|||
wayland_server.cpp
|
||||
wayland_cursor_theme.cpp
|
||||
virtualkeyboard.cpp
|
||||
appmenu.cpp
|
||||
)
|
||||
|
||||
if(KWIN_BUILD_TABBOX)
|
||||
|
@ -485,6 +486,8 @@ qt5_add_dbus_adaptor( kwin_KDEINIT_SRCS ${kwin_effects_dbus_xml} effects.h KWin:
|
|||
|
||||
qt5_add_dbus_interface( kwin_KDEINIT_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/org.freedesktop.ScreenSaver.xml screenlocker_interface)
|
||||
|
||||
qt5_add_dbus_interface( kwin_KDEINIT_SRCS org.kde.kappmenu.xml appmenu_interface )
|
||||
|
||||
qt5_add_resources( kwin_KDEINIT_SRCS resources.qrc )
|
||||
|
||||
ki18n_wrap_ui(kwin_KDEINIT_SRCS
|
||||
|
|
|
@ -18,6 +18,8 @@ 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 "abstract_client.h"
|
||||
|
||||
#include "appmenu.h"
|
||||
#include "decorations/decoratedclient.h"
|
||||
#include "decorations/decorationpalette.h"
|
||||
#include "decorations/decorationbridge.h"
|
||||
|
@ -82,6 +84,10 @@ AbstractClient::AbstractClient()
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
connect(ApplicationMenu::self(), &ApplicationMenu::applicationMenuEnabledChanged, this, [this] {
|
||||
emit hasApplicationMenuChanged(hasApplicationMenu());
|
||||
});
|
||||
}
|
||||
|
||||
AbstractClient::~AbstractClient()
|
||||
|
@ -1676,4 +1682,53 @@ QString AbstractClient::iconFromDesktopFile() const
|
|||
return df.readIcon();
|
||||
}
|
||||
|
||||
bool AbstractClient::hasApplicationMenu() const
|
||||
{
|
||||
return ApplicationMenu::self()->applicationMenuEnabled() && !m_applicationMenuServiceName.isEmpty() && !m_applicationMenuObjectPath.isEmpty();
|
||||
}
|
||||
|
||||
void AbstractClient::updateApplicationMenuServiceName(const QString &serviceName)
|
||||
{
|
||||
const bool old_hasApplicationMenu = hasApplicationMenu();
|
||||
|
||||
m_applicationMenuServiceName = serviceName;
|
||||
|
||||
const bool new_hasApplicationMenu = hasApplicationMenu();
|
||||
|
||||
if (old_hasApplicationMenu != new_hasApplicationMenu) {
|
||||
emit hasApplicationMenuChanged(new_hasApplicationMenu);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractClient::updateApplicationMenuObjectPath(const QString &objectPath)
|
||||
{
|
||||
const bool old_hasApplicationMenu = hasApplicationMenu();
|
||||
|
||||
m_applicationMenuObjectPath = objectPath;
|
||||
|
||||
const bool new_hasApplicationMenu = hasApplicationMenu();
|
||||
|
||||
if (old_hasApplicationMenu != new_hasApplicationMenu) {
|
||||
emit hasApplicationMenuChanged(new_hasApplicationMenu);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractClient::setApplicationMenuActive(bool applicationMenuActive)
|
||||
{
|
||||
if (m_applicationMenuActive != applicationMenuActive) {
|
||||
m_applicationMenuActive = applicationMenuActive;
|
||||
emit applicationMenuActiveChanged(applicationMenuActive);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractClient::showApplicationMenu(int actionId)
|
||||
{
|
||||
if (isDecorated()) {
|
||||
decoration()->showApplicationMenu(actionId);
|
||||
} else {
|
||||
// we don't know where the application menu button will be, show it in the top left corner instead
|
||||
Workspace::self()->showApplicationMenu(QRect(), this, actionId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -255,6 +255,16 @@ class KWIN_EXPORT AbstractClient : public Toplevel
|
|||
* (e.g. "/opt/kde/share/org.kde.foo.desktop") in case it's not in a standard location.
|
||||
**/
|
||||
Q_PROPERTY(QByteArray desktopFileName READ desktopFileName NOTIFY desktopFileNameChanged)
|
||||
|
||||
/**
|
||||
* Whether an application menu is available for this Client
|
||||
*/
|
||||
Q_PROPERTY(bool hasApplicationMenu READ hasApplicationMenu NOTIFY hasApplicationMenuChanged)
|
||||
/**
|
||||
* Whether the application menu for this Client is currently opened
|
||||
*/
|
||||
Q_PROPERTY(bool applicationMenuActive READ applicationMenuActive NOTIFY applicationMenuActiveChanged)
|
||||
|
||||
public:
|
||||
virtual ~AbstractClient();
|
||||
|
||||
|
@ -624,6 +634,25 @@ public:
|
|||
// TODO: remove boolean trap
|
||||
static bool belongToSameApplication(const AbstractClient* c1, const AbstractClient* c2, bool active_hack = false);
|
||||
|
||||
bool hasApplicationMenu() const;
|
||||
bool applicationMenuActive() const {
|
||||
return m_applicationMenuActive;
|
||||
}
|
||||
void setApplicationMenuActive(bool applicationMenuActive);
|
||||
|
||||
QString applicationMenuServiceName() const {
|
||||
return m_applicationMenuServiceName;
|
||||
}
|
||||
QString applicationMenuObjectPath() const {
|
||||
return m_applicationMenuObjectPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request showing the application menu bar
|
||||
* @param actionId The DBus menu ID of the action that should be highlighted, 0 for the root menu
|
||||
*/
|
||||
void showApplicationMenu(int actionId);
|
||||
|
||||
public Q_SLOTS:
|
||||
virtual void closeWindow() = 0;
|
||||
|
||||
|
@ -663,6 +692,8 @@ Q_SIGNALS:
|
|||
void shadeableChanged(bool);
|
||||
void maximizeableChanged(bool);
|
||||
void desktopFileNameChanged();
|
||||
void hasApplicationMenuChanged(bool);
|
||||
void applicationMenuActiveChanged(bool);
|
||||
|
||||
protected:
|
||||
AbstractClient();
|
||||
|
@ -944,6 +975,9 @@ protected:
|
|||
void setDesktopFileName(const QByteArray &name);
|
||||
QString iconFromDesktopFile() const;
|
||||
|
||||
void updateApplicationMenuServiceName(const QString &serviceName);
|
||||
void updateApplicationMenuObjectPath(const QString &objectPath);
|
||||
|
||||
private:
|
||||
void handlePaletteChange();
|
||||
QSharedPointer<TabBox::TabBoxClientImpl> m_tabBoxClient;
|
||||
|
@ -1010,9 +1044,11 @@ private:
|
|||
QPointer<Decoration::DecoratedClientImpl> client;
|
||||
QElapsedTimer doubleClickTimer;
|
||||
} m_decoration;
|
||||
|
||||
QByteArray m_desktopFileName;
|
||||
|
||||
bool m_applicationMenuActive = false;
|
||||
QString m_applicationMenuServiceName;
|
||||
QString m_applicationMenuObjectPath;
|
||||
|
||||
static bool s_haveResizeEffect;
|
||||
};
|
||||
|
|
111
appmenu.cpp
Normal file
111
appmenu.cpp
Normal file
|
@ -0,0 +1,111 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (c) 2011 Lionel Chauvin <megabigbug@yahoo.fr>
|
||||
Copyright (c) 2011,2012 Cédric Bellegarde <gnumdk@gmail.com>
|
||||
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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 2 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#include "appmenu.h"
|
||||
#include "client.h"
|
||||
#include "workspace.h"
|
||||
#include <appmenu_interface.h>
|
||||
|
||||
#include <QDBusObjectPath>
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
KWIN_SINGLETON_FACTORY(ApplicationMenu)
|
||||
|
||||
ApplicationMenu::ApplicationMenu(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_appmenuInterface(new OrgKdeKappmenuInterface(QStringLiteral("org.kde.kappmenu"), QStringLiteral("/KAppMenu"), QDBusConnection::sessionBus(), this))
|
||||
{
|
||||
connect(m_appmenuInterface, &OrgKdeKappmenuInterface::showRequest, this, &ApplicationMenu::slotShowRequest);
|
||||
connect(m_appmenuInterface, &OrgKdeKappmenuInterface::menuShown, this, &ApplicationMenu::slotMenuShown);
|
||||
connect(m_appmenuInterface, &OrgKdeKappmenuInterface::menuHidden, this, &ApplicationMenu::slotMenuHidden);
|
||||
connect(m_appmenuInterface, &OrgKdeKappmenuInterface::reconfigured, this, &ApplicationMenu::slotReconfigured);
|
||||
|
||||
updateApplicationMenuEnabled();
|
||||
}
|
||||
|
||||
ApplicationMenu::~ApplicationMenu()
|
||||
{
|
||||
s_self = nullptr;
|
||||
}
|
||||
|
||||
void ApplicationMenu::slotReconfigured()
|
||||
{
|
||||
updateApplicationMenuEnabled();
|
||||
}
|
||||
|
||||
bool ApplicationMenu::applicationMenuEnabled() const
|
||||
{
|
||||
return m_applicationMenuEnabled;
|
||||
}
|
||||
|
||||
void ApplicationMenu::updateApplicationMenuEnabled()
|
||||
{
|
||||
const bool old_enabled = m_applicationMenuEnabled;
|
||||
|
||||
KConfigGroup config(KSharedConfig::openConfig(QStringLiteral("kdeglobals")), QStringLiteral("Appmenu Style"));
|
||||
const QString &menuStyle = config.readEntry(QStringLiteral("Style"));
|
||||
|
||||
const bool enabled = (menuStyle == QLatin1String("Decoration"));
|
||||
|
||||
if (old_enabled != enabled) {
|
||||
m_applicationMenuEnabled = enabled;
|
||||
emit applicationMenuEnabledChanged(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationMenu::slotShowRequest(const QString &serviceName, const QDBusObjectPath &menuObjectPath, int actionId)
|
||||
{
|
||||
if (AbstractClient *c = findAbstractClientWithApplicationMenu(serviceName, menuObjectPath)) {
|
||||
c->showApplicationMenu(actionId);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationMenu::slotMenuShown(const QString &serviceName, const QDBusObjectPath &menuObjectPath)
|
||||
{
|
||||
if (AbstractClient *c = findAbstractClientWithApplicationMenu(serviceName, menuObjectPath)) {
|
||||
c->setApplicationMenuActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationMenu::slotMenuHidden(const QString &serviceName, const QDBusObjectPath &menuObjectPath)
|
||||
{
|
||||
if (AbstractClient *c = findAbstractClientWithApplicationMenu(serviceName, menuObjectPath)) {
|
||||
c->setApplicationMenuActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
void ApplicationMenu::showApplicationMenu(const QPoint &p, AbstractClient *c, int actionId)
|
||||
{
|
||||
m_appmenuInterface->showMenu(p.x(), p.y(), c->applicationMenuServiceName(), QDBusObjectPath(c->applicationMenuObjectPath()), actionId);
|
||||
}
|
||||
|
||||
AbstractClient *ApplicationMenu::findAbstractClientWithApplicationMenu(const QString &serviceName, const QDBusObjectPath &menuObjectPath)
|
||||
{
|
||||
if (serviceName.isEmpty() || menuObjectPath.path().isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return Workspace::self()->findAbstractClient([&](const AbstractClient *c) {
|
||||
return c->applicationMenuServiceName() == serviceName
|
||||
&& c->applicationMenuObjectPath() == menuObjectPath.path();
|
||||
});
|
||||
}
|
74
appmenu.h
Normal file
74
appmenu.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/********************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (c) 2011 Lionel Chauvin <megabigbug@yahoo.fr>
|
||||
Copyright (c) 2011,2012 Cédric Bellegarde <gnumdk@gmail.com>
|
||||
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
|
||||
|
||||
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 2 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 <http://www.gnu.org/licenses/>.
|
||||
*********************************************************************/
|
||||
#ifndef KWIN_APPLICATIONMENU_H
|
||||
#define KWIN_APPLICATIONMENU_H
|
||||
// KWin
|
||||
#include <kwinglobals.h>
|
||||
// Qt
|
||||
#include <QObject>
|
||||
// xcb
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
class QPoint;
|
||||
class OrgKdeKappmenuInterface;
|
||||
class QDBusObjectPath;
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class AbstractClient;
|
||||
|
||||
class ApplicationMenu : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~ApplicationMenu() override;
|
||||
|
||||
void showApplicationMenu(const QPoint &pos, AbstractClient *c, int actionId);
|
||||
|
||||
bool applicationMenuEnabled() const;
|
||||
|
||||
signals:
|
||||
void applicationMenuEnabledChanged(bool enabled);
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotReconfigured();
|
||||
void slotShowRequest(const QString &serviceName, const QDBusObjectPath &menuObjectPath, int actionId);
|
||||
void slotMenuShown(const QString &serviceName, const QDBusObjectPath &menuObjectPath);
|
||||
void slotMenuHidden(const QString &serviceName, const QDBusObjectPath &menuObjectPath);
|
||||
|
||||
private:
|
||||
void updateApplicationMenuEnabled();
|
||||
|
||||
OrgKdeKappmenuInterface *m_appmenuInterface;
|
||||
|
||||
AbstractClient *findAbstractClientWithApplicationMenu(const QString &serviceName, const QDBusObjectPath &menuObjectPath);
|
||||
|
||||
bool m_applicationMenuEnabled = false;
|
||||
|
||||
KWIN_SINGLETON(ApplicationMenu)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // KWIN_APPLICATIONMENU_H
|
|
@ -59,6 +59,8 @@ Atoms::Atoms()
|
|||
, kwin_dbus_service(QByteArrayLiteral("_ORG_KDE_KWIN_DBUS_SERVICE"))
|
||||
, utf8_string(QByteArrayLiteral("UTF8_STRING"))
|
||||
, wl_surface_id(QByteArrayLiteral("WL_SURFACE_ID"))
|
||||
, kde_net_wm_appmenu_service_name(QByteArrayLiteral("_KDE_NET_WM_APPMENU_SERVICE_NAME"))
|
||||
, kde_net_wm_appmenu_object_path(QByteArrayLiteral("_KDE_NET_WM_APPMENU_OBJECT_PATH"))
|
||||
, m_dtSmWindowInfo(QByteArrayLiteral("_DT_SM_WINDOW_INFO"))
|
||||
, m_motifSupport(QByteArrayLiteral("_MOTIF_WM_INFO"))
|
||||
, m_helpersRetrieved(false)
|
||||
|
|
2
atoms.h
2
atoms.h
|
@ -68,6 +68,8 @@ public:
|
|||
Xcb::Atom kwin_dbus_service;
|
||||
Xcb::Atom utf8_string;
|
||||
Xcb::Atom wl_surface_id;
|
||||
Xcb::Atom kde_net_wm_appmenu_service_name;
|
||||
Xcb::Atom kde_net_wm_appmenu_object_path;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
|
32
client.cpp
32
client.cpp
|
@ -2152,5 +2152,37 @@ QSize Client::resizeIncrements() const
|
|||
return m_geometryHints.resizeIncrements();
|
||||
}
|
||||
|
||||
Xcb::StringProperty Client::fetchApplicationMenuServiceName() const
|
||||
{
|
||||
return Xcb::StringProperty(m_client, atoms->kde_net_wm_appmenu_service_name);
|
||||
}
|
||||
|
||||
void Client::readApplicationMenuServiceName(Xcb::StringProperty &property)
|
||||
{
|
||||
updateApplicationMenuServiceName(QString::fromUtf8(property));
|
||||
}
|
||||
|
||||
void Client::checkApplicationMenuServiceName()
|
||||
{
|
||||
Xcb::StringProperty property = fetchApplicationMenuServiceName();
|
||||
readApplicationMenuServiceName(property);
|
||||
}
|
||||
|
||||
Xcb::StringProperty Client::fetchApplicationMenuObjectPath() const
|
||||
{
|
||||
return Xcb::StringProperty(m_client, atoms->kde_net_wm_appmenu_object_path);
|
||||
}
|
||||
|
||||
void Client::readApplicationMenuObjectPath(Xcb::StringProperty &property)
|
||||
{
|
||||
updateApplicationMenuObjectPath(QString::fromUtf8(property));
|
||||
}
|
||||
|
||||
void Client::checkApplicationMenuObjectPath()
|
||||
{
|
||||
Xcb::StringProperty property = fetchApplicationMenuObjectPath();
|
||||
readApplicationMenuObjectPath(property);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
8
client.h
8
client.h
|
@ -331,6 +331,14 @@ public:
|
|||
**/
|
||||
void showOnScreenEdge() override;
|
||||
|
||||
Xcb::StringProperty fetchApplicationMenuServiceName() const;
|
||||
void readApplicationMenuServiceName(Xcb::StringProperty &property);
|
||||
void checkApplicationMenuServiceName();
|
||||
|
||||
Xcb::StringProperty fetchApplicationMenuObjectPath() const;
|
||||
void readApplicationMenuObjectPath(Xcb::StringProperty &property);
|
||||
void checkApplicationMenuObjectPath();
|
||||
|
||||
static void cleanupX11();
|
||||
|
||||
public Q_SLOTS:
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace Decoration
|
|||
|
||||
DecoratedClientImpl::DecoratedClientImpl(AbstractClient *client, KDecoration2::DecoratedClient *decoratedClient, KDecoration2::Decoration *decoration)
|
||||
: QObject()
|
||||
, DecoratedClientPrivate(decoratedClient, decoration)
|
||||
, ApplicationMenuEnabledDecoratedClientPrivate(decoratedClient, decoration)
|
||||
, m_client(client)
|
||||
, m_clientSize(client->clientSize())
|
||||
, m_renderer(nullptr)
|
||||
|
@ -110,6 +110,9 @@ DecoratedClientImpl::DecoratedClientImpl(AbstractClient *client, KDecoration2::D
|
|||
connect(client, &AbstractClient::maximizeableChanged, decoratedClient, &KDecoration2::DecoratedClient::maximizeableChanged);
|
||||
|
||||
connect(client, &AbstractClient::paletteChanged, decoratedClient, &KDecoration2::DecoratedClient::paletteChanged);
|
||||
|
||||
connect(client, &AbstractClient::hasApplicationMenuChanged, decoratedClient, &KDecoration2::DecoratedClient::hasApplicationMenuChanged);
|
||||
connect(client, &AbstractClient::applicationMenuActiveChanged, decoratedClient, &KDecoration2::DecoratedClient::applicationMenuActiveChanged);
|
||||
}
|
||||
|
||||
DecoratedClientImpl::~DecoratedClientImpl() = default;
|
||||
|
@ -203,6 +206,16 @@ void DecoratedClientImpl::requestShowWindowMenu()
|
|||
Workspace::self()->showWindowMenu(QRect(Cursor::pos(), Cursor::pos()), m_client);
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::requestShowApplicationMenu(const QRect &rect, int actionId)
|
||||
{
|
||||
Workspace::self()->showApplicationMenu(rect, m_client, actionId);
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::showApplicationMenu(int actionId)
|
||||
{
|
||||
decoration()->showApplicationMenu(actionId);
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::requestToggleMaximization(Qt::MouseButtons buttons)
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "delayedRequestToggleMaximization", Qt::QueuedConnection, Q_ARG(Options::WindowOperation, options->operationMaxButtonClick(buttons)));
|
||||
|
@ -265,6 +278,16 @@ Qt::Edges DecoratedClientImpl::adjacentScreenEdges() const
|
|||
return edges;
|
||||
}
|
||||
|
||||
bool DecoratedClientImpl::hasApplicationMenu() const
|
||||
{
|
||||
return m_client->hasApplicationMenu();
|
||||
}
|
||||
|
||||
bool DecoratedClientImpl::isApplicationMenuActive() const
|
||||
{
|
||||
return m_client->applicationMenuActive();
|
||||
}
|
||||
|
||||
void DecoratedClientImpl::createRenderer()
|
||||
{
|
||||
if (Compositor::self()->hasScene()) {
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace Decoration
|
|||
|
||||
class Renderer;
|
||||
|
||||
class DecoratedClientImpl : public QObject, public KDecoration2::DecoratedClientPrivate
|
||||
class DecoratedClientImpl : public QObject, public KDecoration2::ApplicationMenuEnabledDecoratedClientPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
@ -69,16 +69,22 @@ public:
|
|||
|
||||
Qt::Edges adjacentScreenEdges() const override;
|
||||
|
||||
bool hasApplicationMenu() const override;
|
||||
bool isApplicationMenuActive() const override;
|
||||
|
||||
void requestClose() override;
|
||||
void requestContextHelp() override;
|
||||
void requestToggleMaximization(Qt::MouseButtons buttons) override;
|
||||
void requestMinimize() override;
|
||||
void requestShowWindowMenu() override;
|
||||
void requestShowApplicationMenu(const QRect &rect, int actionId) override;
|
||||
void requestToggleKeepAbove() override;
|
||||
void requestToggleKeepBelow() override;
|
||||
void requestToggleOnAllDesktops() override;
|
||||
void requestToggleShade() override;
|
||||
|
||||
void showApplicationMenu(int actionId);
|
||||
|
||||
AbstractClient *client() {
|
||||
return m_client;
|
||||
}
|
||||
|
|
|
@ -155,6 +155,7 @@ void SettingsImpl::readSettings()
|
|||
KConfigGroup config = kwinApp()->config()->group(QStringLiteral("org.kde.kdecoration2"));
|
||||
const auto &left = readDecorationButtons(config, "ButtonsOnLeft", QVector<KDecoration2::DecorationButtonType >({
|
||||
KDecoration2::DecorationButtonType::Menu,
|
||||
KDecoration2::DecorationButtonType::ApplicationMenu,
|
||||
KDecoration2::DecorationButtonType::OnAllDesktops
|
||||
}));
|
||||
if (left != m_leftButtons) {
|
||||
|
|
|
@ -923,6 +923,10 @@ void Client::propertyNotifyEvent(xcb_property_notify_event_t *e)
|
|||
updateShowOnScreenEdge();
|
||||
else if (e->atom == atoms->gtk_frame_extents)
|
||||
detectGtkFrameExtents();
|
||||
else if (e->atom == atoms->kde_net_wm_appmenu_service_name)
|
||||
checkApplicationMenuServiceName();
|
||||
else if (e->atom == atoms->kde_net_wm_appmenu_object_path)
|
||||
checkApplicationMenuObjectPath();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ ButtonsModel::ButtonsModel(const QVector< DecorationButtonType > &buttons, QObje
|
|||
ButtonsModel::ButtonsModel(QObject* parent)
|
||||
: ButtonsModel(QVector<DecorationButtonType>({
|
||||
DecorationButtonType::Menu,
|
||||
DecorationButtonType::ApplicationMenu,
|
||||
DecorationButtonType::OnAllDesktops,
|
||||
DecorationButtonType::Minimize,
|
||||
DecorationButtonType::Maximize,
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace Preview
|
|||
|
||||
PreviewClient::PreviewClient(DecoratedClient *c, Decoration *decoration)
|
||||
: QObject(decoration)
|
||||
, DecoratedClientPrivate(c, decoration)
|
||||
, ApplicationMenuEnabledDecoratedClientPrivate(c, decoration)
|
||||
, m_colorSchemeManager(new KColorSchemeManager(this))
|
||||
, m_colorSchemeIndex(0)
|
||||
, m_icon(QIcon::fromTheme(QStringLiteral("start-here-kde")))
|
||||
|
@ -309,6 +309,16 @@ Qt::Edges PreviewClient::adjacentScreenEdges() const
|
|||
return edges;
|
||||
}
|
||||
|
||||
bool PreviewClient::hasApplicationMenu() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PreviewClient::isApplicationMenuActive() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PreviewClient::bordersBottomEdge() const
|
||||
{
|
||||
return m_bordersBottomEdge;
|
||||
|
@ -408,6 +418,17 @@ void PreviewClient::requestShowWindowMenu()
|
|||
emit showWindowMenuRequested();
|
||||
}
|
||||
|
||||
void PreviewClient::requestShowApplicationMenu(const QRect &rect, int actionId)
|
||||
{
|
||||
Q_UNUSED(rect);
|
||||
Q_UNUSED(actionId);
|
||||
}
|
||||
|
||||
void PreviewClient::showApplicationMenu(int actionId)
|
||||
{
|
||||
Q_UNUSED(actionId)
|
||||
}
|
||||
|
||||
void PreviewClient::requestToggleOnAllDesktops()
|
||||
{
|
||||
setDesktop(isOnAllDesktops() ? 1 : -1);
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace KDecoration2
|
|||
{
|
||||
namespace Preview
|
||||
{
|
||||
class PreviewClient : public QObject, public DecoratedClientPrivate
|
||||
class PreviewClient : public QObject, public ApplicationMenuEnabledDecoratedClientPrivate
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(KDecoration2::Decoration *decoration READ decoration CONSTANT)
|
||||
|
@ -97,6 +97,9 @@ public:
|
|||
QColor color(ColorGroup group, ColorRole role) const override;
|
||||
Qt::Edges adjacentScreenEdges() const override;
|
||||
|
||||
bool hasApplicationMenu() const override;
|
||||
bool isApplicationMenuActive() const override;
|
||||
|
||||
void requestClose() override;
|
||||
void requestContextHelp() override;
|
||||
void requestToggleMaximization(Qt::MouseButtons buttons) override;
|
||||
|
@ -105,8 +108,11 @@ public:
|
|||
void requestToggleKeepBelow() override;
|
||||
void requestToggleShade() override;
|
||||
void requestShowWindowMenu() override;
|
||||
void requestShowApplicationMenu(const QRect &rect, int actionId) override;
|
||||
void requestToggleOnAllDesktops() override;
|
||||
|
||||
void showApplicationMenu(int actionId);
|
||||
|
||||
void setCaption(const QString &caption);
|
||||
void setActive(bool active);
|
||||
void setCloseable(bool closeable);
|
||||
|
@ -176,6 +182,7 @@ Q_SIGNALS:
|
|||
void bordersBottomEdgeChanged(bool);
|
||||
|
||||
void showWindowMenuRequested();
|
||||
void showApplicationMenuRequested();
|
||||
void minimizeRequested();
|
||||
void closeRequested();
|
||||
|
||||
|
|
|
@ -72,6 +72,7 @@ PreviewSettings::PreviewSettings(DecorationSettings *parent)
|
|||
, m_closeOnDoubleClick(false)
|
||||
, m_leftButtons(new ButtonsModel(QVector<DecorationButtonType>({
|
||||
DecorationButtonType::Menu,
|
||||
DecorationButtonType::ApplicationMenu,
|
||||
DecorationButtonType::OnAllDesktops
|
||||
}), this))
|
||||
, m_rightButtons(new ButtonsModel(QVector<DecorationButtonType>({
|
||||
|
|
|
@ -104,6 +104,9 @@ bool Client::manage(xcb_window_t w, bool isMapped)
|
|||
auto firstInTabBoxCookie = fetchFirstInTabBox();
|
||||
auto transientCookie = fetchTransient();
|
||||
auto activitiesCookie = fetchActivities();
|
||||
auto applicationMenuServiceNameCookie = fetchApplicationMenuServiceName();
|
||||
auto applicationMenuObjectPathCookie = fetchApplicationMenuObjectPath();
|
||||
|
||||
m_geometryHints.init(window());
|
||||
m_motif.init(window());
|
||||
info = new WinInfo(this, m_client, rootWindow(), properties, properties2);
|
||||
|
@ -391,6 +394,9 @@ bool Client::manage(xcb_window_t w, bool isMapped)
|
|||
|
||||
readColorScheme(colorSchemeCookie);
|
||||
|
||||
readApplicationMenuServiceName(applicationMenuServiceNameCookie);
|
||||
readApplicationMenuObjectPath(applicationMenuObjectPathCookie);
|
||||
|
||||
updateDecoration(false); // Also gravitates
|
||||
// TODO: Is CentralGravity right here, when resizing is done after gravitating?
|
||||
plainResize(rules()->checkSize(sizeForClientSize(geom.size()), !isMapped));
|
||||
|
|
28
org.kde.kappmenu.xml
Normal file
28
org.kde.kappmenu.xml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.kappmenu">
|
||||
<method name="showMenu">
|
||||
<arg name="x" type="i" direction="in"/>
|
||||
<arg name="y" type="i" direction="in"/>
|
||||
<arg name="service" type="s" direction="in"/>
|
||||
<arg name="objectPath" type="o" direction="in"/>
|
||||
<arg name="actionId" type="i" direction="in"/>
|
||||
</method>
|
||||
<method name="reconfigure">
|
||||
</method>
|
||||
<signal name="reconfigured" />
|
||||
<signal name="showRequest">
|
||||
<arg name="service" type="s" direction="out"/>
|
||||
<arg name="objectPath" type="o" direction="out"/>
|
||||
<arg name="actionId" type="i" direction="out"/>
|
||||
</signal>
|
||||
<signal name="menuShown">
|
||||
<arg name="service" type="s" direction="out"/>
|
||||
<arg name="objectPath" type="o" direction="out"/>
|
||||
</signal>
|
||||
<signal name="menuHidden">
|
||||
<arg name="service" type="s" direction="out"/>
|
||||
<arg name="objectPath" type="o" direction="out"/>
|
||||
</signal>
|
||||
</interface>
|
||||
</node>
|
|
@ -56,6 +56,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
using namespace KWayland::Server;
|
||||
|
||||
static const QByteArray s_schemePropertyName = QByteArrayLiteral("KDE_COLOR_SCHEME_PATH");
|
||||
static const QByteArray s_appMenuServiceNamePropertyName = QByteArrayLiteral("KDE_APPMENU_SERVICE_NAME");
|
||||
static const QByteArray s_appMenuObjectPathPropertyName = QByteArrayLiteral("KDE_APPMENU_OBJECT_PATH");
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -252,6 +254,7 @@ void ShellClient::init()
|
|||
}
|
||||
|
||||
updateColorScheme(QString());
|
||||
updateApplicationMenu();
|
||||
}
|
||||
|
||||
void ShellClient::destroyClient()
|
||||
|
@ -1234,6 +1237,10 @@ bool ShellClient::eventFilter(QObject *watched, QEvent *event)
|
|||
QDynamicPropertyChangeEvent *pe = static_cast<QDynamicPropertyChangeEvent*>(event);
|
||||
if (pe->propertyName() == s_schemePropertyName) {
|
||||
updateColorScheme(rules()->checkDecoColor(m_qtExtendedSurface->property(pe->propertyName().constData()).toString()));
|
||||
} else if (pe->propertyName() == s_appMenuServiceNamePropertyName) {
|
||||
updateApplicationMenuServiceName(m_qtExtendedSurface->property(pe->propertyName().constData()).toString());
|
||||
} else if (pe->propertyName() == s_appMenuObjectPathPropertyName) {
|
||||
updateApplicationMenuObjectPath(m_qtExtendedSurface->property(pe->propertyName().constData()).toString());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -1466,4 +1473,12 @@ void ShellClient::killWindow()
|
|||
QTimer::singleShot(5000, c, &ClientConnection::destroy);
|
||||
}
|
||||
|
||||
void ShellClient::updateApplicationMenu()
|
||||
{
|
||||
if (m_qtExtendedSurface) {
|
||||
updateApplicationMenuServiceName(m_qtExtendedSurface->property(s_appMenuObjectPathPropertyName).toString());
|
||||
updateApplicationMenuObjectPath(m_qtExtendedSurface->property(s_appMenuServiceNamePropertyName).toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -137,6 +137,8 @@ public:
|
|||
// TODO: const-ref
|
||||
void placeIn(QRect &area);
|
||||
|
||||
void updateApplicationMenu();
|
||||
|
||||
protected:
|
||||
void addDamage(const QRegion &damage) override;
|
||||
bool belongsToSameApplication(const AbstractClient *other, bool active_hack) const override;
|
||||
|
|
|
@ -45,6 +45,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "activities.h"
|
||||
#include <kactivities/info.h>
|
||||
#endif
|
||||
#include "appmenu.h"
|
||||
|
||||
#include <KProcess>
|
||||
|
||||
|
@ -1702,6 +1703,11 @@ void Workspace::showWindowMenu(const QRect &pos, AbstractClient* cl)
|
|||
m_userActionsMenu->show(pos, cl);
|
||||
}
|
||||
|
||||
void Workspace::showApplicationMenu(const QRect &pos, AbstractClient *c, int actionId)
|
||||
{
|
||||
ApplicationMenu::self()->showApplicationMenu(c->geometry().topLeft() + pos.bottomLeft(), c, actionId);
|
||||
}
|
||||
|
||||
/*!
|
||||
Closes the popup client
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#ifdef KWIN_BUILD_ACTIVITIES
|
||||
#include "activities.h"
|
||||
#endif
|
||||
#include "appmenu.h"
|
||||
#include "atoms.h"
|
||||
#include "client.h"
|
||||
#include "composite.h"
|
||||
|
@ -128,6 +129,8 @@ Workspace::Workspace(const QString &sessionKey)
|
|||
// If KWin was already running it saved its configuration after loosing the selection -> Reread
|
||||
QFuture<void> reparseConfigFuture = QtConcurrent::run(options, &Options::reparseConfiguration);
|
||||
|
||||
ApplicationMenu::create(this);
|
||||
|
||||
_self = this;
|
||||
|
||||
// first initialize the extensions
|
||||
|
|
|
@ -285,6 +285,8 @@ public:
|
|||
return m_userActionsMenu;
|
||||
}
|
||||
|
||||
void showApplicationMenu(const QRect &pos, AbstractClient *c, int actionId);
|
||||
|
||||
void updateMinimizedOfTransients(AbstractClient*);
|
||||
void updateOnAllDesktopsOfTransients(AbstractClient*);
|
||||
void checkTransients(xcb_window_t w);
|
||||
|
|
Loading…
Reference in a new issue