summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Gräßlin <[email protected]>2016-10-18 10:51:50 +0200
committerMartin Gräßlin <[email protected]>2016-10-18 10:53:31 +0200
commit0a4be7bdc1dd987c2c347228dc7ae6b075f51408 (patch)
tree24d4e05b0fccf21cdb330015c35b991bba608bce
parentb6979c29d1b8fb656de9dbb8e12a84e78ec5c9a9 (diff)
[kstyle] Implement window moving on Wayland
Summary: So far oxygen hard disabled the window moving on Wayland. With this change the required functionality gets added. For that Oxygen creates an additional Seat and a Pointer on it to track all pointer button events on the window. That way the kstyle gets the latest serial which needs to be passed to the move requests. This is not available through QtWayland's native interface, thus Oxygen needs to interact with Wayland directly. When the move is triggered Oxygen gets the ShellSurface for the window and triggers the move on the own Seat object with the tracked serial. Test Plan: Tested with KWin/Wayland Reviewers: #plasma, hpereiradacosta Subscribers: plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D3096
-rw-r--r--kstyle/oxygenwindowmanager.cpp177
-rw-r--r--kstyle/oxygenwindowmanager.h32
2 files changed, 171 insertions, 38 deletions
diff --git a/kstyle/oxygenwindowmanager.cpp b/kstyle/oxygenwindowmanager.cpp
index dbe72f0..fd73f8b 100644
--- a/kstyle/oxygenwindowmanager.cpp
+++ b/kstyle/oxygenwindowmanager.cpp
@@ -93,6 +93,14 @@
#endif
+#if OXYGEN_HAVE_KWAYLAND
+#include <KWayland/Client/connection_thread.h>
+#include <KWayland/Client/pointer.h>
+#include <KWayland/Client/registry.h>
+#include <KWayland/Client/shell.h>
+#include <KWayland/Client/seat.h>
+#endif
+
namespace Oxygen
{
@@ -203,6 +211,11 @@ namespace Oxygen
_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 @@ namespace Oxygen
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 @@ namespace Oxygen
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 @@ namespace Oxygen
// 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();
diff --git a/kstyle/oxygenwindowmanager.h b/kstyle/oxygenwindowmanager.h
index c66f939..5630d1e 100644
--- a/kstyle/oxygenwindowmanager.h
+++ b/kstyle/oxygenwindowmanager.h
@@ -31,6 +31,17 @@
#include <QString>
#include <QWidget>
+#if OXYGEN_HAVE_KWAYLAND
+namespace KWayland
+{
+namespace Client
+{
+ class Pointer;
+ class Seat;
+}
+}
+#endif
+
namespace Oxygen
{
@@ -125,6 +136,12 @@ namespace Oxygen
*/
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 @@ namespace Oxygen
//* 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 @@ namespace Oxygen
//* 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;