Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
KWin
Commits
2aeaf933
Commit
2aeaf933
authored
Aug 05, 2021
by
David Redondo
🏎
Browse files
Implement pointer hold gestures interface
parent
e63783df
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/wayland/autotests/client/CMakeLists.txt
View file @
2aeaf933
...
...
@@ -27,6 +27,10 @@ if (HAVE_LINUX_INPUT_H)
set
(
testWaylandSeat_SRCS
test_wayland_seat.cpp
)
ecm_add_qtwayland_client_protocol
(
testWaylandSeat_SRCS
PROTOCOL
${
WaylandProtocols_DATADIR
}
/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml
BASENAME pointer-gestures-unstable-v1
)
add_executable
(
testWaylandSeat
${
testWaylandSeat_SRCS
}
)
target_link_libraries
(
testWaylandSeat Qt::Test Qt::Gui KF5::WaylandClient Plasma::KWaylandServer Wayland::Client Wayland::Server
)
add_test
(
NAME kwayland-testWaylandSeat COMMAND testWaylandSeat
)
...
...
src/wayland/autotests/client/test_wayland_seat.cpp
View file @
2aeaf933
...
...
@@ -36,6 +36,7 @@
#include
"KWayland/Client/surface.h"
#include
"KWayland/Client/touch.h"
// Wayland
#include
"qwayland-pointer-gestures-unstable-v1.h"
#include
<wayland-client-protocol.h>
#include
<linux/input.h>
...
...
@@ -65,6 +66,8 @@ private Q_SLOTS:
void
testPointerSwipeGesture
();
void
testPointerPinchGesture_data
();
void
testPointerPinchGesture
();
void
testPointerHoldGesture_data
();
void
testPointerHoldGesture
();
void
testPointerAxis
();
void
testCursor
();
void
testCursorDamage
();
...
...
@@ -1081,6 +1084,132 @@ void TestWaylandSeat::testPointerPinchGesture()
QVERIFY
(
spy
->
wait
());
}
void
TestWaylandSeat
::
testPointerHoldGesture_data
()
{
QTest
::
addColumn
<
bool
>
(
"cancel"
);
QTest
::
addColumn
<
int
>
(
"expectedEndCount"
);
QTest
::
addColumn
<
int
>
(
"expectedCancelCount"
);
QTest
::
newRow
(
"end"
)
<<
false
<<
1
<<
0
;
QTest
::
newRow
(
"cancel"
)
<<
true
<<
0
<<
1
;
}
class
PointerHoldGesture
:
public
QObject
,
public
QtWayland
::
zwp_pointer_gesture_hold_v1
{
using
zwp_pointer_gesture_hold_v1
::
zwp_pointer_gesture_hold_v1
;
Q_OBJECT
void
zwp_pointer_gesture_hold_v1_begin
(
uint32_t
serial
,
uint32_t
time
,
wl_surface
*
surface
,
uint32_t
fingers
)
override
{
Q_EMIT
started
(
serial
,
time
,
surface
,
fingers
);
}
void
zwp_pointer_gesture_hold_v1_end
(
uint32_t
serial
,
uint32_t
time
,
int32_t
cancelled
)
override
{
cancelled
?
Q_EMIT
this
->
cancelled
(
serial
,
time
)
:
Q_EMIT
ended
(
serial
,
time
);
}
Q_SIGNALS:
void
started
(
quint32
serial
,
quint32
time
,
void
*
surface
,
quint32
fingers
);
void
ended
(
quint32
serial
,
quint32
time
);
void
cancelled
(
quint32
serial
,
quint32
time
);
};
void
TestWaylandSeat
::
testPointerHoldGesture
()
{
using
namespace
KWayland
::
Client
;
using
namespace
KWaylandServer
;
// first create the pointer and pointer swipe gesture
QSignalSpy
hasPointerChangedSpy
(
m_seat
,
&
Seat
::
hasPointerChanged
);
QVERIFY
(
hasPointerChangedSpy
.
isValid
());
m_seatInterface
->
setHasPointer
(
true
);
QVERIFY
(
hasPointerChangedSpy
.
wait
());
QScopedPointer
<
Pointer
>
pointer
(
m_seat
->
createPointer
());
Registry
registry
;
QSignalSpy
gesturesAnnoucedSpy
(
&
registry
,
&
Registry
::
pointerGesturesUnstableV1Announced
);
QVERIFY
(
gesturesAnnoucedSpy
.
isValid
());
registry
.
create
(
m_connection
);
registry
.
setup
();
QVERIFY
(
gesturesAnnoucedSpy
.
wait
());
QtWayland
::
zwp_pointer_gestures_v1
gestures
(
registry
,
gesturesAnnoucedSpy
.
first
().
at
(
0
).
value
<
int
>
(),
gesturesAnnoucedSpy
.
first
().
at
(
1
).
value
<
int
>
());
PointerHoldGesture
gesture
(
gestures
.
get_hold_gesture
(
*
pointer
));
QVERIFY
(
gesture
.
isInitialized
());
QSignalSpy
startSpy
(
&
gesture
,
&
PointerHoldGesture
::
started
);
QVERIFY
(
startSpy
.
isValid
());
QSignalSpy
endSpy
(
&
gesture
,
&
PointerHoldGesture
::
ended
);
QVERIFY
(
endSpy
.
isValid
());
QSignalSpy
cancelledSpy
(
&
gesture
,
&
PointerHoldGesture
::
cancelled
);
QVERIFY
(
cancelledSpy
.
isValid
());
// now create a surface
QSignalSpy
surfaceCreatedSpy
(
m_compositorInterface
,
&
CompositorInterface
::
surfaceCreated
);
QVERIFY
(
surfaceCreatedSpy
.
isValid
());
QScopedPointer
<
Surface
>
surface
(
m_compositor
->
createSurface
());
QVERIFY
(
surfaceCreatedSpy
.
wait
());
auto
serverSurface
=
surfaceCreatedSpy
.
first
().
first
().
value
<
SurfaceInterface
*>
();
QVERIFY
(
serverSurface
);
QImage
image
(
QSize
(
100
,
100
),
QImage
::
Format_ARGB32_Premultiplied
);
image
.
fill
(
Qt
::
black
);
surface
->
attachBuffer
(
m_shm
->
createBuffer
(
image
));
surface
->
damage
(
image
.
rect
());
surface
->
commit
(
Surface
::
CommitFlag
::
None
);
QSignalSpy
committedSpy
(
serverSurface
,
&
KWaylandServer
::
SurfaceInterface
::
committed
);
QVERIFY
(
committedSpy
.
wait
());
m_seatInterface
->
setFocusedPointerSurface
(
serverSurface
);
QCOMPARE
(
m_seatInterface
->
focusedPointerSurface
(),
serverSurface
);
QVERIFY
(
m_seatInterface
->
pointer
());
// send in the start
quint32
timestamp
=
1
;
m_seatInterface
->
setTimestamp
(
timestamp
++
);
m_seatInterface
->
startPointerHoldGesture
(
3
);
QVERIFY
(
startSpy
.
wait
());
QCOMPARE
(
startSpy
.
count
(),
1
);
QCOMPARE
(
startSpy
.
first
().
at
(
0
).
value
<
quint32
>
(),
m_display
->
serial
());
QCOMPARE
(
startSpy
.
first
().
at
(
1
).
value
<
quint32
>
(),
1u
);
QCOMPARE
(
startSpy
.
first
().
at
(
2
).
value
<
void
*>
(),
*
surface
.
get
());
QCOMPARE
(
startSpy
.
first
().
at
(
3
).
value
<
quint32
>
(),
3
);
// another start should not be possible
m_seatInterface
->
startPointerPinchGesture
(
3
);
QVERIFY
(
!
startSpy
.
wait
(
500
));
// now end or cancel
QFETCH
(
bool
,
cancel
);
QSignalSpy
*
spy
;
m_seatInterface
->
setTimestamp
(
timestamp
++
);
if
(
cancel
)
{
m_seatInterface
->
cancelPointerHoldGesture
();
spy
=
&
cancelledSpy
;
}
else
{
m_seatInterface
->
endPointerHoldGesture
();
spy
=
&
endSpy
;
}
QVERIFY
(
spy
->
wait
());
QTEST
(
endSpy
.
count
(),
"expectedEndCount"
);
QTEST
(
cancelledSpy
.
count
(),
"expectedCancelCount"
);
QCOMPARE
(
spy
->
count
(),
1
);
QCOMPARE
(
spy
->
first
().
at
(
0
).
value
<
quint32
>
(),
m_display
->
serial
());
QCOMPARE
(
spy
->
first
().
at
(
1
).
value
<
quint32
>
(),
2
);
// now a start should be possible again
m_seatInterface
->
setTimestamp
(
timestamp
++
);
m_seatInterface
->
startPointerHoldGesture
(
3
);
QVERIFY
(
startSpy
.
wait
());
// and end
m_seatInterface
->
setTimestamp
(
timestamp
++
);
if
(
cancel
)
{
m_seatInterface
->
cancelPointerHoldGesture
();
}
else
{
m_seatInterface
->
endPointerHoldGesture
();
}
QVERIFY
(
spy
->
wait
());
}
void
TestWaylandSeat
::
testPointerAxis
()
{
using
namespace
KWayland
::
Client
;
...
...
src/wayland/pointer_interface.cpp
View file @
2aeaf933
...
...
@@ -45,6 +45,7 @@ PointerInterfacePrivate::PointerInterfacePrivate(PointerInterface *q, SeatInterf
,
relativePointersV1
(
new
RelativePointerV1Interface
(
q
))
,
swipeGesturesV1
(
new
PointerSwipeGestureV1Interface
(
q
))
,
pinchGesturesV1
(
new
PointerPinchGestureV1Interface
(
q
))
,
holdGesturesV1
(
new
PointerHoldGestureV1Interface
(
q
))
{
}
...
...
src/wayland/pointer_interface_p.h
View file @
2aeaf933
...
...
@@ -20,6 +20,7 @@ namespace KWaylandServer
class
ClientConnection
;
class
PointerPinchGestureV1Interface
;
class
PointerSwipeGestureV1Interface
;
class
PointerHoldGestureV1Interface
;
class
RelativePointerV1Interface
;
class
PointerInterfacePrivate
:
public
QtWaylandServer
::
wl_pointer
...
...
@@ -40,6 +41,7 @@ public:
QScopedPointer
<
RelativePointerV1Interface
>
relativePointersV1
;
QScopedPointer
<
PointerSwipeGestureV1Interface
>
swipeGesturesV1
;
QScopedPointer
<
PointerPinchGestureV1Interface
>
pinchGesturesV1
;
QScopedPointer
<
PointerHoldGestureV1Interface
>
holdGesturesV1
;
QPointF
lastPosition
;
void
sendLeave
(
quint32
serial
);
...
...
src/wayland/pointergestures_v1_interface.cpp
View file @
2aeaf933
...
...
@@ -15,7 +15,7 @@
namespace
KWaylandServer
{
static
const
int
s_version
=
2
;
static
const
int
s_version
=
3
;
PointerGesturesV1InterfacePrivate
::
PointerGesturesV1InterfacePrivate
(
Display
*
display
)
:
QtWaylandServer
::
zwp_pointer_gestures_v1
(
*
display
,
s_version
)
...
...
@@ -46,6 +46,19 @@ void PointerGesturesV1InterfacePrivate::zwp_pointer_gestures_v1_get_pinch_gestur
pinchGesture
->
add
(
resource
->
client
(),
id
,
resource
->
version
());
}
void
PointerGesturesV1InterfacePrivate
::
zwp_pointer_gestures_v1_get_hold_gesture
(
Resource
*
resource
,
uint32_t
id
,
struct
::
wl_resource
*
pointer_resource
)
{
PointerInterface
*
pointer
=
PointerInterface
::
get
(
pointer_resource
);
if
(
!
pointer
)
{
wl_resource_post_error
(
resource
->
handle
,
WL_DISPLAY_ERROR_INVALID_OBJECT
,
"invalid pointer"
);
return
;
}
PointerHoldGestureV1Interface
*
holdGesture
=
PointerHoldGestureV1Interface
::
get
(
pointer
);
holdGesture
->
add
(
resource
->
client
(),
id
,
resource
->
version
());
}
void
PointerGesturesV1InterfacePrivate
::
zwp_pointer_gestures_v1_release
(
Resource
*
resource
)
{
wl_resource_destroy
(
resource
->
handle
);
...
...
@@ -254,4 +267,82 @@ void PointerPinchGestureV1Interface::sendCancel(quint32 serial)
focusedClient
=
nullptr
;
}
PointerHoldGestureV1Interface
::
PointerHoldGestureV1Interface
(
PointerInterface
*
pointer
)
:
pointer
(
pointer
)
{
}
PointerHoldGestureV1Interface
*
PointerHoldGestureV1Interface
::
get
(
PointerInterface
*
pointer
)
{
if
(
pointer
)
{
PointerInterfacePrivate
*
pointerPrivate
=
PointerInterfacePrivate
::
get
(
pointer
);
return
pointerPrivate
->
holdGesturesV1
.
data
();
}
return
nullptr
;
}
void
PointerHoldGestureV1Interface
::
zwp_pointer_gesture_hold_v1_destroy
(
Resource
*
resource
)
{
wl_resource_destroy
(
resource
->
handle
);
}
void
PointerHoldGestureV1Interface
::
sendBegin
(
quint32
serial
,
quint32
fingerCount
)
{
if
(
focusedClient
)
{
return
;
// gesture is already active
}
if
(
!
pointer
->
focusedSurface
())
{
return
;
}
const
SurfaceInterface
*
focusedSurface
=
pointer
->
focusedSurface
();
focusedClient
=
focusedSurface
->
client
();
SeatInterface
*
seat
=
pointer
->
seat
();
const
QList
<
Resource
*>
holdResources
=
resourceMap
().
values
(
*
focusedClient
);
for
(
Resource
*
holdResource
:
holdResources
)
{
if
(
holdResource
->
client
()
==
focusedClient
->
client
())
{
send_begin
(
holdResource
->
handle
,
serial
,
seat
->
timestamp
(),
focusedSurface
->
resource
(),
fingerCount
);
}
}
}
void
PointerHoldGestureV1Interface
::
sendEnd
(
quint32
serial
)
{
if
(
!
focusedClient
)
{
return
;
}
SeatInterface
*
seat
=
pointer
->
seat
();
const
QList
<
Resource
*>
holdResources
=
resourceMap
().
values
(
*
focusedClient
);
for
(
Resource
*
holdResource
:
holdResources
)
{
if
(
holdResource
->
client
()
==
focusedClient
->
client
())
{
send_end
(
holdResource
->
handle
,
serial
,
seat
->
timestamp
(),
false
);
}
}
// The gesture session has been just finished, reset the cached focused client.
focusedClient
=
nullptr
;
}
void
PointerHoldGestureV1Interface
::
sendCancel
(
quint32
serial
)
{
if
(
!
focusedClient
)
{
return
;
}
SeatInterface
*
seat
=
pointer
->
seat
();
const
QList
<
Resource
*>
holdResources
=
resourceMap
().
values
(
*
focusedClient
);
for
(
Resource
*
holdResource
:
holdResources
)
{
if
(
holdResource
->
client
()
==
holdResource
->
client
())
{
send_end
(
holdResource
->
handle
,
serial
,
seat
->
timestamp
(),
true
);
}
}
// The gesture session has been just finished, reset the cached focused client.
focusedClient
=
nullptr
;
}
}
// namespace KWaylandServer
src/wayland/pointergestures_v1_interface_p.h
View file @
2aeaf933
...
...
@@ -26,6 +26,7 @@ public:
protected:
void
zwp_pointer_gestures_v1_get_swipe_gesture
(
Resource
*
resource
,
uint32_t
id
,
struct
::
wl_resource
*
pointer_resource
)
override
;
void
zwp_pointer_gestures_v1_get_pinch_gesture
(
Resource
*
resource
,
uint32_t
id
,
struct
::
wl_resource
*
pointer_resource
)
override
;
void
zwp_pointer_gestures_v1_get_hold_gesture
(
Resource
*
resource
,
uint32_t
id
,
struct
::
wl_resource
*
pointer_resource
)
override
;
void
zwp_pointer_gestures_v1_release
(
Resource
*
resource
)
override
;
};
...
...
@@ -69,4 +70,24 @@ private:
QPointer
<
ClientConnection
>
focusedClient
;
};
class
PointerHoldGestureV1Interface
:
public
QtWaylandServer
::
zwp_pointer_gesture_hold_v1
{
public:
explicit
PointerHoldGestureV1Interface
(
PointerInterface
*
pointer
);
static
PointerHoldGestureV1Interface
*
get
(
PointerInterface
*
pointer
);
void
sendBegin
(
quint32
serial
,
quint32
fingerCount
);
void
sendUpdate
(
const
QSizeF
&
delta
,
qreal
scale
,
qreal
rotation
);
void
sendEnd
(
quint32
serial
);
void
sendCancel
(
quint32
serial
);
protected:
void
zwp_pointer_gesture_hold_v1_destroy
(
Resource
*
resource
)
override
;
private:
PointerInterface
*
pointer
;
QPointer
<
ClientConnection
>
focusedClient
;
};
}
// namespace KWaylandServer
src/wayland/seat_interface.cpp
View file @
2aeaf933
...
...
@@ -854,6 +854,42 @@ void SeatInterface::cancelPointerPinchGesture()
}
}
void
SeatInterface
::
startPointerHoldGesture
(
quint32
fingerCount
)
{
if
(
!
d
->
pointer
)
{
return
;
}
auto
holdGesture
=
PointerHoldGestureV1Interface
::
get
(
pointer
());
if
(
holdGesture
)
{
holdGesture
->
sendBegin
(
d
->
display
->
nextSerial
(),
fingerCount
);
}
}
void
SeatInterface
::
endPointerHoldGesture
()
{
if
(
!
d
->
pointer
)
{
return
;
}
auto
holdGesture
=
PointerHoldGestureV1Interface
::
get
(
pointer
());
if
(
holdGesture
)
{
holdGesture
->
sendEnd
(
d
->
display
->
nextSerial
());
}
}
void
SeatInterface
::
cancelPointerHoldGesture
()
{
if
(
!
d
->
pointer
)
{
return
;
}
auto
holdGesture
=
PointerHoldGestureV1Interface
::
get
(
pointer
());
if
(
holdGesture
)
{
holdGesture
->
sendCancel
(
d
->
display
->
nextSerial
());
}
}
SurfaceInterface
*
SeatInterface
::
focusedKeyboardSurface
()
const
{
return
d
->
globalKeyboard
.
focus
.
surface
;
...
...
src/wayland/seat_interface.h
View file @
2aeaf933
...
...
@@ -422,7 +422,7 @@ public:
* The precise conditions of when such a gesture is detected are
* implementation-dependent.
*
* Only one gesture (either swipe or pinch) can be active at a given time.
* Only one gesture (either swipe or pinch
or hold
) can be active at a given time.
*
* @param fingerCount The number of fingers involved in this multi-finger touchpad gesture
*
...
...
@@ -472,7 +472,7 @@ public:
* around a logical center of gravity. The precise conditions of when
* such a gesture is detected are implementation-dependent.
*
* Only one gesture (either swipe or pinch) can be active at a given time.
* Only one gesture (either swipe or pinch
or hold
) can be active at a given time.
*
* @param fingerCount The number of fingers involved in this multi-touch touchpad gesture
*
...
...
@@ -513,6 +513,41 @@ public:
* @see endPointerPinchGesture
*/
void
cancelPointerPinchGesture
();
/**
* Starts a multi-finger hold gesture for the currently focused pointer surface.
*
* Such gestures are normally reported through dedicated input devices such as touchpads.
*
* The gesture is usually initiated by multiple fingers being held down on the touchpad.
* The precise conditions of when such a gesture is detected are
* implementation-dependent.
*
* Only one gesture (either swipe or pinch or hold) can be active at a given time.
*
* @param fingerCount The number of fingers involved in this multi-finger touchpad gesture
*
* @see PointerGesturesInterface
* @see focusedPointerSurface
* @see endPointerHoldeGesture
* @see cancelPointerHoldGesture
*/
void
startPointerHoldGesture
(
quint32
fingerCount
);
/**
* The multi-finger hold gesture ended. This may happen when one or more fingers are lifted.
* @see startPointerHoldGesture
* @see cancelPointerHoldGesture
*/
void
endPointerHoldGesture
();
/**
* The multi-finger swipe gestures ended and got cancelled by the Wayland compositor.
* @see startPointerHoldGesture
* @see endPointerHoldGesture
*/
void
cancelPointerHoldGesture
();
///@}
/**
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment