////////////////////////////////////////////////////////////////////////////// // breezedetectwidget.cpp // Note: this class is a stripped down version of // /kdebase/workspace/kwin/kcmkwin/kwinrules/detectwidget.cpp // SPDX-FileCopyrightText: 2004 Lubos Lunak // ------------------- // // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa // // SPDX-License-Identifier: MIT ////////////////////////////////////////////////////////////////////////////// #include "breezedetectwidget.h" #include "breeze.h" #include #include #include #include #if BREEZE_HAVE_X11 #include #include #endif namespace Breeze { //_________________________________________________________ DetectDialog::DetectDialog( QWidget* parent ): QDialog( parent ) { // setup m_ui.setupUi( this ); connect( m_ui.buttonBox->button( QDialogButtonBox::Cancel ), &QAbstractButton::clicked, this, &QWidget::close ); m_ui.windowClassCheckBox->setChecked( true ); #if BREEZE_HAVE_X11 if (QX11Info::isPlatformX11()) { // create atom xcb_connection_t* connection( QX11Info::connection() ); const QString atomName( QStringLiteral( "WM_STATE" ) ); xcb_intern_atom_cookie_t cookie( xcb_intern_atom( connection, false, atomName.size(), qPrintable( atomName ) ) ); QScopedPointer reply( xcb_intern_atom_reply( connection, cookie, nullptr) ); m_wmStateAtom = reply ? reply->atom : 0; } #endif } //_________________________________________________________ void DetectDialog::detect( WId window ) { if( window == 0 ) selectWindow(); else readWindow( window ); } //_________________________________________________________ void DetectDialog::readWindow( WId window ) { if( window == 0 ) { emit detectionDone( false ); return; } m_info.reset(new KWindowInfo( window, NET::WMAllProperties, NET::WM2AllProperties )); if( !m_info->valid()) { emit detectionDone( false ); return; } const QString wmClassClass( QString::fromUtf8( m_info->windowClassClass() ) ); const QString wmClassName( QString::fromUtf8( m_info->windowClassName() ) ); m_ui.windowClass->setText( QStringLiteral( "%1 (%2 %3)" ).arg( wmClassClass ).arg( wmClassName ).arg( wmClassClass ) ); m_ui.windowTitle->setText( m_info->name() ); emit detectionDone( exec() == QDialog::Accepted ); } //_________________________________________________________ void DetectDialog::selectWindow() { // use a dialog, so that all user input is blocked // use WX11BypassWM and moving away so that it's not actually visible // grab only mouse, so that keyboard can be used e.g. for switching windows m_grabber = new QDialog( nullptr, Qt::X11BypassWindowManagerHint ); m_grabber->move( -1000, -1000 ); m_grabber->setModal( true ); m_grabber->show(); // need to explicitly override cursor for Qt5 qApp->setOverrideCursor( Qt::CrossCursor ); m_grabber->grabMouse( Qt::CrossCursor ); m_grabber->installEventFilter( this ); } //_________________________________________________________ bool DetectDialog::eventFilter( QObject* o, QEvent* e ) { // check object and event type if( o != m_grabber ) return false; if( e->type() != QEvent::MouseButtonRelease ) return false; // need to explicitly release cursor for Qt5 qApp->restoreOverrideCursor(); // delete old m_grabber delete m_grabber; m_grabber = nullptr; // check button if( static_cast< QMouseEvent* >( e )->button() != Qt::LeftButton ) return true; // read window information readWindow( findWindow() ); return true; } //_________________________________________________________ WId DetectDialog::findWindow() { #if BREEZE_HAVE_X11 if (!QX11Info::isPlatformX11()) { return 0; } // check atom if( !m_wmStateAtom ) return 0; xcb_connection_t* connection( QX11Info::connection() ); xcb_window_t parent( QX11Info::appRootWindow() ); // why is there a loop of only 10 here for( int i = 0; i < 10; ++i ) { // query pointer xcb_query_pointer_cookie_t pointerCookie( xcb_query_pointer( connection, parent ) ); QScopedPointer pointerReply( xcb_query_pointer_reply( connection, pointerCookie, nullptr ) ); if( !( pointerReply && pointerReply->child ) ) return 0; const xcb_window_t child( pointerReply->child ); xcb_get_property_cookie_t cookie( xcb_get_property( connection, 0, child, m_wmStateAtom, XCB_GET_PROPERTY_TYPE_ANY, 0, 0 ) ); QScopedPointer reply( xcb_get_property_reply( connection, cookie, nullptr ) ); if( reply && reply->type ) return child; else parent = child; } #endif return 0; } }