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
icc-effect-5.14.5
Kai Uwe Broulik 2017-01-11 10:21:03 +01:00
parent e616925fb0
commit 93938d60b8
24 changed files with 454 additions and 5 deletions

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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
View 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
View 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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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()) {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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);

View File

@ -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();

View File

@ -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>({

View File

@ -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
View 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>

View File

@ -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());
}
}
}

View File

@ -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;

View File

@ -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
*/

View File

@ -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

View File

@ -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);