Skip to content

Commit

Permalink
Replace xdg_output with wl_output v4
Browse files Browse the repository at this point in the history
  • Loading branch information
emersion committed Jun 3, 2022
1 parent de77798 commit 69c03f6
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 102 deletions.
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# swaybg

swaybg is a wallpaper utility for Wayland compositors. It is compatible with any
Wayland compositor which implements the following Wayland protocols:

- wlr-layer-shell
- xdg-output
swaybg is a wallpaper utility for Wayland compositors. It is compatible with
any Wayland compositor which implements the wlr-layer-shell protocol and
`wl_output` version 4.

See the man page, `swaybg(1)`, for instructions on using swaybg.

Expand Down
150 changes: 54 additions & 96 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include "log.h"
#include "pool-buffer.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"

static uint32_t parse_color(const char *color) {
if (color[0] == '#') {
Expand All @@ -38,7 +37,6 @@ struct swaybg_state {
struct wl_compositor *compositor;
struct wl_shm *shm;
struct zwlr_layer_shell_v1 *layer_shell;
struct zxdg_output_manager_v1 *xdg_output_manager;
struct wl_list configs; // struct swaybg_output_config::link
struct wl_list outputs; // struct swaybg_output::link
struct wl_list images; // struct swaybg_image::link
Expand All @@ -63,7 +61,6 @@ struct swaybg_output_config {
struct swaybg_output {
uint32_t wl_name;
struct wl_output *wl_output;
struct zxdg_output_v1 *xdg_output;
char *name;
char *identifier;

Expand Down Expand Up @@ -184,7 +181,6 @@ static void destroy_swaybg_output(struct swaybg_output *output) {
if (output->surface != NULL) {
wl_surface_destroy(output->surface);
}
zxdg_output_v1_destroy(output->xdg_output);
wl_output_destroy(output->wl_output);
free(output->name);
free(output->identifier);
Expand Down Expand Up @@ -226,8 +222,45 @@ static void output_mode(void *data, struct wl_output *output, uint32_t flags,
// Who cares
}

static void output_done(void *data, struct wl_output *output) {
// Who cares
static void create_layer_surface(struct swaybg_output *output) {
output->surface = wl_compositor_create_surface(output->state->compositor);
assert(output->surface);

// Empty input region
struct wl_region *input_region =
wl_compositor_create_region(output->state->compositor);
assert(input_region);
wl_surface_set_input_region(output->surface, input_region);
wl_region_destroy(input_region);

output->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
output->state->layer_shell, output->surface, output->wl_output,
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper");
assert(output->layer_surface);

zwlr_layer_surface_v1_set_size(output->layer_surface, 0, 0);
zwlr_layer_surface_v1_set_anchor(output->layer_surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1);
zwlr_layer_surface_v1_add_listener(output->layer_surface,
&layer_surface_listener, output);
wl_surface_commit(output->surface);
}

static void output_done(void *data, struct wl_output *wl_output) {
struct swaybg_output *output = data;
if (!output->config) {
swaybg_log(LOG_DEBUG, "Could not find config for output %s (%s)",
output->name, output->identifier);
destroy_swaybg_output(output);
} else if (!output->layer_surface) {
swaybg_log(LOG_DEBUG, "Found config %s for output %s (%s)",
output->config->output, output->name, output->identifier);
create_layer_surface(output);
}
}

static void output_scale(void *data, struct wl_output *wl_output,
Expand All @@ -239,23 +272,6 @@ static void output_scale(void *data, struct wl_output *wl_output,
}
}

static const struct wl_output_listener output_listener = {
.geometry = output_geometry,
.mode = output_mode,
.done = output_done,
.scale = output_scale,
};

static void xdg_output_handle_logical_position(void *data,
struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y) {
// Who cares
}

static void xdg_output_handle_logical_size(void *data,
struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height) {
// Who cares
}

static void find_config(struct swaybg_output *output, const char *name) {
struct swaybg_output_config *config = NULL;
wl_list_for_each(config, &output->state->configs, link) {
Expand All @@ -268,8 +284,8 @@ static void find_config(struct swaybg_output *output, const char *name) {
}
}

static void xdg_output_handle_name(void *data,
struct zxdg_output_v1 *xdg_output, const char *name) {
static void output_name(void *data, struct wl_output *wl_output,
const char *name) {
struct swaybg_output *output = data;
output->name = strdup(name);

Expand All @@ -280,8 +296,8 @@ static void xdg_output_handle_name(void *data,
}
}

static void xdg_output_handle_description(void *data,
struct zxdg_output_v1 *xdg_output, const char *description) {
static void output_description(void *data, struct wl_output *wl_output,
const char *description) {
struct swaybg_output *output = data;

// wlroots currently sets the description to `make model serial (name)`
Expand All @@ -301,54 +317,13 @@ static void xdg_output_handle_description(void *data,
}
}

static void create_layer_surface(struct swaybg_output *output) {
output->surface = wl_compositor_create_surface(output->state->compositor);
assert(output->surface);

// Empty input region
struct wl_region *input_region =
wl_compositor_create_region(output->state->compositor);
assert(input_region);
wl_surface_set_input_region(output->surface, input_region);
wl_region_destroy(input_region);

output->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
output->state->layer_shell, output->surface, output->wl_output,
ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND, "wallpaper");
assert(output->layer_surface);

zwlr_layer_surface_v1_set_size(output->layer_surface, 0, 0);
zwlr_layer_surface_v1_set_anchor(output->layer_surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1);
zwlr_layer_surface_v1_add_listener(output->layer_surface,
&layer_surface_listener, output);
wl_surface_commit(output->surface);
}

static void xdg_output_handle_done(void *data,
struct zxdg_output_v1 *xdg_output) {
struct swaybg_output *output = data;
if (!output->config) {
swaybg_log(LOG_DEBUG, "Could not find config for output %s (%s)",
output->name, output->identifier);
destroy_swaybg_output(output);
} else if (!output->layer_surface) {
swaybg_log(LOG_DEBUG, "Found config %s for output %s (%s)",
output->config->output, output->name, output->identifier);
create_layer_surface(output);
}
}

static const struct zxdg_output_v1_listener xdg_output_listener = {
.logical_position = xdg_output_handle_logical_position,
.logical_size = xdg_output_handle_logical_size,
.name = xdg_output_handle_name,
.description = xdg_output_handle_description,
.done = xdg_output_handle_done,
static const struct wl_output_listener output_listener = {
.geometry = output_geometry,
.mode = output_mode,
.done = output_done,
.scale = output_scale,
.name = output_name,
.description = output_description,
};

static void handle_global(void *data, struct wl_registry *registry,
Expand All @@ -364,22 +339,12 @@ static void handle_global(void *data, struct wl_registry *registry,
output->state = state;
output->wl_name = name;
output->wl_output =
wl_registry_bind(registry, name, &wl_output_interface, 3);
wl_registry_bind(registry, name, &wl_output_interface, 4);
wl_output_add_listener(output->wl_output, &output_listener, output);
wl_list_insert(&state->outputs, &output->link);

if (state->run_display) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
state->xdg_output_manager, output->wl_output);
zxdg_output_v1_add_listener(output->xdg_output,
&xdg_output_listener, output);
}
} else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
state->layer_shell =
wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
state->xdg_output_manager = wl_registry_bind(registry, name,
&zxdg_output_manager_v1_interface, 2);
}
}

Expand Down Expand Up @@ -578,22 +543,15 @@ int main(int argc, char **argv) {
return 1;
}
if (state.compositor == NULL || state.shm == NULL ||
state.layer_shell == NULL || state.xdg_output_manager == NULL) {
state.layer_shell == NULL) {
swaybg_log(LOG_ERROR, "Missing a required Wayland interface");
return 1;
}

struct swaybg_output *output;
wl_list_for_each(output, &state.outputs, link) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output(
state.xdg_output_manager, output->wl_output);
zxdg_output_v1_add_listener(output->xdg_output,
&xdg_output_listener, output);
}

state.run_display = true;
while (wl_display_dispatch(state.display) != -1 && state.run_display) {
// Send acks, and determine which images need to be loaded
struct swaybg_output *output;
wl_list_for_each(output, &state.outputs, link) {
if (output->needs_ack) {
output->needs_ack = false;
Expand Down Expand Up @@ -644,7 +602,7 @@ int main(int argc, char **argv) {
}
}

struct swaybg_output *tmp_output;
struct swaybg_output *output, *tmp_output;
wl_list_for_each_safe(output, tmp_output, &state.outputs, link) {
destroy_swaybg_output(output);
}
Expand Down
1 change: 0 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ client_protos_headers = []

client_protocols = [
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
]

Expand Down

0 comments on commit 69c03f6

Please sign in to comment.