/* * Copyright 2015 Kai Uwe Broulik * * 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) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * 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 . */ #include "switchuserdialog.h" #include "ksmserver_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KSMSwitchUserDialog::KSMSwitchUserDialog(KDisplayManager *dm, KWayland::Client::PlasmaShell *plasmaShell, QWindow *parent) : QQuickView(parent) , m_displayManager(dm) , m_waylandPlasmaShell(plasmaShell) { setClearBeforeRendering(true); setColor(QColor(Qt::transparent)); setFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint); setResizeMode(QQuickView::SizeRootObjectToView); QPoint globalPosition(QCursor::pos()); foreach (QScreen *s, QGuiApplication::screens()) { if (s->geometry().contains(globalPosition)) { setScreen(s); break; } } // Qt doesn't set this on unmanaged windows //FIXME: or does it? if (KWindowSystem::isPlatformX11()) { XChangeProperty( QX11Info::display(), winId(), XInternAtom( QX11Info::display(), "WM_WINDOW_ROLE", False ), XA_STRING, 8, PropModeReplace, (unsigned char *)"logoutdialog", strlen( "logoutdialog" )); XClassHint classHint; classHint.res_name = const_cast("ksmserver"); classHint.res_class = const_cast("ksmserver"); XSetClassHint(QX11Info::display(), winId(), &classHint); } KDeclarative::KDeclarative kdeclarative; kdeclarative.setDeclarativeEngine(engine()); kdeclarative.initialize(); kdeclarative.setupBindings(); } void KSMSwitchUserDialog::init() { rootContext()->setContextProperty(QStringLiteral("screenGeometry"), screen()->geometry()); KPackage::Package package = KPackage::PackageLoader::self()->loadPackage("Plasma/LookAndFeel"); KConfigGroup cg(KSharedConfig::openConfig("kdeglobals"), "KDE"); const QString packageName = cg.readEntry("LookAndFeelPackage", QString()); if (!packageName.isEmpty()) { package.setPath(packageName); } const QString fileName = package.filePath("userswitchermainscript"); if (QFile::exists(fileName)) { setSource(QUrl::fromLocalFile(fileName)); } else { qCWarning(KSMSERVER) << "Couldn't find a theme for the Switch User dialog" << fileName; return; } if (!errors().isEmpty()) { qCWarning(KSMSERVER) << errors(); } connect(rootObject(), SIGNAL(dismissed()), this, SIGNAL(dismissed())); connect(rootObject(), SIGNAL(ungrab()), this, SLOT(ungrab())); connect(screen(), &QScreen::geometryChanged, this, [this] { setGeometry(screen()->geometry()); }); QQuickView::show(); requestActivate(); KWindowSystem::setState(winId(), NET::SkipTaskbar|NET::SkipPager); // in case you change this make sure to adjust ungrab() also setKeyboardGrabEnabled(true); } bool KSMSwitchUserDialog::event(QEvent *e) { if (e->type() == QEvent::PlatformSurface) { switch (static_cast(e)->surfaceEventType()) { case QPlatformSurfaceEvent::SurfaceCreated: setupWaylandIntegration(); KWindowEffects::enableBlurBehind(winId(), true); break; case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed: delete m_shellSurface; m_shellSurface = nullptr; break; } } return QQuickView::event(e); } void KSMSwitchUserDialog::setupWaylandIntegration() { if (m_shellSurface) { // already setup return; } using namespace KWayland::Client; if (!m_waylandPlasmaShell) { return; } Surface *s = Surface::fromWindow(this); if (!s) { return; } m_shellSurface = m_waylandPlasmaShell->createSurface(s, this); // TODO: set a proper window type to indicate to KWin that this is the logout dialog // maybe we need a dedicated type for it? m_shellSurface->setPosition(geometry().topLeft()); } void KSMSwitchUserDialog::ungrab() { setKeyboardGrabEnabled(false); }