Skip to content

Commit

Permalink
use layer-shell-qt instead of speaking protocol on our own
Browse files Browse the repository at this point in the history
  • Loading branch information
xdavidwu committed Jul 19, 2023
1 parent 8913e96 commit f6c69a2
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 428 deletions.
28 changes: 7 additions & 21 deletions meson.build
Original file line number Diff line number Diff line change
@@ -1,22 +1,8 @@
project('qt-video-wlr',['c','cpp'])
project('qt-video-wlr', ['cpp'])

wl_client=dependency('wayland-client')
wl_protocols=dependency('wayland-protocols')
scanner=find_program('wayland-scanner')
scanner_private_code=generator(scanner,output: '@[email protected]',arguments: ['private-code','@INPUT@','@OUTPUT@'])
scanner_client_header=generator(scanner,output: '@[email protected]',arguments: ['client-header','@INPUT@','@OUTPUT@'])

protocols_src=[
scanner_private_code.process('wlr-layer-shell-unstable-v1.xml'),
scanner_private_code.process(wl_protocols.get_pkgconfig_variable('pkgdatadir')+'/stable/xdg-shell/xdg-shell.xml')
]
protocols_headers=[
scanner_client_header.process('wlr-layer-shell-unstable-v1.xml')
]
lib_protocols=static_library('protocols',protocols_src+protocols_headers,dependencies: wl_client)
protocols_dep=declare_dependency(link_with: lib_protocols,sources: protocols_headers)

qt5=import('qt5')
qt5_dep=dependency('qt5',modules: ['Widgets','Core','Multimedia','MultimediaWidgets','Gui'])
qtgui=dependency('Qt5Gui')
executable('qt-video-wlr',['qt-video-wlr-bg.cpp'],dependencies: [qt5_dep,protocols_dep],cpp_args: '-I'+join_paths(qtgui.get_pkgconfig_variable('includedir'),'QtGui',qtgui.version(),'QtGui'),install: true)
qt5_dep = dependency('qt5', modules: ['Widgets', 'Core', 'Multimedia', 'MultimediaWidgets', 'Gui'])
layer_shell_qt_dep = dependency('LayerShellQt', modules: ['LayerShellQt::Interface'])
executable('qt-video-wlr',
['qt-video-wlr-bg.cpp'],
dependencies: [qt5_dep, layer_shell_qt_dep],
install: true)
194 changes: 72 additions & 122 deletions qt-video-wlr-bg.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,27 @@
#include <QUrl>
#include <QWidget>
#include <QFileInfo>
#include <QApplication>
#include <QCommandLineParser>
#include <QFileInfo>
#include <QMediaPlayer>
#include <QVideoWidget>
#include <QMediaPlaylist>
#include <QCommandLineParser>
#include <qpa/qplatformnativeinterface.h>
#include <iostream>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include <QUrl>
#include <QVBoxLayout>
#include <QVideoWidget>
#include <QWidget>
#include <QWindow>

struct qvw_state {
struct zwlr_layer_shell_v1 *layer_shell;
uint32_t width, height;
QApplication *app;
QWidget *root;
QVideoWidget *videoWidget;
};
#include <LayerShellQt/Window>
#include <LayerShellQt/Shell>

int main(int argc,char *argv[]){
struct wl_surface *wl_surface;
struct zwlr_layer_surface_v1 *layer_surface;
struct qvw_state state {
.app = new QApplication(argc, argv),
.root = new QWidget,
};

// hack: disable shell integration
setenv("QT_WAYLAND_SHELL_INTEGRATION","nonexistance",1);
LayerShellQt::Shell::useLayerShell();
QApplication::setApplicationName("qt-video-wlr");
QApplication::setApplicationVersion("dev");
// XXX: hack to make QWidget::windowHandle available before show
// removed @ Qt6
QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);

QApplication app(argc, argv);
QWidget root;

