diff --git a/appmenu/appmenu.cpp b/appmenu/appmenu.cpp index 7c956c6e9..4ab710677 100644 --- a/appmenu/appmenu.cpp +++ b/appmenu/appmenu.cpp @@ -1,211 +1,211 @@ /* This file is part of the KDE project. Copyright (c) 2011 Lionel Chauvin Copyright (c) 2011,2012 Cédric Bellegarde Copyright (c) 2016 Kai Uwe Broulik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include #include "appmenu.h" #include "kdbusimporter.h" #include "menuimporteradaptor.h" #include "appmenuadaptor.h" #include "appmenu_dbus.h" #include "verticalmenu.h" #include #include #include #include #include #include #include #include #include #if HAVE_X11 #include #include #endif static const QByteArray s_x11AppMenuServiceNamePropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_SERVICE_NAME"); static const QByteArray s_x11AppMenuObjectPathPropertyName = QByteArrayLiteral("_KDE_NET_WM_APPMENU_OBJECT_PATH"); K_PLUGIN_FACTORY_WITH_JSON(AppMenuFactory, "appmenu.json", registerPlugin();) AppMenuModule::AppMenuModule(QObject* parent, const QList&) : KDEDModule(parent), m_appmenuDBus(new AppmenuDBus(this)) { reconfigure(); m_appmenuDBus->connectToBus(); connect(m_appmenuDBus, &AppmenuDBus::appShowMenu, this, &AppMenuModule::slotShowMenu); connect(m_appmenuDBus, &AppmenuDBus::reconfigured, this, &AppMenuModule::reconfigure); // transfer our signals to dbus connect(this, &AppMenuModule::showRequest, m_appmenuDBus, &AppmenuDBus::showRequest); connect(this, &AppMenuModule::menuHidden, m_appmenuDBus, &AppmenuDBus::menuHidden); connect(this, &AppMenuModule::menuShown, m_appmenuDBus, &AppmenuDBus::menuShown); m_menuViewWatcher = new QDBusServiceWatcher(QStringLiteral("org.kde.kappmenuview"), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForRegistration|QDBusServiceWatcher::WatchForUnregistration, this); auto setupMenuImporter = [this]() { QDBusConnection::sessionBus().connect({}, {}, QStringLiteral("com.canonical.dbusmenu"), QStringLiteral("ItemActivationRequested"), this, SLOT(itemActivationRequested(int,uint))); // Setup a menu importer if needed if (!m_menuImporter) { m_menuImporter = new MenuImporter(this); connect(m_menuImporter, &MenuImporter::WindowRegistered, this, &AppMenuModule::slotWindowRegistered); m_menuImporter->connectToBus(); } }; connect(m_menuViewWatcher, &QDBusServiceWatcher::serviceRegistered, this, setupMenuImporter); connect(m_menuViewWatcher, &QDBusServiceWatcher::serviceUnregistered, this, [this](const QString &service) { Q_UNUSED(service) QDBusConnection::sessionBus().disconnect({}, {}, QStringLiteral("com.canonical.dbusmenu"), QStringLiteral("ItemActivationRequested"), this, SLOT(itemActivationRequested(int,uint))); delete m_menuImporter; m_menuImporter = nullptr; }); if (QDBusConnection::sessionBus().interface()->isServiceRegistered(QStringLiteral("org.kde.kappmenuview"))) { setupMenuImporter(); } } AppMenuModule::~AppMenuModule() = default; void AppMenuModule::slotWindowRegistered(WId id, const QString &serviceName, const QDBusObjectPath &menuObjectPath) { -#ifdef HAVE_X11 +#if HAVE_X11 if (KWindowSystem::isPlatformX11()) { auto *c = QX11Info::connection(); static xcb_atom_t s_serviceNameAtom = XCB_ATOM_NONE; static xcb_atom_t s_objectPathAtom = XCB_ATOM_NONE; auto setWindowProperty = [c](WId id, xcb_atom_t &atom, const QByteArray &name, const QByteArray &value) { if (atom == XCB_ATOM_NONE) { const xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, false, name.length(), name.constData()); QScopedPointer reply(xcb_intern_atom_reply(c, cookie, nullptr)); if (reply.isNull()) { return; } atom = reply->atom; if (atom == XCB_ATOM_NONE) { return; } } xcb_change_property(c, XCB_PROP_MODE_REPLACE, id, atom, XCB_ATOM_STRING, 8, value.length(), value.constData()); }; // TODO only set the property if it doesn't already exist setWindowProperty(id, s_serviceNameAtom, s_x11AppMenuServiceNamePropertyName, serviceName.toUtf8()); setWindowProperty(id, s_objectPathAtom, s_x11AppMenuObjectPathPropertyName, menuObjectPath.path().toUtf8()); } #endif } void AppMenuModule::slotShowMenu(int x, int y, const QString &serviceName, const QDBusObjectPath &menuObjectPath, int actionId) { if (!m_menuImporter) { return; } // If menu visible, hide it if (m_menu && m_menu.data()->isVisible()) { m_menu.data()->hide(); return; } //dbus call by user (for khotkey shortcut) if (x == -1 || y == -1) { // We do not know kwin button position, so tell kwin to show menu emit showRequest(serviceName, menuObjectPath, actionId); return; } auto *importer = new KDBusMenuImporter(serviceName, menuObjectPath.path(), this); QMetaObject::invokeMethod(importer, "updateMenu", Qt::QueuedConnection); disconnect(importer, nullptr, this, nullptr); // ensure we don't popup multiple times in case the menu updates again later connect(importer, &KDBusMenuImporter::menuUpdated, this, [=](QMenu *m) { QMenu *menu = importer->menu(); if (!menu || menu != m) { return; } m_menu = qobject_cast(menu); m_menu.data()->setServiceName(serviceName); m_menu.data()->setMenuObjectPath(menuObjectPath); connect(m_menu.data(), &QMenu::aboutToHide, this, [this, importer] { hideMenu(); importer->deleteLater(); }); //m_menuImporter->fakeUnityAboutToShow(serviceName, menuObjectPath); m_menu.data()->popup(QPoint(x, y) / qApp->devicePixelRatio()); QAction *actiontoActivate = importer->actionForId(actionId); emit menuShown(serviceName, menuObjectPath); if (actiontoActivate) { m_menu.data()->setActiveAction(actiontoActivate); } }); } void AppMenuModule::hideMenu() { if (m_menu) { emit menuHidden(m_menu.data()->serviceName(), m_menu->menuObjectPath()); } } void AppMenuModule::itemActivationRequested(int actionId, uint timeStamp) { Q_UNUSED(timeStamp); emit showRequest(message().service(), QDBusObjectPath(message().path()), actionId); } // this method is not really used anymore but has to be kept for DBus compatibility void AppMenuModule::reconfigure() { } #include "appmenu.moc" diff --git a/config-X11.h.cmake b/config-X11.h.cmake index 60286dd63..ae8978a08 100644 --- a/config-X11.h.cmake +++ b/config-X11.h.cmake @@ -1,44 +1,44 @@ /* Define if you have the XRandR extension */ #cmakedefine HAVE_XRANDR 1 /* Define if you have the XDamage extension */ #cmakedefine HAVE_XDAMAGE 1 /* Define if you have the XKB extension */ #cmakedefine HAVE_XKB 1 /* Define if you have the Xinerama extension */ #cmakedefine HAVE_XINERAMA 1 /* Define if you have the XSHM (MIT SHM) extension */ #cmakedefine HAVE_XSHM 1 /* Define if you have the XComposite extension */ #cmakedefine HAVE_XCOMPOSITE 1 /* Define to 1 if you have Xcursor */ #cmakedefine HAVE_XCURSOR 1 /* Define if you have the xf86misc extension */ #cmakedefine HAVE_XF86MISC 1 /* Define if you have the XFixes extension */ #cmakedefine HAVE_XFIXES 1 /* Define if you have the XTest extension */ #cmakedefine HAVE_XTEST 1 /* Define if your system has XRender support */ #cmakedefine HAVE_XRENDER 1 /* Define if you have OpenGL */ #cmakedefine HAVE_OPENGL 1 /* Define if you have the XSync extension */ #cmakedefine HAVE_XSYNC 1 /* Define if you have XRandR 1.3 */ #cmakedefine HAS_RANDR_1_3 1 /* Define if you have X11 at all */ -#define HAVE_X11 ${X11_FOUND} +#cmakedefine01 HAVE_X11 diff --git a/libkworkspace/config-libkworkspace.h.cmake b/libkworkspace/config-libkworkspace.h.cmake index 36a826ee9..c3ae6d787 100644 --- a/libkworkspace/config-libkworkspace.h.cmake +++ b/libkworkspace/config-libkworkspace.h.cmake @@ -1,2 +1,2 @@ /* Define if you have X11 at all */ -#define HAVE_X11 ${X11_FOUND} +#cmakedefine01 HAVE_X11 diff --git a/runners/windows/config-windowsrunner.h.cmake b/runners/windows/config-windowsrunner.h.cmake index 36a826ee9..c3ae6d787 100644 --- a/runners/windows/config-windowsrunner.h.cmake +++ b/runners/windows/config-windowsrunner.h.cmake @@ -1,2 +1,2 @@ /* Define if you have X11 at all */ -#define HAVE_X11 ${X11_FOUND} +#cmakedefine01 HAVE_X11 diff --git a/shell/scripting/appinterface.cpp b/shell/scripting/appinterface.cpp index bd66cd2b1..a0ad73cf4 100644 --- a/shell/scripting/appinterface.cpp +++ b/shell/scripting/appinterface.cpp @@ -1,228 +1,228 @@ /* * Copyright 2009 Aaron Seigo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2, 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 Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "appinterface.h" #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_WIN #include #endif -#ifdef HAVE_X11 +#if HAVE_X11 #include #include #endif #include "scriptengine.h" namespace WorkspaceScripting { AppInterface::AppInterface(ScriptEngine *env) : QObject(env), m_env(env) { m_theme = new Plasma::Theme(this); } int AppInterface::screenCount() const { return m_env->corona()->numScreens(); } QJSValue AppInterface::screenGeometry(int screen) const { QRectF rect = m_env->corona()->screenGeometry(screen); QJSValueList args({QJSValue(rect.x()), QJSValue(rect.y()), QJSValue(rect.width()), QJSValue(rect.height())}); return m_env->globalObject().property("QRectF").callAsConstructor(args); } QList AppInterface::activityIds() const { //FIXME: the ints could overflow since Applet::id() returns a uint, // however QScript deals with QList very, very poorly QList containments; foreach (Plasma::Containment *c, m_env->corona()->containments()) { if (!ScriptEngine::isPanel(c)) { containments.append(c->id()); } } return containments; } QList AppInterface::panelIds() const { //FIXME: the ints could overflow since Applet::id() returns a uint, // however QScript deals with QList very, very poorly QList panels; foreach (Plasma::Containment *c, m_env->corona()->containments()) { //qDebug() << "checking" << (QObject*)c << isPanel(c); if (ScriptEngine::isPanel(c)) { panels.append(c->id()); } } return panels; } QString AppInterface::applicationVersion() const { return qApp->applicationVersion(); } QString AppInterface::platformVersion() const { return QString();//KDE::versionString(); } int AppInterface::scriptingVersion() const { return PLASMA_DESKTOP_SCRIPTING_VERSION; } QString AppInterface::theme() const { return m_theme->themeName(); } void AppInterface::setTheme(const QString &name) { m_theme->setThemeName(name); } QString AppInterface::locale() const { return QLocale::system().name(); } QString AppInterface::language() const { return QLocale::system().languageToString(QLocale::system().language()); } QString AppInterface::languageId() const { return QLocale::system().bcp47Name().section(QLatin1Char('-'), 0, 0); } bool AppInterface::multihead() const { return false; } int AppInterface::multiheadScreen() const { return 0; } void AppInterface::lockCorona(bool locked) { m_env->corona()->setImmutability(locked ? Plasma::Types::UserImmutable : Plasma::Types::Mutable); } bool AppInterface::coronaLocked() const { return m_env->corona()->immutability() != Plasma::Types::Mutable; } void AppInterface::sleep(int ms) { QEventLoop loop; QTimer::singleShot(ms, &loop, &QEventLoop::quit); loop.exec(QEventLoop::ExcludeUserInputEvents); } bool AppInterface::hasBattery() const { QList batteryDevices = Solid::Device::listFromType(Solid::DeviceInterface::Battery); for (auto device: batteryDevices) { Solid::Battery *battery = device.as(); // check for _both_ primary and power supply status // apparently some devices misreport as "primary", and we don't // want to trigger on just having UPC connected to a desktop box if (battery && battery->type() == Solid::Battery::PrimaryBattery && battery->isPowerSupply()) { return true; } } return false; } QStringList AppInterface::knownWidgetTypes() const { if (m_knownWidgets.isEmpty()) { QStringList widgets; KPluginInfo::List infoLs = Plasma::PluginLoader::self()->listAppletInfo(QString()); foreach (const KPluginInfo &info, infoLs) { widgets.append(info.pluginName()); } const_cast(this)->m_knownWidgets = widgets; } return m_knownWidgets; } QStringList AppInterface::knownActivityTypes() const { return knownContainmentTypes(QStringLiteral("desktop")); } QStringList AppInterface::knownPanelTypes() const { return knownContainmentTypes(QStringLiteral("panel")); } QStringList AppInterface::knownContainmentTypes(const QString &type) const { QStringList containments; const KPluginInfo::List infoLs = Plasma::PluginLoader::listContainmentsOfType(type); containments.reserve(infoLs.count()); foreach (const KPluginInfo &info, infoLs) { containments.append(info.pluginName()); } return containments; } } diff --git a/soliduiserver/soliduiserver.cpp b/soliduiserver/soliduiserver.cpp index 3ec09c066..d06a1e6a5 100644 --- a/soliduiserver/soliduiserver.cpp +++ b/soliduiserver/soliduiserver.cpp @@ -1,235 +1,235 @@ /* This file is part of the KDE Project Copyright (c) 2005 Jean-Remy Falleri Copyright (c) 2005-2007 Kevin Ottens Copyright (c) 2007 Alexis Ménard Copyright (c) 2011, 2014 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "soliduiserver.h" #include "config-X11.h" #include #include #include #include #include #include #include #include #include #include #include #include "deviceactionsdialog.h" #include "deviceaction.h" #include "deviceserviceaction.h" #include "devicenothingaction.h" K_PLUGIN_CLASS_WITH_JSON(SolidUiServer, "soliduiserver.json") SolidUiServer::SolidUiServer(QObject* parent, const QList&) : KDEDModule(parent) { } SolidUiServer::~SolidUiServer() { } void SolidUiServer::showActionsDialog(const QString &udi, const QStringList &desktopFiles) { if (m_udiToActionsDialog.contains(udi)) { DeviceActionsDialog *dialog = m_udiToActionsDialog[udi]; dialog->activateWindow(); return; } QList actions; foreach (const QString &desktop, desktopFiles) { const QString filePath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "solid/actions/"+desktop); QList services = KDesktopFileActions::userDefinedServices(filePath, true); foreach (const KServiceAction &service, services) { DeviceServiceAction *action = new DeviceServiceAction(); action->setService(service); actions << action; } } // Only one action, execute directly if (actions.size()==1) { DeviceAction *action = actions.takeFirst(); Solid::Device device(udi); action->execute(device); delete action; return; } actions << new DeviceNothingAction(); DeviceActionsDialog *dialog = new DeviceActionsDialog(); dialog->setDevice(Solid::Device(udi)); dialog->setActions(actions); connect(dialog, &DeviceActionsDialog::finished, this, &SolidUiServer::onActionDialogFinished); m_udiToActionsDialog[udi] = dialog; // Update user activity timestamp, otherwise the notification dialog will be shown // in the background due to focus stealing prevention. Entering a new media can // be seen as a kind of user activity after all. It'd be better to update the timestamp // as soon as the media is entered, but it apparently takes some time to get here. KUserTimestamp::updateUserTimestamp(); dialog->show(); } void SolidUiServer::onActionDialogFinished() { DeviceActionsDialog *dialog = qobject_cast(sender()); if (dialog) { QString udi = dialog->device().udi(); m_udiToActionsDialog.remove(udi); } } void SolidUiServer::showPassphraseDialog(const QString &udi, const QString &returnService, const QString &returnObject, uint wId, const QString &appId) { if (m_idToPassphraseDialog.contains(returnService+':'+udi)) { KPasswordDialog *dialog = m_idToPassphraseDialog[returnService+':'+udi]; dialog->activateWindow(); return; } Solid::Device device(udi); KPasswordDialog *dialog = new KPasswordDialog(nullptr, KPasswordDialog::ShowKeepPassword); QString label = device.vendor(); if (!label.isEmpty()) label+=' '; label+= device.product(); dialog->setPrompt(i18n("'%1' needs a password to be accessed. Please enter a password.", label)); dialog->setPixmap(QIcon::fromTheme(device.icon()).pixmap(64, 64)); dialog->setProperty("soliduiserver.udi", udi); dialog->setProperty("soliduiserver.returnService", returnService); dialog->setProperty("soliduiserver.returnObject", returnObject); QString uuid; if (device.is()) uuid = device.as()->uuid(); // read the password from wallet and prefill it to the dialog if (!uuid.isEmpty()) { dialog->setProperty("soliduiserver.uuid", uuid); KWallet::Wallet * wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), (WId) wId); const QString folderName = QString::fromLatin1("SolidLuks"); if (wallet && wallet->hasFolder(folderName)) { wallet->setFolder(folderName); QString savedPassword; if (wallet->readPassword(uuid, savedPassword) == 0) { dialog->setKeepPassword(true); dialog->setPassword(savedPassword); } wallet->closeWallet(wallet->walletName(), false); } delete wallet; } connect(dialog, &KPasswordDialog::gotPassword, this, &SolidUiServer::onPassphraseDialogCompleted); connect(dialog, &KPasswordDialog::rejected, this, &SolidUiServer::onPassphraseDialogRejected); m_idToPassphraseDialog[returnService+':'+udi] = dialog; reparentDialog(dialog, (WId)wId, appId, true); dialog->show(); } void SolidUiServer::onPassphraseDialogCompleted(const QString &pass, bool keep) { KPasswordDialog *dialog = qobject_cast(sender()); if (dialog) { QString returnService = dialog->property("soliduiserver.returnService").toString(); QString returnObject = dialog->property("soliduiserver.returnObject").toString(); QDBusInterface returnIface(returnService, returnObject); QDBusReply reply = returnIface.call(QStringLiteral("passphraseReply"), pass); QString udi = dialog->property("soliduiserver.udi").toString(); m_idToPassphraseDialog.remove(returnService+':'+udi); if (!reply.isValid()) { qWarning() << "Impossible to send the passphrase to the application, D-Bus said: " << reply.error().name() << ", " << reply.error().message() << endl; return; // don't save into wallet if an error occurs } if (keep) { // save the password into the wallet KWallet::Wallet * wallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), 0); if (wallet) { const QString folderName = QString::fromLatin1("SolidLuks"); const QString uuid = dialog->property("soliduiserver.uuid").toString(); if (!wallet->hasFolder(folderName)) wallet->createFolder(folderName); if (wallet->setFolder(folderName)) wallet->writePassword(uuid, pass); wallet->closeWallet(wallet->walletName(), false); delete wallet; } } } } void SolidUiServer::onPassphraseDialogRejected() { onPassphraseDialogCompleted(QString(), false); } void SolidUiServer::reparentDialog(QWidget *dialog, WId wId, const QString &appId, bool modal) { Q_UNUSED(appId); // Code borrowed from kwalletd KWindowSystem::setMainWindow(dialog, wId); // correct, set dialog parent -#ifdef HAVE_X11 +#if HAVE_X11 if (modal) { KWindowSystem::setState(dialog->winId(), NET::Modal); } else { KWindowSystem::clearState(dialog->winId(), NET::Modal); } #endif // allow dialog activation even if it interrupts, better than trying hacks // with keeping the dialog on top or on all desktops KUserTimestamp::updateUserTimestamp(); } #include "soliduiserver.moc"