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
4a1888fd
Commit
4a1888fd
authored
Feb 27, 2015
by
Martin Flöser
Browse files
Add support for setting cursor on the Pointer
Methods on client side added and proper handling on server side.
parent
ff33fcdb
Changes
3
Hide whitespace changes
Inline
Side-by-side
src/wayland/autotests/client/test_wayland_seat.cpp
View file @
4a1888fd
...
...
@@ -60,6 +60,7 @@ private Q_SLOTS:
void
testPointer
();
void
testPointerButton_data
();
void
testPointerButton
();
void
testCursor
();
void
testKeyboard
();
void
testCast
();
void
testDestroy
();
...
...
@@ -73,6 +74,7 @@ private:
KWayland
::
Client
::
ConnectionThread
*
m_connection
;
KWayland
::
Client
::
Compositor
*
m_compositor
;
KWayland
::
Client
::
Seat
*
m_seat
;
KWayland
::
Client
::
ShmPool
*
m_shm
;
KWayland
::
Client
::
EventQueue
*
m_queue
;
QThread
*
m_thread
;
};
...
...
@@ -87,6 +89,7 @@ TestWaylandSeat::TestWaylandSeat(QObject *parent)
,
m_connection
(
nullptr
)
,
m_compositor
(
nullptr
)
,
m_seat
(
nullptr
)
,
m_shm
(
nullptr
)
,
m_queue
(
nullptr
)
,
m_thread
(
nullptr
)
{
...
...
@@ -100,6 +103,7 @@ void TestWaylandSeat::init()
m_display
->
setSocketName
(
s_socketName
);
m_display
->
start
();
QVERIFY
(
m_display
->
isRunning
());
m_display
->
createShm
();
m_compositorInterface
=
m_display
->
createCompositor
(
m_display
);
QVERIFY
(
m_compositorInterface
);
...
...
@@ -132,6 +136,7 @@ void TestWaylandSeat::init()
KWayland
::
Client
::
Registry
registry
;
QSignalSpy
compositorSpy
(
&
registry
,
SIGNAL
(
compositorAnnounced
(
quint32
,
quint32
)));
QSignalSpy
seatSpy
(
&
registry
,
SIGNAL
(
seatAnnounced
(
quint32
,
quint32
)));
QSignalSpy
shmSpy
(
&
registry
,
SIGNAL
(
shmAnnounced
(
quint32
,
quint32
)));
registry
.
setEventQueue
(
m_queue
);
registry
.
create
(
m_connection
->
display
());
QVERIFY
(
registry
.
isValid
());
...
...
@@ -152,10 +157,18 @@ void TestWaylandSeat::init()
m_seat
=
registry
.
createSeat
(
seatSpy
.
first
().
first
().
value
<
quint32
>
(),
seatSpy
.
first
().
last
().
value
<
quint32
>
(),
this
);
QSignalSpy
nameSpy
(
m_seat
,
SIGNAL
(
nameChanged
(
QString
)));
QVERIFY
(
nameSpy
.
wait
());
m_shm
=
new
KWayland
::
Client
::
ShmPool
(
this
);
m_shm
->
setup
(
registry
.
bindShm
(
shmSpy
.
first
().
first
().
value
<
quint32
>
(),
shmSpy
.
first
().
last
().
value
<
quint32
>
()));
QVERIFY
(
m_shm
->
isValid
());
}
void
TestWaylandSeat
::
cleanup
()
{
if
(
m_shm
)
{
delete
m_shm
;
m_shm
=
nullptr
;
}
if
(
m_seat
)
{
delete
m_seat
;
m_seat
=
nullptr
;
...
...
@@ -514,6 +527,103 @@ void TestWaylandSeat::testPointerButton()
QCOMPARE
(
buttonChangedSpy
.
last
().
at
(
3
).
value
<
KWayland
::
Client
::
Pointer
::
ButtonState
>
(),
Pointer
::
ButtonState
::
Released
);
}
void
TestWaylandSeat
::
testCursor
()
{
using
namespace
KWayland
::
Client
;
using
namespace
KWayland
::
Server
;
QSignalSpy
pointerSpy
(
m_seat
,
SIGNAL
(
hasPointerChanged
(
bool
)));
QVERIFY
(
pointerSpy
.
isValid
());
m_seatInterface
->
setHasPointer
(
true
);
QVERIFY
(
pointerSpy
.
wait
());
QSignalSpy
surfaceCreatedSpy
(
m_compositorInterface
,
SIGNAL
(
surfaceCreated
(
KWayland
::
Server
::
SurfaceInterface
*
)));
QVERIFY
(
surfaceCreatedSpy
.
isValid
());
m_compositor
->
createSurface
(
m_compositor
);
QVERIFY
(
surfaceCreatedSpy
.
wait
());
SurfaceInterface
*
serverSurface
=
surfaceCreatedSpy
.
first
().
first
().
value
<
KWayland
::
Server
::
SurfaceInterface
*>
();
QVERIFY
(
serverSurface
);
QScopedPointer
<
Pointer
>
p
(
m_seat
->
createPointer
());
QVERIFY
(
p
->
isValid
());
wl_display_flush
(
m_connection
->
display
());
QCoreApplication
::
processEvents
();
QSignalSpy
enteredSpy
(
p
.
data
(),
SIGNAL
(
entered
(
quint32
,
QPointF
)));
QVERIFY
(
enteredSpy
.
isValid
());
m_seatInterface
->
setPointerPos
(
QPoint
(
20
,
18
));
m_seatInterface
->
setFocusedPointerSurface
(
serverSurface
,
QPoint
(
10
,
15
));
quint32
serial
=
m_seatInterface
->
display
()
->
serial
();
QVERIFY
(
enteredSpy
.
wait
());
QCOMPARE
(
enteredSpy
.
first
().
first
().
value
<
quint32
>
(),
serial
);
QVERIFY
(
m_seatInterface
->
focusedPointerSurface
());
QVERIFY
(
m_seatInterface
->
focusedPointer
());
QVERIFY
(
!
m_seatInterface
->
focusedPointer
()
->
cursor
());
QSignalSpy
cursorChangedSpy
(
m_seatInterface
->
focusedPointer
(),
SIGNAL
(
cursorChanged
()));
QVERIFY
(
cursorChangedSpy
.
isValid
());
// just remove the pointer
p
->
setCursor
(
nullptr
);
QVERIFY
(
cursorChangedSpy
.
wait
());
QCOMPARE
(
cursorChangedSpy
.
count
(),
1
);
auto
cursor
=
m_seatInterface
->
focusedPointer
()
->
cursor
();
QVERIFY
(
cursor
);
QVERIFY
(
!
cursor
->
surface
());
QCOMPARE
(
cursor
->
hotspot
(),
QPoint
());
QCOMPARE
(
cursor
->
enteredSerial
(),
serial
);
QSignalSpy
hotspotChangedSpy
(
cursor
,
SIGNAL
(
hotspotChanged
()));
QVERIFY
(
hotspotChangedSpy
.
isValid
());
QSignalSpy
surfaceChangedSpy
(
cursor
,
SIGNAL
(
surfaceChanged
()));
QVERIFY
(
surfaceChangedSpy
.
isValid
());
QSignalSpy
enteredSerialChangedSpy
(
cursor
,
SIGNAL
(
enteredSerialChanged
()));
QVERIFY
(
enteredSerialChangedSpy
.
isValid
());
QSignalSpy
changedSpy
(
cursor
,
SIGNAL
(
changed
()));
QVERIFY
(
changedSpy
.
isValid
());
// test changing hotspot
p
->
setCursor
(
nullptr
,
QPoint
(
1
,
2
));
QVERIFY
(
hotspotChangedSpy
.
wait
());
QCOMPARE
(
hotspotChangedSpy
.
count
(),
1
);
QCOMPARE
(
changedSpy
.
count
(),
1
);
QCOMPARE
(
cursorChangedSpy
.
count
(),
2
);
QCOMPARE
(
cursor
->
hotspot
(),
QPoint
(
1
,
2
));
QVERIFY
(
enteredSerialChangedSpy
.
isEmpty
());
QVERIFY
(
surfaceChangedSpy
.
isEmpty
());
// set surface
auto
cursorSurface
=
m_compositor
->
createSurface
(
m_compositor
);
QVERIFY
(
cursorSurface
->
isValid
());
p
->
setCursor
(
cursorSurface
,
QPoint
(
1
,
2
));
QVERIFY
(
surfaceChangedSpy
.
wait
());
QCOMPARE
(
surfaceChangedSpy
.
count
(),
1
);
QCOMPARE
(
changedSpy
.
count
(),
2
);
QCOMPARE
(
cursorChangedSpy
.
count
(),
3
);
QVERIFY
(
enteredSerialChangedSpy
.
isEmpty
());
QCOMPARE
(
cursor
->
hotspot
(),
QPoint
(
1
,
2
));
QVERIFY
(
cursor
->
surface
());
// and add an image to the surface
QImage
img
(
QSize
(
10
,
20
),
QImage
::
Format_RGB32
);
img
.
fill
(
Qt
::
red
);
cursorSurface
->
attachBuffer
(
m_shm
->
createBuffer
(
img
));
cursorSurface
->
damage
(
QRect
(
0
,
0
,
10
,
20
));
cursorSurface
->
commit
(
Surface
::
CommitFlag
::
None
);
QVERIFY
(
changedSpy
.
wait
());
QCOMPARE
(
changedSpy
.
count
(),
3
);
QCOMPARE
(
cursorChangedSpy
.
count
(),
4
);
QCOMPARE
(
surfaceChangedSpy
.
count
(),
1
);
QCOMPARE
(
cursor
->
surface
()
->
buffer
()
->
data
(),
img
);
p
->
hideCursor
();
QVERIFY
(
surfaceChangedSpy
.
wait
());
QCOMPARE
(
changedSpy
.
count
(),
4
);
QCOMPARE
(
cursorChangedSpy
.
count
(),
5
);
QCOMPARE
(
surfaceChangedSpy
.
count
(),
2
);
QVERIFY
(
!
cursor
->
surface
());
}
void
TestWaylandSeat
::
testKeyboard
()
{
using
namespace
KWayland
::
Client
;
...
...
@@ -685,6 +795,7 @@ void TestWaylandSeat::testDestroy()
delete
m_compositor
;
m_compositor
=
nullptr
;
connect
(
m_connection
,
&
ConnectionThread
::
connectionDied
,
m_seat
,
&
Seat
::
destroy
);
connect
(
m_connection
,
&
ConnectionThread
::
connectionDied
,
m_shm
,
&
ShmPool
::
destroy
);
connect
(
m_connection
,
&
ConnectionThread
::
connectionDied
,
m_queue
,
&
EventQueue
::
destroy
);
QVERIFY
(
m_seat
->
isValid
());
...
...
src/wayland/pointer_interface.cpp
View file @
4a1888fd
...
...
@@ -39,8 +39,13 @@ public:
SeatInterface
*
seat
;
SurfaceInterface
*
focusedSurface
=
nullptr
;
QMetaObject
::
Connection
destroyConnection
;
Cursor
*
cursor
=
nullptr
;
private:
PointerInterface
*
q_func
()
{
return
reinterpret_cast
<
PointerInterface
*>
(
q
);
}
void
setCursor
(
quint32
serial
,
SurfaceInterface
*
surface
,
const
QPoint
&
hotspot
);
// interface
static
void
setCursorCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
serial
,
wl_resource
*
surface
,
int32_t
hotspot_x
,
int32_t
hotspot_y
);
...
...
@@ -50,12 +55,41 @@ private:
static
const
struct
wl_pointer_interface
s_interface
;
};
class
Cursor
::
Private
{
public:
Private
(
Cursor
*
q
,
PointerInterface
*
pointer
);
PointerInterface
*
pointer
;
quint32
enteredSerial
=
0
;
QPoint
hotspot
;
QPointer
<
SurfaceInterface
>
surface
;
void
update
(
const
QPointer
<
SurfaceInterface
>
&
surface
,
quint32
serial
,
const
QPoint
&
hotspot
);
private:
Cursor
*
q
;
};
PointerInterface
::
Private
::
Private
(
SeatInterface
*
parent
,
wl_resource
*
parentResource
,
PointerInterface
*
q
)
:
Resource
::
Private
(
q
,
parent
,
parentResource
,
&
wl_pointer_interface
,
&
s_interface
)
,
seat
(
parent
)
{
}
void
PointerInterface
::
Private
::
setCursor
(
quint32
serial
,
SurfaceInterface
*
surface
,
const
QPoint
&
hotspot
)
{
if
(
!
cursor
)
{
Q_Q
(
PointerInterface
);
cursor
=
new
Cursor
(
q
);
cursor
->
d
->
enteredSerial
=
serial
;
cursor
->
d
->
hotspot
=
hotspot
;
cursor
->
d
->
surface
=
QPointer
<
SurfaceInterface
>
(
surface
);
QObject
::
connect
(
cursor
,
&
Cursor
::
changed
,
q
,
&
PointerInterface
::
cursorChanged
);
emit
q
->
cursorChanged
();
}
else
{
cursor
->
d
->
update
(
QPointer
<
SurfaceInterface
>
(
surface
),
serial
,
hotspot
);
}
}
const
struct
wl_pointer_interface
PointerInterface
::
Private
::
s_interface
=
{
setCursorCallback
,
...
...
@@ -129,13 +163,9 @@ void PointerInterface::axis(Qt::Orientation orientation, quint32 delta)
void
PointerInterface
::
Private
::
setCursorCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
serial
,
wl_resource
*
surface
,
int32_t
hotspot_x
,
int32_t
hotspot_y
)
{
Q_UNUSED
(
client
)
Q_UNUSED
(
resource
)
Q_UNUSED
(
serial
)
Q_UNUSED
(
surface
)
Q_UNUSED
(
hotspot_x
)
Q_UNUSED
(
hotspot_y
)
// TODO: implement
auto
p
=
cast
<
Private
>
(
resource
);
Q_ASSERT
(
p
->
client
->
client
()
==
client
);
p
->
setCursor
(
serial
,
SurfaceInterface
::
get
(
surface
),
QPoint
(
hotspot_x
,
hotspot_y
));
}
void
PointerInterface
::
Private
::
releaseCallback
(
wl_client
*
client
,
wl_resource
*
resource
)
...
...
@@ -144,10 +174,79 @@ void PointerInterface::Private::releaseCallback(wl_client *client, wl_resource *
unbind
(
resource
);
}
Cursor
*
PointerInterface
::
cursor
()
const
{
Q_D
();
return
d
->
cursor
;
}
PointerInterface
::
Private
*
PointerInterface
::
d_func
()
const
{
return
reinterpret_cast
<
Private
*>
(
d
.
data
());
}
Cursor
::
Private
::
Private
(
Cursor
*
q
,
PointerInterface
*
pointer
)
:
pointer
(
pointer
)
,
q
(
q
)
{
}
void
Cursor
::
Private
::
update
(
const
QPointer
<
SurfaceInterface
>
&
s
,
quint32
serial
,
const
QPoint
&
p
)
{
bool
emitChanged
=
false
;
if
(
enteredSerial
!=
serial
)
{
enteredSerial
=
serial
;
emitChanged
=
true
;
emit
q
->
enteredSerialChanged
();
}
if
(
hotspot
!=
p
)
{
hotspot
=
p
;
emitChanged
=
true
;
emit
q
->
hotspotChanged
();
}
if
(
surface
!=
s
)
{
if
(
!
surface
.
isNull
())
{
QObject
::
disconnect
(
surface
.
data
(),
&
SurfaceInterface
::
damaged
,
q
,
&
Cursor
::
changed
);
}
surface
=
s
;
if
(
!
surface
.
isNull
())
{
QObject
::
connect
(
surface
.
data
(),
&
SurfaceInterface
::
damaged
,
q
,
&
Cursor
::
changed
);
}
emitChanged
=
true
;
emit
q
->
surfaceChanged
();
}
if
(
emitChanged
)
{
emit
q
->
changed
();
}
}
Cursor
::
Cursor
(
PointerInterface
*
parent
)
:
QObject
(
parent
)
,
d
(
new
Private
(
this
,
parent
))
{
}
Cursor
::~
Cursor
()
=
default
;
quint32
Cursor
::
enteredSerial
()
const
{
return
d
->
enteredSerial
;
}
QPoint
Cursor
::
hotspot
()
const
{
return
d
->
hotspot
;
}
PointerInterface
*
Cursor
::
pointer
()
const
{
return
d
->
pointer
;
}
QPointer
<
SurfaceInterface
>
Cursor
::
surface
()
const
{
return
d
->
surface
;
}
}
}
src/wayland/pointer_interface.h
View file @
4a1888fd
...
...
@@ -29,6 +29,7 @@ namespace KWayland
namespace
Server
{
class
Cursor
;
class
SeatInterface
;
class
SurfaceInterface
;
...
...
@@ -39,6 +40,18 @@ public:
virtual
~
PointerInterface
();
SurfaceInterface
*
focusedSurface
()
const
;
/**
* The Cursor set on this PointerInterface. Might be @c null.
* @since 5.3
**/
Cursor
*
cursor
()
const
;
Q_SIGNALS:
/**
* Signal emitted whenever the Cursor changes.
**/
void
cursorChanged
();
private:
void
setFocusedSurface
(
SurfaceInterface
*
surface
,
quint32
serial
);
void
buttonPressed
(
quint32
button
,
quint32
serial
);
...
...
@@ -50,6 +63,46 @@ private:
Private
*
d_func
()
const
;
};
/**
* @brief Class encapsulating a Cursor image.
*
* @since 5.3
**/
class
KWAYLANDSERVER_EXPORT
Cursor
:
public
QObject
{
Q_OBJECT
public:
virtual
~
Cursor
();
/**
* The hotspot of the cursor image in surface-relative coordinates.
**/
QPoint
hotspot
()
const
;
/**
* The entered serial when the Cursor got set.
**/
quint32
enteredSerial
()
const
;
/**
* The PointerInterface this Cursor belongs to.
**/
PointerInterface
*
pointer
()
const
;
/**
* The SurfaceInterface for the image content of the Cursor.
**/
QPointer
<
SurfaceInterface
>
surface
()
const
;
Q_SIGNALS:
void
hotspotChanged
();
void
enteredSerialChanged
();
void
surfaceChanged
();
void
changed
();
private:
friend
class
PointerInterface
;
Cursor
(
PointerInterface
*
parent
);
class
Private
;
const
QScopedPointer
<
Private
>
d
;
};
}
}
...
...
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