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
0cd3cbcf
Commit
0cd3cbcf
authored
Sep 17, 2014
by
Martin Flöser
Browse files
Merge in server related commits
parents
8e54a479
37c53183
Changes
14
Hide whitespace changes
Inline
Side-by-side
src/wayland/compositor_interface.cpp
0 → 100644
View file @
0cd3cbcf
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include
"compositor_interface.h"
#include
"display.h"
#include
"surface_interface.h"
namespace
KWin
{
namespace
WaylandServer
{
static
const
quint32
s_version
=
3
;
const
struct
wl_compositor_interface
CompositorInterface
::
s_interface
=
{
CompositorInterface
::
createSurfaceCallback
,
CompositorInterface
::
createRegionCallback
};
CompositorInterface
::
CompositorInterface
(
Display
*
display
,
QObject
*
parent
)
:
QObject
(
parent
)
,
m_display
(
display
)
,
m_compositor
(
nullptr
)
{
}
CompositorInterface
::~
CompositorInterface
()
{
destroy
();
}
void
CompositorInterface
::
create
()
{
Q_ASSERT
(
!
m_compositor
);
m_compositor
=
wl_global_create
(
*
m_display
,
&
wl_compositor_interface
,
s_version
,
this
,
CompositorInterface
::
bind
);
}
void
CompositorInterface
::
destroy
()
{
if
(
!
m_compositor
)
{
return
;
}
wl_global_destroy
(
m_compositor
);
m_compositor
=
nullptr
;
}
void
CompositorInterface
::
bind
(
wl_client
*
client
,
void
*
data
,
uint32_t
version
,
uint32_t
id
)
{
CompositorInterface
*
compositor
=
reinterpret_cast
<
CompositorInterface
*>
(
data
);
compositor
->
bind
(
client
,
version
,
id
);
}
void
CompositorInterface
::
bind
(
wl_client
*
client
,
uint32_t
version
,
uint32_t
id
)
{
wl_resource
*
resource
=
wl_resource_create
(
client
,
&
wl_compositor_interface
,
qMin
(
version
,
s_version
),
id
);
if
(
!
resource
)
{
wl_client_post_no_memory
(
client
);
return
;
}
wl_resource_set_implementation
(
resource
,
&
CompositorInterface
::
s_interface
,
this
,
CompositorInterface
::
unbind
);
// TODO: should we track?
}
void
CompositorInterface
::
unbind
(
wl_resource
*
resource
)
{
Q_UNUSED
(
resource
)
// TODO: implement?
}
void
CompositorInterface
::
createSurfaceCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
)
{
CompositorInterface
::
cast
(
resource
)
->
createSurface
(
client
,
resource
,
id
);
}
void
CompositorInterface
::
createSurface
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
)
{
SurfaceInterface
*
surface
=
new
SurfaceInterface
(
this
);
surface
->
create
(
client
,
wl_resource_get_version
(
resource
),
id
);
if
(
!
surface
->
surface
())
{
wl_resource_post_no_memory
(
resource
);
delete
surface
;
return
;
}
emit
surfaceCreated
(
surface
);
}
void
CompositorInterface
::
createRegionCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
)
{
CompositorInterface
::
cast
(
resource
)
->
createRegion
(
client
,
resource
,
id
);
}
void
CompositorInterface
::
createRegion
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
)
{
Q_UNUSED
(
client
)
Q_UNUSED
(
resource
)
Q_UNUSED
(
id
)
// TODO: implement
}
}
}
src/wayland/compositor_interface.h
0 → 100644
View file @
0cd3cbcf
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_WAYLAND_SERVER_COMPOSITOR_INTERFACE_H
#define KWIN_WAYLAND_SERVER_COMPOSITOR_INTERFACE_H
#include
"surface_interface.h"
#include
<QObject>
#include
<wayland-server.h>
namespace
KWin
{
namespace
WaylandServer
{
class
Display
;
class
SurfaceInterface
;
class
CompositorInterface
:
public
QObject
{
Q_OBJECT
public:
virtual
~
CompositorInterface
();
void
create
();
void
destroy
();
bool
isValid
()
const
{
return
m_compositor
!=
nullptr
;
}
Q_SIGNALS:
void
surfaceCreated
(
KWin
::
WaylandServer
::
SurfaceInterface
*
);
private:
explicit
CompositorInterface
(
Display
*
display
,
QObject
*
parent
=
nullptr
);
friend
class
Display
;
static
void
bind
(
wl_client
*
client
,
void
*
data
,
uint32_t
version
,
uint32_t
id
);
static
void
unbind
(
wl_resource
*
resource
);
static
void
createSurfaceCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
);
static
void
createRegionCallback
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
);
void
bind
(
wl_client
*
client
,
uint32_t
version
,
uint32_t
id
);
void
createSurface
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
);
void
createRegion
(
wl_client
*
client
,
wl_resource
*
resource
,
uint32_t
id
);
static
CompositorInterface
*
cast
(
wl_resource
*
r
)
{
return
reinterpret_cast
<
CompositorInterface
*>
(
wl_resource_get_user_data
(
r
));
}
static
const
struct
wl_compositor_interface
s_interface
;
Display
*
m_display
;
wl_global
*
m_compositor
;
};
}
}
#endif
src/wayland/display.cpp
0 → 100644
View file @
0cd3cbcf
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include
"display.h"
#include
"compositor_interface.h"
#include
"output_interface.h"
#include
"seat_interface.h"
#include
"shell_interface.h"
#include
<QCoreApplication>
#include
<QDebug>
#include
<QAbstractEventDispatcher>
#include
<QSocketNotifier>
#include
<wayland-server.h>
namespace
KWin
{
namespace
WaylandServer
{
Display
::
Display
(
QObject
*
parent
)
:
QObject
(
parent
)
,
m_display
(
nullptr
)
,
m_loop
(
nullptr
)
,
m_socketName
(
QStringLiteral
(
"wayland-0"
))
,
m_running
(
false
)
{
connect
(
QCoreApplication
::
eventDispatcher
(),
&
QAbstractEventDispatcher
::
aboutToBlock
,
this
,
&
Display
::
flush
);
}
Display
::~
Display
()
{
terminate
();
}
void
Display
::
flush
()
{
if
(
!
m_display
||
!
m_loop
)
{
return
;
}
if
(
wl_event_loop_dispatch
(
m_loop
,
0
)
!=
0
)
{
qWarning
()
<<
"Error on dispatching Wayland event loop"
;
}
wl_display_flush_clients
(
m_display
);
}
void
Display
::
setSocketName
(
const
QString
&
name
)
{
if
(
m_socketName
==
name
)
{
return
;
}
m_socketName
=
name
;
emit
socketNameChanged
(
m_socketName
);
}
QString
Display
::
socketName
()
const
{
return
m_socketName
;
}
void
Display
::
start
()
{
Q_ASSERT
(
!
m_running
);
Q_ASSERT
(
!
m_display
);
m_display
=
wl_display_create
();
if
(
wl_display_add_socket
(
m_display
,
qPrintable
(
m_socketName
))
!=
0
)
{
return
;
}
m_loop
=
wl_display_get_event_loop
(
m_display
);
int
fd
=
wl_event_loop_get_fd
(
m_loop
);
if
(
fd
==
-
1
)
{
qWarning
()
<<
"Did not get the file descriptor for the event loop"
;
return
;
}
QSocketNotifier
*
m_notifier
=
new
QSocketNotifier
(
fd
,
QSocketNotifier
::
Read
,
this
);
connect
(
m_notifier
,
&
QSocketNotifier
::
activated
,
this
,
&
Display
::
flush
);
setRunning
(
true
);
}
void
Display
::
terminate
()
{
if
(
!
m_running
)
{
return
;
}
emit
aboutToTerminate
();
wl_display_terminate
(
m_display
);
wl_display_destroy
(
m_display
);
m_display
=
nullptr
;
m_loop
=
nullptr
;
setRunning
(
false
);
}
void
Display
::
setRunning
(
bool
running
)
{
Q_ASSERT
(
m_running
!=
running
);
m_running
=
running
;
emit
runningChanged
(
m_running
);
}
OutputInterface
*
Display
::
createOutput
(
QObject
*
parent
)
{
OutputInterface
*
output
=
new
OutputInterface
(
this
,
parent
);
connect
(
output
,
&
QObject
::
destroyed
,
this
,
[
this
,
output
]
{
m_outputs
.
removeAll
(
output
);
});
connect
(
this
,
&
Display
::
aboutToTerminate
,
output
,
[
this
,
output
]
{
removeOutput
(
output
);
});
m_outputs
<<
output
;
return
output
;
}
CompositorInterface
*
Display
::
createCompositor
(
QObject
*
parent
)
{
CompositorInterface
*
compositor
=
new
CompositorInterface
(
this
,
parent
);
connect
(
this
,
&
Display
::
aboutToTerminate
,
compositor
,
[
this
,
compositor
]
{
delete
compositor
;
});
return
compositor
;
}
ShellInterface
*
Display
::
createShell
(
QObject
*
parent
)
{
ShellInterface
*
shell
=
new
ShellInterface
(
this
,
parent
);
connect
(
this
,
&
Display
::
aboutToTerminate
,
shell
,
[
this
,
shell
]
{
delete
shell
;
});
return
shell
;
}
SeatInterface
*
Display
::
createSeat
(
QObject
*
parent
)
{
SeatInterface
*
seat
=
new
SeatInterface
(
this
,
parent
);
connect
(
this
,
&
Display
::
aboutToTerminate
,
seat
,
[
this
,
seat
]
{
delete
seat
;
});
return
seat
;
}
void
Display
::
createShm
()
{
Q_ASSERT
(
m_running
);
wl_display_init_shm
(
m_display
);
}
void
Display
::
removeOutput
(
OutputInterface
*
output
)
{
m_outputs
.
removeAll
(
output
);
delete
output
;
}
quint32
Display
::
nextSerial
()
{
return
wl_display_next_serial
(
m_display
);
}
quint32
Display
::
serial
()
{
return
wl_display_get_serial
(
m_display
);
}
}
}
src/wayland/display.h
0 → 100644
View file @
0cd3cbcf
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_WAYLAND_SERVER_DISPLAY_H
#define KWIN_WAYLAND_SERVER_DISPLAY_H
#include
<QList>
#include
<QObject>
struct
wl_display
;
struct
wl_event_loop
;
namespace
KWin
{
namespace
WaylandServer
{
class
CompositorInterface
;
class
OutputInterface
;
class
SeatInterface
;
class
ShellInterface
;
class
Display
:
public
QObject
{
Q_OBJECT
Q_PROPERTY
(
QString
socketName
READ
socketName
WRITE
setSocketName
NOTIFY
socketNameChanged
)
Q_PROPERTY
(
bool
running
READ
isRunning
NOTIFY
runningChanged
)
public:
explicit
Display
(
QObject
*
parent
=
nullptr
);
virtual
~
Display
();
void
setSocketName
(
const
QString
&
name
);
QString
socketName
()
const
;
quint32
serial
();
quint32
nextSerial
();
void
start
();
void
terminate
();
operator
wl_display
*
()
{
return
m_display
;
}
operator
wl_display
*
()
const
{
return
m_display
;
}
bool
isRunning
()
const
{
return
m_running
;
}
OutputInterface
*
createOutput
(
QObject
*
parent
=
nullptr
);
void
removeOutput
(
OutputInterface
*
output
);
const
QList
<
OutputInterface
*>
&
outputs
()
const
{
return
m_outputs
;
}
CompositorInterface
*
createCompositor
(
QObject
*
parent
=
nullptr
);
void
createShm
();
ShellInterface
*
createShell
(
QObject
*
parent
=
nullptr
);
SeatInterface
*
createSeat
(
QObject
*
parent
=
nullptr
);
Q_SIGNALS:
void
socketNameChanged
(
const
QString
&
);
void
runningChanged
(
bool
);
void
aboutToTerminate
();
private:
void
flush
();
void
setRunning
(
bool
running
);
wl_display
*
m_display
;
wl_event_loop
*
m_loop
;
QString
m_socketName
;
bool
m_running
;
QList
<
OutputInterface
*>
m_outputs
;
};
}
}
#endif
src/wayland/output_interface.cpp
0 → 100644
View file @
0cd3cbcf
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include
"output_interface.h"
#include
"display.h"
#include
<wayland-server.h>
namespace
KWin
{
namespace
WaylandServer
{
static
const
quint32
s_version
=
2
;
OutputInterface
::
OutputInterface
(
Display
*
display
,
QObject
*
parent
)
:
QObject
(
parent
)
,
m_display
(
display
)
,
m_output
(
nullptr
)
,
m_physicalSize
(
QSize
())
,
m_globalPosition
(
QPoint
())
,
m_manufacturer
(
QStringLiteral
(
"org.kde.kwin"
))
,
m_model
(
QStringLiteral
(
"none"
))
,
m_scale
(
1
)
,
m_subPixel
(
SubPixel
::
Unknown
)
,
m_transform
(
Transform
::
Normal
)
{
connect
(
this
,
&
OutputInterface
::
currentModeChanged
,
this
,
[
this
]
{
auto
currentModeIt
=
std
::
find_if
(
m_modes
.
constBegin
(),
m_modes
.
constEnd
(),
[](
const
Mode
&
mode
)
{
return
mode
.
flags
.
testFlag
(
ModeFlag
::
Current
);
});
if
(
currentModeIt
==
m_modes
.
constEnd
())
{
return
;
}
for
(
auto
it
=
m_resources
.
constBegin
();
it
!=
m_resources
.
constEnd
();
++
it
)
{
sendMode
((
*
it
).
resource
,
*
currentModeIt
);
sendDone
(
*
it
);
}
}
);
connect
(
this
,
&
OutputInterface
::
subPixelChanged
,
this
,
&
OutputInterface
::
updateGeometry
);
connect
(
this
,
&
OutputInterface
::
transformChanged
,
this
,
&
OutputInterface
::
updateGeometry
);
connect
(
this
,
&
OutputInterface
::
globalPositionChanged
,
this
,
&
OutputInterface
::
updateGeometry
);
connect
(
this
,
&
OutputInterface
::
modelChanged
,
this
,
&
OutputInterface
::
updateGeometry
);
connect
(
this
,
&
OutputInterface
::
manufacturerChanged
,
this
,
&
OutputInterface
::
updateGeometry
);
connect
(
this
,
&
OutputInterface
::
scaleChanged
,
this
,
&
OutputInterface
::
updateScale
);
}
OutputInterface
::~
OutputInterface
()
{
destroy
();
}
void
OutputInterface
::
create
()
{
Q_ASSERT
(
!
m_output
);
m_output
=
wl_global_create
(
*
m_display
,
&
wl_output_interface
,
s_version
,
this
,
OutputInterface
::
bind
);
}
void
OutputInterface
::
destroy
()
{
if
(
!
m_output
)
{
return
;
}
wl_global_destroy
(
m_output
);
m_output
=
nullptr
;
}
QSize
OutputInterface
::
pixelSize
()
const
{
auto
it
=
std
::
find_if
(
m_modes
.
begin
(),
m_modes
.
end
(),
[](
const
Mode
&
mode
)
{
return
mode
.
flags
.
testFlag
(
ModeFlag
::
Current
);
}
);
if
(
it
==
m_modes
.
end
())
{
return
QSize
();
}
return
(
*
it
).
size
;
}
int
OutputInterface
::
refreshRate
()
const
{
auto
it
=
std
::
find_if
(
m_modes
.
begin
(),
m_modes
.
end
(),
[](
const
Mode
&
mode
)
{
return
mode
.
flags
.
testFlag
(
ModeFlag
::
Current
);
}
);
if
(
it
==
m_modes
.
end
())
{
return
60000
;
}
return
(
*
it
).
refreshRate
;
}
void
OutputInterface
::
addMode
(
const
QSize
&
size
,
OutputInterface
::
ModeFlags
flags
,
int
refreshRate
)
{
Q_ASSERT
(
!
isValid
());
auto
currentModeIt
=
std
::
find_if
(
m_modes
.
begin
(),
m_modes
.
end
(),
[](
const
Mode
&
mode
)
{
return
mode
.
flags
.
testFlag
(
ModeFlag
::
Current
);
}
);
if
(
currentModeIt
==
m_modes
.
end
()
&&
!
flags
.
testFlag
(
ModeFlag
::
Current
))
{
// no mode with current flag - enforce
flags
|=
ModeFlag
::
Current
;
}
if
(
currentModeIt
!=
m_modes
.
end
()
&&
flags
.
testFlag
(
ModeFlag
::
Current
))
{
// another mode has the current flag - remove
(
*
currentModeIt
).
flags
&=
~
uint
(
ModeFlag
::
Current
);
}
if
(
flags
.
testFlag
(
ModeFlag
::
Preferred
))
{
// remove from existing Preferred mode
auto
preferredIt
=
std
::
find_if
(
m_modes
.
begin
(),
m_modes
.
end
(),
[](
const
Mode
&
mode
)
{
return
mode
.
flags
.
testFlag
(
ModeFlag
::
Preferred
);
}
);
if
(
preferredIt
!=
m_modes
.
end
())
{
(
*
preferredIt
).
flags
&=
~
uint
(
ModeFlag
::
Preferred
);
}
}
auto
existingModeIt
=
std
::
find_if
(
m_modes
.
begin
(),
m_modes
.
end
(),
[
size
,
refreshRate
](
const
Mode
&
mode
)
{
return
mode
.
size
==
size
&&
mode
.
refreshRate
==
refreshRate
;
}
);
auto
emitChanges
=
[
this
,
flags
,
size
,
refreshRate
]
{
emit
modesChanged
();
if
(
flags
.
testFlag
(
ModeFlag
::
Current
))
{
emit
refreshRateChanged
(
refreshRate
);
emit
pixelSizeChanged
(
size
);
emit
currentModeChanged
();
}
};
if
(
existingModeIt
!=
m_modes
.
end
())
{
if
((
*
existingModeIt
).
flags
==
flags
)
{