Skip to content

Commit

Permalink
Implement per output configuration & fractional scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
francma committed Oct 13, 2023
1 parent c3db849 commit bd646ba
Show file tree
Hide file tree
Showing 15 changed files with 702 additions and 325 deletions.
1 change: 0 additions & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ trim_trailing_whitespace = true

[*.{c,h,txt}]
indent_style = tab
indent_size = 4

[*.{xml,yml}]
indent_style = space
Expand Down
48 changes: 26 additions & 22 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,38 @@ wayland_scanner_client = generator(
arguments: ['client-header', '@INPUT@', '@OUTPUT@'],
)

client_protocols = [
[wl_protocol_dir + '/stable/xdg-shell', 'xdg-shell.xml'],
[meson.project_source_root() + '/protocols', 'wlr-layer-shell-unstable-v1.xml'],
wl_proto_xml = [
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'stable/viewporter/viewporter.xml',
'protocols/wlr-layer-shell-unstable-v1.xml',
]

foreach p : client_protocols
xml = join_paths(p)
src = wayland_scanner_code.process(xml)
header = wayland_scanner_client.process(xml)

name = p[1].split('.')[0].underscorify()

lib = static_library(
name,
[src, header],
dependencies: [wayland_client],
)

dep = declare_dependency(
link_with: lib,
sources: header,
if wayland_protos.version().version_compare('>=1.31')
wl_proto_xml += wl_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml'
add_project_arguments(
['-DHAVE_FRACTIONAL_SCALE_PROTOCOL=1'],
language: 'c'
)
endif

set_variable(name, dep)
wl_proto_headers = []
wl_proto_src = []
foreach proto : wl_proto_xml
wl_proto_headers += custom_target(
proto.underscorify() + '_client_header',
output: '@[email protected]',
input: proto,
command: [wayland_scanner, 'client-header', '@INPUT@', '@OUTPUT@'])

wl_proto_src += custom_target(
proto.underscorify() + '_private_code',
output: '@[email protected]',
input: proto,
command: [wayland_scanner, 'private-code', '@INPUT@', '@OUTPUT@'])
endforeach

wob_sources = ['src/main.c', 'src/image.c', 'src/log.c', 'src/color.c', 'src/config.c', 'src/wob.c']
wob_dependencies = [wayland_client, wlr_layer_shell_unstable_v1, xdg_shell, rt, inih]
wob_sources = ['src/main.c', 'src/image.c', 'src/log.c', 'src/color.c', 'src/config.c', 'src/wob.c', 'src/shm.c', wl_proto_src, wl_proto_headers]
wob_dependencies = [wayland_client, rt, inih]
if seccomp.found()
wob_dependencies += seccomp
wob_sources += 'src/pledge_seccomp.c'
Expand Down
18 changes: 9 additions & 9 deletions protocols/wlr-layer-shell-unstable-v1.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<description summary="create surfaces that are layers of the desktop">
Clients can use this interface to assign the surface_layer role to
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
rendered with a defined z-depth respective to each other. They may also be
surface with a defined z-depth respective to each other. They may also be
anchored to the edges and corners of a screen and specify input handling
semantics. This interface should be suitable for the implementation of
many desktop shell components, and a broad number of other applications
Expand All @@ -42,9 +42,9 @@
layer_surface, or raises a protocol error if another role is already
assigned.

Creating a layer surface from a wl_surface which has a buffer attached
Creating a layer surface from a wl_surface which has a shm_data attached
or committed is a client error, and any attempts by a client to attach
or manipulate a buffer prior to the first layer_surface.configure call
or manipulate a shm_data prior to the first layer_surface.configure call
must also be treated as errors.

You may pass NULL for output to allow the compositor to decide which
Expand All @@ -64,15 +64,15 @@
<enum name="error">
<entry name="role" value="0" summary="wl_surface has another role"/>
<entry name="invalid_layer" value="1" summary="layer value is invalid"/>
<entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
<entry name="already_constructed" value="2" summary="wl_surface has a shm_data attached or committed"/>
</enum>

<enum name="layer">
<description summary="available layers for surfaces">
These values indicate which layers a surface can be rendered in. They
These values indicate which layers a surface can be surface in. They
are ordered by z depth, bottom-most first. Traditional shell surfaces
will typically be rendered between the bottom and top layers.
Fullscreen shell surfaces are typically rendered at the top layer.
will typically be surface between the bottom and top layers.
Fullscreen shell surfaces are typically surface at the top layer.
Multiple surfaces can share a single layer, and ordering within a
single layer is undefined.
</description>
Expand All @@ -87,7 +87,7 @@
<interface name="zwlr_layer_surface_v1" version="2">
<description summary="layer metadata interface">
An interface that may be implemented by a wl_surface, for surfaces that
are designed to be rendered as a layer of a stacked desktop-like
are designed to be surface as a layer of a stacked desktop-like
environment.

Layer surface state (layer, size, anchor, exclusive zone,
Expand Down Expand Up @@ -291,7 +291,7 @@

<request name="set_layer" since="2">
<description summary="change the layer of the surface">
Change the layer that the surface is rendered on.
Change the layer that the surface is surface on.

Layer is double-buffered, see wl_surface.commit.
</description>
Expand Down
1 change: 1 addition & 0 deletions src/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ wob_color_from_rgba_string(const char *str, struct wob_color *color)
switch (length) {
case 8:
parts[3] = hex_to_int(str[6]) * 16 + hex_to_int(str[7]);
// fallthrough
case 6:
parts[0] = hex_to_int(str[0]) * 16 + hex_to_int(str[1]);
parts[1] = hex_to_int(str[2]) * 16 + hex_to_int(str[3]);
Expand Down
129 changes: 120 additions & 9 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,14 +318,52 @@ handler(void *user, const char *section, const char *name, const char *value)

struct wob_output_config *output_config = wob_config_find_output(config, output_id);
if (output_config == NULL) {
output_config = malloc(sizeof(struct wob_output_config));
output_config = calloc(1, sizeof(struct wob_output_config));
if (output_config == NULL) {
wob_log_panic("calloc() failed");
}

output_config->id = strdup(output_id);
output_config->match = NULL;
output_config->dimensions = config->dimensions;
output_config->margin = config->margin;
output_config->anchor = config->anchor;
wl_list_insert(&config->outputs, &output_config->link);
}

if (strcmp(name, "name") == 0) {
output_config->name = strdup(value);

if (strcmp(name, "match") == 0) {
output_config->match = strdup(value);
return 1;
}
if (strcmp(name, "width") == 0) {
if (parse_number(value, &ul) == false) {
wob_log_error("Width must be a positive value.");
return 0;
}
output_config->dimensions.width = ul;
return 1;
}
if (strcmp(name, "height") == 0) {
if (parse_number(value, &ul) == false) {
wob_log_error("Height must be a positive value.");
return 0;
}
output_config->dimensions.height = ul;
return 1;
}
if (strcmp(name, "margin") == 0) {
if (parse_margin(value, &output_config->margin) == false) {
wob_log_error("Margin must be in format <value> or <value_top> <value_right> <value_bottom> <value_left>.");
return 0;
}
return 1;
}
if (strcmp(name, "anchor") == 0) {
if (parse_anchor(value, &ul) == false) {
wob_log_error("Anchor must be one of 'top', 'bottom', 'left', 'right', 'center'.");
return 0;
}
output_config->anchor = ul;
return 1;
}

Expand All @@ -339,7 +377,11 @@ handler(void *user, const char *section, const char *name, const char *value)

struct wob_style *style = wob_config_find_style(config, style_name);
if (style == NULL) {
style = malloc(sizeof(struct wob_style));
style = calloc(1, sizeof(struct wob_style));
if (style == NULL) {
wob_log_panic("calloc() failed");
}

style->name = strdup(style_name);
style->colors = config->default_style.colors;
style->overflow_colors = config->default_style.overflow_colors;
Expand Down Expand Up @@ -486,6 +528,14 @@ wob_config_load(struct wob_config *config, const char *config_path)
return false;
}

struct wob_output_config *output;
wl_list_for_each (output, &config->outputs, link) {
if (output->match == NULL) {
wob_log_error("Output %s is missing \"match\" property", output->id);
return false;
}
}

return true;
}

Expand Down Expand Up @@ -527,7 +577,23 @@ wob_config_debug(struct wob_config *config)

struct wob_output_config *output_config;
wl_list_for_each (output_config, &config->outputs, link) {
wob_log_debug("config.output.%s.name = %s", output_config->id, output_config->name);
wob_log_debug("config.output.%s.match = %s", output_config->id, output_config->match);
wob_log_debug("config.output.%s.margin.top = %lu", output_config->id, output_config->margin.top);
wob_log_debug("config.output.%s.margin.right = %lu", output_config->id, output_config->margin.right);
wob_log_debug("config.output.%s.margin.bottom = %lu", output_config->id, output_config->margin.bottom);
wob_log_debug("config.output.%s.margin.left = %lu", output_config->id, output_config->margin.left);
wob_log_debug("config.output.%s.dimensions.width = %lu", output_config->id, output_config->dimensions.width);
wob_log_debug("config.output.%s.dimensions.height = %lu", output_config->id, output_config->dimensions.height);
wob_log_debug("config.output.%s.dimensions.border_offset = %lu", output_config->id, output_config->dimensions.border_offset);
wob_log_debug("config.output.%s.dimensions.border_size = %lu", output_config->id, output_config->dimensions.border_size);
wob_log_debug("config.output.%s.dimensions.bar_padding = %lu", output_config->id, output_config->dimensions.bar_padding);
wob_log_debug(
"config.output.%s.dimensions.orientation = %lu (horizontal = %d, vertical = %d)",
output_config->id,
output_config->dimensions.orientation,
WOB_ORIENTATION_HORIZONTAL,
WOB_ORIENTATION_VERTICAL
);
}
}

Expand All @@ -536,7 +602,7 @@ wob_config_destroy(struct wob_config *config)
{
struct wob_output_config *output, *output_tmp;
wl_list_for_each_safe (output, output_tmp, &config->outputs, link) {
free(output->name);
free(output->match);
free(output->id);
free(output);
}
Expand Down Expand Up @@ -591,12 +657,12 @@ wob_config_find_output(struct wob_config *config, const char *output_id)
}

struct wob_output_config *
wob_config_find_output_by_name(struct wob_config *config, const char *output_name)
wob_config_match_output(struct wob_config *config, const char *match)
{
struct wob_output_config *output_config = NULL;
bool output_found = false;
wl_list_for_each (output_config, &config->outputs, link) {
if (strcmp(output_config->name, output_name) == 0) {
if (strstr(output_config->match, match) == 0) {
output_found = true;
break;
}
Expand All @@ -609,3 +675,48 @@ wob_config_find_output_by_name(struct wob_config *config, const char *output_nam
return NULL;
}
}

uint32_t
scale_apply(uint32_t base, uint32_t scale)
{
return base * (scale / 120.);
}

struct wob_dimensions
wob_dimensions_apply_scale(struct wob_dimensions dimensions, uint32_t scale)
{
struct wob_dimensions scaled_dimensions = {
.width = scale_apply(dimensions.width, scale),
.height = scale_apply(dimensions.height, scale),
.bar_padding = scale_apply(dimensions.bar_padding, scale),
.border_offset = scale_apply(dimensions.border_offset, scale),
.border_size = scale_apply(dimensions.border_size, scale),
.orientation = dimensions.orientation,
};

return scaled_dimensions;
}

bool
wob_dimensions_eq(struct wob_dimensions a, struct wob_dimensions b)
{
if (a.height != b.height) return false;
if (a.width != b.width) return false;
if (a.orientation != b.orientation) return false;
if (a.border_offset != b.border_offset) return false;
if (a.border_size != b.border_size) return false;
if (a.bar_padding != b.bar_padding) return false;

return true;
}

bool
wob_margin_eq(struct wob_margin a, struct wob_margin b)
{
if (a.top != b.top) return false;
if (a.right != b.right) return false;
if (a.bottom != b.bottom) return false;
if (a.left != b.left) return false;

return true;
}
31 changes: 20 additions & 11 deletions src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,22 @@ struct wob_margin {
unsigned long left;
};

struct wob_dimensions {
unsigned long width;
unsigned long height;
unsigned long border_offset;
unsigned long border_size;
unsigned long bar_padding;
enum wob_orientation orientation;
};

struct wob_output_config {
char *id;
char *name;
char *match;
struct wl_list link;
struct wob_dimensions dimensions;
struct wob_margin margin;
unsigned long anchor;
};

struct wob_colors {
Expand All @@ -56,15 +68,6 @@ struct wob_style {
struct wl_list link;
};

struct wob_dimensions {
unsigned long width;
unsigned long height;
unsigned long border_offset;
unsigned long border_size;
unsigned long bar_padding;
enum wob_orientation orientation;
};

struct wob_config {
unsigned long max;
unsigned long timeout_msec;
Expand Down Expand Up @@ -93,6 +96,12 @@ struct wob_style *wob_config_find_style(struct wob_config *config, const char *s

struct wob_output_config *wob_config_find_output(struct wob_config *config, const char *output_id);

struct wob_output_config *wob_config_find_output_by_name(struct wob_config *config, const char *output_name);
struct wob_output_config *wob_config_match_output(struct wob_config *config, const char *match);

struct wob_dimensions wob_dimensions_apply_scale(struct wob_dimensions dimensions, uint32_t scale);

bool wob_dimensions_eq(struct wob_dimensions a, struct wob_dimensions b);

bool wob_margin_eq(struct wob_margin a, struct wob_margin b);

#endif
Loading

0 comments on commit bd646ba

Please sign in to comment.