[kstyle] Implement window moving on Wayland

Summary:
So far breeze hard disabled the window moving on Wayland. With this
change the required functionality gets added.

For that Breeze 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 Breeze needs to
interact with Wayland directly.

When the move is triggered Breeze gets the ShellSurface for the window
and triggers the move on the own Seat object with the tracked serial.

Test Plan: Tested with KWin and Weston, move triggered in both.

Reviewers: #plasma_on_wayland

Subscribers: plasma-devel

Tags: #plasma_on_wayland

Differential Revision: https://phabricator.kde.org/D3019
wilder-pre-rebase
Martin Gräßlin 10 years ago
parent 8fa6313f46
commit 85f0e93ee8
  1. 176
      kstyle/breezewindowmanager.cpp
  2. 32
      kstyle/breezewindowmanager.h

@ -93,6 +93,14 @@
#endif #endif
#if BREEZE_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 Breeze namespace Breeze
{ {
@ -203,6 +211,11 @@ namespace Breeze
_dragInProgress( false ), _dragInProgress( false ),
_locked( false ), _locked( false ),
_cursorOverride( false ) _cursorOverride( false )
#if BREEZE_HAVE_KWAYLAND
, _seat( Q_NULLPTR )
, _pointer( Q_NULLPTR )
, _waylandSerial( 0 )
#endif
{ {
// install application wise event filter // install application wise event filter
@ -224,7 +237,62 @@ namespace Breeze
initializeWhiteList(); initializeWhiteList();
initializeBlackList(); initializeBlackList();
initializeWayland();
}
//_______________________________________________________
void WindowManager::initializeWayland()
{
#if BREEZE_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 BREEZE_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
} }
//_____________________________________________________________ //_____________________________________________________________
@ -570,12 +638,6 @@ namespace Breeze
bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position ) bool WindowManager::canDrag( QWidget* widget, QWidget* child, const QPoint& position )
{ {
// 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;
// retrieve child at given position and check cursor again // retrieve child at given position and check cursor again
if( child && child->cursor().shape() != Qt::ArrowCursor ) return false; if( child && child->cursor().shape() != Qt::ArrowCursor ) return false;
@ -746,58 +808,94 @@ namespace Breeze
if( useWMMoveResize() ) if( useWMMoveResize() )
{ {
#if BREEZE_HAVE_X11 if( Helper::isX11() ) {
// connection startDragX11( widget, position );
xcb_connection_t* connection( Helper::connection() ); } else if( Helper::isWayland() ) {
startDragWayland( widget, position );
}
// window } else if( !_cursorOverride ) {
const WId window( widget->window()->winId() );
#if QT_VERSION >= 0x050300 qApp->setOverrideCursor( Qt::SizeAllCursor );
qreal dpiRatio = 1; _cursorOverride = true;
QWindow* windowHandle = widget->window()->windowHandle();
if( windowHandle ) dpiRatio = windowHandle->devicePixelRatio();
else dpiRatio = qApp->devicePixelRatio();
dpiRatio = qApp->devicePixelRatio();
#else
const qreal dpiRatio = 1;
#endif
#if BREEZE_USE_KDE4 }
Display* net_connection = QX11Info::display();
#else
xcb_connection_t* net_connection = connection;
#endif
xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME ); _dragInProgress = true;
NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest(
window, position.x() * dpiRatio,
position.y() * dpiRatio,
NET::Move );
#else return;
Q_UNUSED( position ); }
#endif //_______________________________________________________
void WindowManager::startDragX11( QWidget* widget, const QPoint& position )
{
#if BREEZE_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
} else if( !_cursorOverride ) { #if BREEZE_USE_KDE4
Display* net_connection = QX11Info::display();
#else
xcb_connection_t* net_connection = connection;
#endif
qApp->setOverrideCursor( Qt::SizeAllCursor ); xcb_ungrab_pointer( connection, XCB_TIME_CURRENT_TIME );
_cursorOverride = true; NETRootInfo( net_connection, NET::WMMoveResize ).moveResizeRequest(
window, position.x() * dpiRatio,
position.y() * dpiRatio,
NET::Move );
} #else
_dragInProgress = true; Q_UNUSED( widget );
Q_UNUSED( position );
return; #endif
}
//_______________________________________________________
void WindowManager::startDragWayland( QWidget* widget, const QPoint& position )
{
#if BREEZE_HAVE_KWAYLAND
if( !_seat ) {
return;
}
QWindow* windowHandle = widget->window()->windowHandle();
auto shellSurface = KWayland::Client::ShellSurface::fromWindow(windowHandle);
if( !shellSurface ) {
// TODO: also check for xdg-shell in future
return;
}
shellSurface->requestMove( _seat, _waylandSerial );
#endif
} }
//____________________________________________________________ //____________________________________________________________
bool WindowManager::supportWMMoveResize( void ) const bool WindowManager::supportWMMoveResize( void ) const
{ {
#if BREEZE_HAVE_KWAYLAND
if( Helper::isWayland() ) {
return true;
}
#endif
#if BREEZE_HAVE_X11 #if BREEZE_HAVE_X11
return Helper::isX11(); return Helper::isX11();
#else #else

@ -31,6 +31,17 @@
#include <QString> #include <QString>
#include <QWidget> #include <QWidget>
#if BREEZE_HAVE_KWAYLAND
namespace KWayland
{
namespace Client
{
class Pointer;
class Seat;
}
}
#endif
namespace Breeze namespace Breeze
{ {
@ -125,6 +136,12 @@ namespace Breeze
*/ */
void initializeBlackList( void ); 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 //* returns true if widget is dragable
@ -149,6 +166,12 @@ namespace Breeze
//* start drag //* start drag
void startDrag( QWidget*, const QPoint& ); 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 //* returns true if window manager is used for moving
/** right now this is true only for X11 */ /** right now this is true only for X11 */
bool supportWMMoveResize( void ) const; bool supportWMMoveResize( void ) const;
@ -256,6 +279,15 @@ namespace Breeze
//* application event filter //* application event filter
QObject* _appEventFilter; QObject* _appEventFilter;
#if BREEZE_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 //* allow access of all private members to the app event filter
friend class AppEventFilter; friend class AppEventFilter;

Loading…
Cancel
Save