QCommandLineParser parser;
parser.setApplicationDescription("Qt pip-mode-like video player "
Expand Down Expand Up @@ -69,60 +61,66 @@ int main(int argc,char *argv[]){
volumeOption, positionOption, noLoopOption, marginOption,
topMarginOption, rightMarginOption, bottomMarginOption,
leftMarginOption });
parser.process(*state.app);
parser.process(app);

uint32_t layer, anchor;
int32_t top_margin, right_margin, bottom_margin, left_margin;
bool ok;

uint32_t width, height;
width = parser.value(widthOption).toInt(&ok);
if (!ok) parser.showHelp(1);
height = parser.value(heightOption).toInt(&ok);
if (!ok) parser.showHelp(1);

auto layerShell = LayerShellQt::Window::get(root.windowHandle());
LayerShellQt::Window::Layer layer;
QString layerStr = parser.value(layerOption);
if (layerStr == "background")
layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND;
layer = LayerShellQt::Window::LayerBackground;
else if (layerStr == "bottom")
layer = ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM;
layer = LayerShellQt::Window::LayerBottom;
else if (layerStr == "top")
layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
layer = LayerShellQt::Window::LayerTop;
else if (layerStr == "overlay")
layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
layer = LayerShellQt::Window::LayerOverlay;
else
parser.showHelp(1);
layerShell->setLayer(layer);

state.width = parser.value(widthOption).toInt(&ok);
if (!ok) parser.showHelp(1);
state.height = parser.value(heightOption).toInt(&ok);
if (!ok) parser.showHelp(1);

LayerShellQt::Window::Anchors anchor;
QString positionStr = parser.value(positionOption);
if (positionStr == "center")
anchor = 0;
anchor = {};
else if (positionStr == "top")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
anchor = LayerShellQt::Window::Anchor::AnchorTop;
else if (positionStr == "top-left")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
anchor = {LayerShellQt::Window::Anchor::AnchorTop,
LayerShellQt::Window::Anchor::AnchorLeft};
else if (positionStr == "top-right")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
anchor = {LayerShellQt::Window::Anchor::AnchorTop,
LayerShellQt::Window::Anchor::AnchorRight};
else if (positionStr == "bottom")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
anchor = LayerShellQt::Window::Anchor::AnchorBottom;
else if (positionStr == "bottom-left")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
anchor = {LayerShellQt::Window::Anchor::AnchorBottom,
LayerShellQt::Window::Anchor::AnchorLeft};
else if (positionStr == "bottom-right")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
anchor = {LayerShellQt::Window::Anchor::AnchorBottom,
LayerShellQt::Window::Anchor::AnchorRight};
else if (positionStr == "left")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
anchor = LayerShellQt::Window::Anchor::AnchorLeft;
else if (positionStr == "right")
anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
anchor = LayerShellQt::Window::Anchor::AnchorRight;
else
parser.showHelp(1);
if (state.width == 0)
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT;
if (state.height == 0)
anchor |= ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP;
if (width == 0)
anchor |= {LayerShellQt::Window::Anchor::AnchorLeft,
LayerShellQt::Window::Anchor::AnchorRight};
if (height == 0)
anchor |= {LayerShellQt::Window::Anchor::AnchorTop,
LayerShellQt::Window::Anchor::AnchorBottom};
layerShell->setAnchors(anchor);

int top_margin, right_margin, bottom_margin, left_margin;
top_margin = right_margin = bottom_margin = left_margin =
parser.value(marginOption).toInt(&ok);
if (!ok) parser.showHelp(1);
Expand All @@ -134,29 +132,17 @@ int main(int argc,char *argv[]){
if (!ok) parser.showHelp(1);
left_margin = parser.value(leftMarginOption).toInt(&ok);
if (!ok) parser.showHelp(1);
layerShell->setMargins({left_margin, top_margin, right_margin, bottom_margin});

QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface();
struct wl_display *display = (struct wl_display *)
native->nativeResourceForWindow("display", NULL);
struct wl_registry *registry = wl_display_get_registry(display);
const struct wl_registry_listener registry_listener = {
.global = [](void *data, struct wl_registry *registry,
uint32_t name, const char *interface, uint32_t version) {
struct qvw_state *state = static_cast<struct qvw_state *>(data);
if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
state->layer_shell = (zwlr_layer_shell_v1*)wl_registry_bind(
registry, name, &zwlr_layer_shell_v1_interface, 1);
}
},
.global_remove = [](void *data, struct wl_registry *registry, uint32_t name) {},
};
wl_registry_add_listener(registry, &registry_listener, &state);
wl_display_roundtrip(display);
if (state.layer_shell == NULL) {
fprintf(stderr, "layer_shell not available\n");
state.app->quit();
return 1;
}
layerShell->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityNone);

