Implement the fullscreen shell protocol

Fixes #86.
This commit is contained in:
Jente Hidskes 2020-02-02 15:14:31 +01:00
parent b04e02cd60
commit 96b4294e47
No known key found for this signature in database
GPG key ID: 04BE5A29F32D91EA
7 changed files with 170 additions and 0 deletions

11
cage.c
View file

@ -39,6 +39,7 @@
#include <wlr/xwayland.h>
#endif
#include "fullscreen_shell.h"
#include "idle_inhibit_v1.h"
#include "output.h"
#include "seat.h"
@ -181,6 +182,7 @@ main(int argc, char *argv[])
struct wlr_screencopy_manager_v1 *screencopy_manager = NULL;
struct wlr_xdg_output_manager_v1 *output_manager = NULL;
struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL;
struct wlr_fullscreen_shell_v1 *fullscreen_shell = NULL;
struct wlr_xdg_shell *xdg_shell = NULL;
#if CAGE_HAS_XWAYLAND
struct wlr_xwayland *xwayland = NULL;
@ -283,6 +285,15 @@ main(int argc, char *argv[])
wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1);
wl_list_init(&server.inhibitors);
fullscreen_shell = wlr_fullscreen_shell_v1_create(server.wl_display);
if (!fullscreen_shell) {
wlr_log(WLR_ERROR, "Unable to create the Fullscreen Shell interface");
ret = 1;
goto end;
}
server.fullscreen_shell_present_surface.notify = handle_fullscreen_shell_present_surface;
wl_signal_add(&fullscreen_shell->events.present_surface, &server.fullscreen_shell_present_surface);
xdg_shell = wlr_xdg_shell_create(server.wl_display);
if (!xdg_shell) {
wlr_log(WLR_ERROR, "Unable to create the XDG shell interface");

132
fullscreen_shell.c Normal file
View file

@ -0,0 +1,132 @@
/*
* Cage: A Wayland kiosk.
*
* Copyright (C) 2020 Jente Hidskes
*
* See the LICENSE file accompanying this file.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <wayland-server-core.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_fullscreen_shell_v1.h>
#include <wlr/util/log.h>
#include "fullscreen_shell.h"
#include "output.h"
#include "server.h"
#include "view.h"
static struct cg_fullscreen_shell_view *
fullscreen_shell_view_from_view(struct cg_view *view)
{
return (struct cg_fullscreen_shell_view *) view;
}
static void
get_geometry(struct cg_view *view, int *width_out, int *height_out)
{
// struct wlr_box *layout_box = wlr_output_layout_get_box(view->server->output_layout, NULL);
// *width_out = layout_box->width;
// *height_out = layout_box->height;
*width_out = view->wlr_surface->current.width;
*height_out = view->wlr_surface->current.height;
}
static bool
is_primary(struct cg_view *view)
{
return true;
}
static bool
is_transient_for(struct cg_view *child, struct cg_view *parent)
{
return false;
}
static void
maximize(struct cg_view *view, int output_width, int output_height)
{
// view->wlr_surface->pending.width = output_width;
// view->wlr_surface->pending.height = output_height;
}
static void
destroy(struct cg_view *view)
{
struct cg_fullscreen_shell_view *fullscreen_shell_view = fullscreen_shell_view_from_view(view);
free(fullscreen_shell_view);
}
static void
for_each_surface(struct cg_view *view, wlr_surface_iterator_func_t iterator, void *data)
{
wlr_surface_for_each_surface(view->wlr_surface, iterator, data);
}
static struct wlr_surface *
wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y)
{
return wlr_surface_surface_at(view->wlr_surface, sx, sy, sub_x, sub_y);
}
//static void output_set_surface(struct cg_output *output, struct wlr_surface *surface);
//
//static void
//output_handle_surface_destroy(struct wl_listener *listener, void *data)
//{
// struct cg_output *output = wl_container_of(listener, output, surface_destroy);
// output_set_surface(output, NULL);
//}
//
//static void
//output_set_surface(struct cg_output *output, struct wlr_surface *surface)
//{
// if (output->surface == surface) {
// return;
// }
//
// if (output->surface) {
// wl_list_remove(&output->surface_destroy.link);
// output->surface = NULL;
// }
//
// if (surface) {
// output->surface_destroy.notify = output_handle_surface_destroy;
// wl_signal_add(&surface->events.destroy, &output->surface_destroy);
// output->surface = surface;
// }
//
// wlr_log(WLR_DEBUG, "Presenting fullscreen shell surface %p on output %s", surface, output->wlr_output->name);
//}
static const struct cg_view_impl fullscreen_shell_view_impl = {
.get_title = NULL,
.get_geometry = get_geometry,
.is_primary = is_primary,
.is_transient_for = is_transient_for,
.activate = NULL,
.maximize = maximize,
.destroy = destroy,
.for_each_surface = for_each_surface,
.for_each_popup = NULL,
.wlr_surface_at = wlr_surface_at,
};
void
handle_fullscreen_shell_present_surface(struct wl_listener *listener, void *data)
{
struct cg_server *server = wl_container_of(listener, server, fullscreen_shell_present_surface);
struct wlr_fullscreen_shell_v1_present_surface_event *event = data;
struct cg_fullscreen_shell_view *fullscreen_shell_view = calloc(1, sizeof(struct cg_fullscreen_shell_view));
if (!fullscreen_shell_view) {
wlr_log(WLR_ERROR, "Failed to allocate Fullscreen Shell view");
return;
}
view_init(&fullscreen_shell_view->view, server, CAGE_FULLSCREEN_SHELL_VIEW, &fullscreen_shell_view_impl);
view_map(&fullscreen_shell_view->view, event->surface);
}

15
fullscreen_shell.h Normal file
View file

@ -0,0 +1,15 @@
#ifndef CG_FULLSCREEN_SHELL_H
#define CG_FULLSCREEN_SHELL_H
#include <wayland-server-core.h>
#include <wlr/types/wlr_fullscreen_shell_v1.h>
#include "view.h"
struct cg_fullscreen_shell_view {
struct cg_view view;
};
void handle_fullscreen_shell_present_surface(struct wl_listener *listener, void *data);
#endif

View file

@ -51,6 +51,7 @@ wayland_scanner_server = generator(
server_protocols = [
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml'],
]
server_protos_headers = []
@ -96,6 +97,7 @@ conf_data.set_quoted('CAGE_VERSION', version)
cage_sources = [
'cage.c',
'fullscreen_shell.c',
'idle_inhibit_v1.c',
'output.c',
'render.c',
@ -109,6 +111,7 @@ cage_headers = [
configure_file(input: 'config.h.in',
output: 'config.h',
configuration: conf_data),
'fullscreen_shell.h',
'idle_inhibit_v1.h',
'output.h',
'render.h',

View file

@ -32,6 +32,7 @@ struct cg_server {
struct wl_list outputs;
struct wl_listener new_output;
struct wl_listener fullscreen_shell_present_surface;
struct wl_listener xdg_toplevel_decoration;
struct wl_listener new_xdg_shell_surface;
#if CAGE_HAS_XWAYLAND

7
view.c
View file

@ -117,6 +117,10 @@ handle_new_subsurface(struct wl_listener *listener, void *data)
char *
view_get_title(struct cg_view *view)
{
if (!view->impl->get_title) {
return NULL;
}
const char *title = view->impl->get_title(view);
if (!title) {
return NULL;
@ -156,6 +160,9 @@ view_damage_whole(struct cg_view *view)
void
view_activate(struct cg_view *view, bool activate)
{
if (!view->impl->activate) {
return;
}
view->impl->activate(view, activate);
}

1
view.h
View file

@ -15,6 +15,7 @@
#include "server.h"
enum cg_view_type {
CAGE_FULLSCREEN_SHELL_VIEW,
CAGE_XDG_SHELL_VIEW,
#if CAGE_HAS_XWAYLAND
CAGE_XWAYLAND_VIEW,