diff --git a/kstyle/oxygenwindowmanager.h b/kstyle/oxygenwindowmanager.h --- a/kstyle/oxygenwindowmanager.h +++ b/kstyle/oxygenwindowmanager.h @@ -31,6 +31,17 @@ #include #include +#if OXYGEN_HAVE_KWAYLAND +namespace KWayland +{ +namespace Client +{ + class Pointer; + class Seat; +} +} +#endif + namespace Oxygen { @@ -125,6 +136,12 @@ */ void initializeBlackList( void ); + //* initializes the Wayland specific parts + void initializeWayland(); + + //* The Wayland Seat's hasPointer property changed + void waylandHasPointerChanged( bool hasPointer ); + //@} //* returns true if widget is dragable @@ -149,6 +166,12 @@ //* start drag void startDrag( QWidget*, const QPoint& ); + //* X11 specific implementation for startDrag + void startDragX11( QWidget*, const QPoint& ); + + //* Wayland specific implementation for startDrag + void startDragWayland( QWidget*, const QPoint& ); + //* returns true if window manager is used for moving /** right now this is true only for X11 */ bool supportWMMoveResize( void ) const; @@ -256,6 +279,15 @@ //* application event filter QObject* _appEventFilter; + #if OXYGEN_HAVE_KWAYLAND + //* The Wayland seat object which needs to be passed to move requests. + KWayland::Client::Seat* _seat; + //* The Wayland pointer object where we get pointer events on. + KWayland::Client::Pointer* _pointer; + //* latest searial which needs to be passed to the move requests. + quint32 _waylandSerial; + #endif + //* allow access of all private members to the app event filter friend class AppEventFilter; diff --git a/kstyle/oxygenwindowmanager.cpp b/kstyle/oxygenwindowmanager.cpp --- a/kstyle/oxygenwindowmanager.cpp +++ b/kstyle/oxygenwindowmanager.cpp @@ -93,6 +93,14 @@ #endif +#if OXYGEN_HAVE_KWAYLAND +#include +#include +#include +#include +#include +#endif + namespace Oxygen { @@ -203,6 +211,11 @@ _dragInProgress( false ), _locked( false ), _cursorOverride( false ) + #if OXYGEN_HAVE_KWAYLAND + , _seat( Q_NULLPTR ) + , _pointer( Q_NULLPTR ) + , _waylandSerial( 0 ) + #endif { // install application wise event filter @@ -224,7 +237,62 @@ initializeWhiteList(); initializeBlackList(); + initializeWayland(); + + } + + //_______________________________________________________ + void WindowManager::initializeWayland() + { + #if OXYGEN_HAVE_KWAYLAND + if( !Helper::isWayland() ) return; + + if( _seat ) { + // already initialized + return; + } + + using namespace KWayland::Client; + auto connection = ConnectionThread::fromApplication( this ); + if( !connection ) { + return; + } + Registry *registry = new Registry( this ); + registry->create( connection ); + connect(registry, &Registry::interfacesAnnounced, this, + [registry, this] { + const auto interface = registry->interface( Registry::Interface::Seat ); + if( interface.name != 0 ) { + _seat = registry->createSeat( interface.name, interface.version, this ); + connect(_seat, &Seat::hasPointerChanged, this, &WindowManager::waylandHasPointerChanged); + } + } + ); + + registry->setup(); + connection->roundtrip(); + #endif + } + //_______________________________________________________ + void WindowManager::waylandHasPointerChanged(bool hasPointer) + { + #if OXYGEN_HAVE_KWAYLAND + Q_ASSERT( _seat ); + if( hasPointer ) { + if( !_pointer ) { + _pointer = _seat->createPointer(this); + connect(_pointer, &KWayland::Client::Pointer::buttonStateChanged, this, + [this] (quint32 serial) { + _waylandSerial = serial; + } + ); + } + } else { + delete _pointer; + _pointer = nullptr; + } + #endif } //_____________________________________________________________ @@ -545,12 +613,6 @@ bool WindowManager::canDrag( QWidget* widget ) { - // do not start drag on Wayland, this is not yet supported - // To implement integration with KWayland is required - // and QtWayland must support getting the wl_seat. - // Other option would be adding support to Qt for starting a move - if( Helper::isWayland() ) return false; - // check if enabled if( !enabled() ) return false; @@ -745,58 +807,97 @@ // ungrab pointer if( useWMMoveResize() ) { + if( Helper::isX11() ) { + startDragX11( widget, position ); + } else if( Helper::isWayland() ) { + startDragWayland( widget, position ); + } - #if OXYGEN_HAVE_X11 - // connection - xcb_connection_t* connection( Helper::connection() ); + } else if( !_cursorOverride ) { - // window - const WId window( widget->window()->winId() ); + qApp->setOverrideCursor( Qt::SizeAllCursor ); + _cursorOverride = true; - #if QT_VERSION >= 0x050300 - qreal dpiRatio = 1; - QWindow* windowHandle = widget->window()->windowHandle(); - if( windowHandle ) dpiRatio = windowHandle->devicePixelRatio(); - else dpiRatio = qApp->devicePixelRatio(); - dpiRatio = qApp->devicePixelRatio(); - #else - const qreal dpiRatio = 1; - #endif + } - #if OXYGEN_USE_KDE4 - Display* net_connection = QX11Info::display(); - #else - xcb_connection_t* net_connection = connection; - #endif + _dragInProgress = true; - xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); - NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest( - window, position.x() * dpiRatio, - position.y() * dpiRatio, - NET::Move ); + return; - #else + } - Q_UNUSED( position ); + //_______________________________________________________ + void WindowManager::startDragX11( QWidget* widget, const QPoint& position ) + { + #if OXYGEN_HAVE_X11 + // connection + xcb_connection_t* connection( Helper::connection() ); + + // window + const WId window( widget->window()->winId() ); + + #if QT_VERSION >= 0x050300 + qreal dpiRatio = 1; + QWindow* windowHandle = widget->window()->windowHandle(); + if( windowHandle ) dpiRatio = windowHandle->devicePixelRatio(); + else dpiRatio = qApp->devicePixelRatio(); + dpiRatio = qApp->devicePixelRatio(); + #else + const qreal dpiRatio = 1; + #endif - #endif + #if OXYGEN_USE_KDE4 + Display* net_connection = QX11Info::display(); + #else + xcb_connection_t* net_connection = connection; + #endif - } else if( !_cursorOverride ) { + xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); + NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest( + window, position.x() * dpiRatio, + position.y() * dpiRatio, + NET::Move ); - qApp->setOverrideCursor( Qt::SizeAllCursor ); - _cursorOverride = true; + #else + + Q_UNUSED( widget ); + Q_UNUSED( position ); + + #endif + } + //_______________________________________________________ + void WindowManager::startDragWayland( QWidget* widget, const QPoint& position ) + { + #if OXYGEN_HAVE_KWAYLAND + if( !_seat ) { + return; } - _dragInProgress = true; + QWindow* windowHandle = widget->window()->windowHandle(); + auto shellSurface = KWayland::Client::ShellSurface::fromWindow(windowHandle); + if( !shellSurface ) { + // TODO: also check for xdg-shell in future + return; + } - return; + shellSurface->requestMove( _seat, _waylandSerial ); + #else + Q_UNUSED( widget ); + Q_UNUSED( position ); + + #endif } //____________________________________________________________ bool WindowManager::supportWMMoveResize( void ) const { + #if OXYGEN_HAVE_KWAYLAND + if( Helper::isWayland() ) { + return true; + } + #endif #if OXYGEN_HAVE_X11 return Helper::isX11();