QVBoxLayout layout;
QVideoWidget videoWidget;
layout.addWidget(&videoWidget);
layout.setContentsMargins({});
root.setLayout(&layout);
root.resize(width ? width : 1, height ? height : 1);
root.show();

QMediaPlayer player;
QMediaPlaylist playlist;
Expand All @@ -174,63 +160,27 @@ int main(int argc,char *argv[]){
if (!ok) parser.showHelp(1);
}

state.videoWidget = new QVideoWidget(state.root);
state.root->resize(state.width ? state.width : 1, state.height ? state.height : 1);
state.root->show();

wl_surface = static_cast<struct wl_surface *>(
native->nativeResourceForWindow("surface", state.root->windowHandle()));
layer_surface = zwlr_layer_shell_v1_get_layer_surface(state.layer_shell,
wl_surface, NULL, layer, "video-player");

const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
.configure = [](void *data,
struct zwlr_layer_surface_v1 *surface,
uint32_t serial, uint32_t w, uint32_t h) {
struct qvw_state *state = static_cast<struct qvw_state *>(data);
printf("resize %d %d\n", w, h);
state->root->resize(w, h);
state->videoWidget->resize(w ,h);
zwlr_layer_surface_v1_ack_configure(surface, serial);
},
.closed = [](void *data,
struct zwlr_layer_surface_v1 *surface) {
struct qvw_state *state = static_cast<struct qvw_state *>(data);
zwlr_layer_surface_v1_destroy(surface);
state->app->quit();
},
};
zwlr_layer_surface_v1_set_margin(layer_surface, top_margin, right_margin,
bottom_margin, left_margin);
zwlr_layer_surface_v1_set_size(layer_surface, state.width, state.height);
zwlr_layer_surface_v1_set_anchor(layer_surface, anchor);
zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener, &state);
wl_surface_commit(wl_surface);
wl_display_roundtrip(display);

player.setVideoOutput(state.videoWidget);
state.videoWidget->setMinimumSize(state.width ? state.width : 1, state.height ? state.height : 1);
player.setVideoOutput(&videoWidget);
if (parser.isSet(colorOption)) {
QColor qcolor(parser.value(colorOption));
if(!qcolor.isValid()) parser.showHelp(1);
QPalette pal;
pal.setColor(QPalette::Window, qcolor);
state.videoWidget->setAutoFillBackground(true);
state.videoWidget->setPalette(pal);
videoWidget.setAutoFillBackground(true);
videoWidget.setPalette(pal);
QPalette pal2;
pal2.setColor(QPalette::Window, "#00000000");
state.root->setAutoFillBackground(true);
state.root->setPalette(pal2);
root.setAutoFillBackground(true);
root.setPalette(pal2);
}
state.videoWidget->show();
videoWidget.show();
player.play();
QObject::connect(&player, &QMediaPlayer::stateChanged,
[&layer_surface, &state](QMediaPlayer::State playerState) {
[&app](QMediaPlayer::State playerState) {
if(playerState == QMediaPlayer::StoppedState){
zwlr_layer_surface_v1_destroy(layer_surface);
state.app->quit();
app.quit();
}
});

return state.app->exec();
return app.exec();
}
Loading

0 comments on commit f6c69a2

Please sign in to comment.