Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions config.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ void init_default_style(struct mako_style *style) {
style->border_radius.bottom = 0;
style->border_radius.left = 0;

style->border_cut.top = 0;
style->border_cut.right = 0;
style->border_cut.bottom = 0;
style->border_cut.left = 0;

style->border_size = 2;

#ifdef HAVE_ICONS
Expand Down Expand Up @@ -356,6 +361,11 @@ bool apply_style(struct mako_style *target, const struct mako_style *style) {
target->spec.border_radius = true;
}

if (style->spec.border_cut) {
target->border_cut = style->border_cut;
target->spec.border_cut = true;
}

if (style->spec.output) {
free(target->output);
target->output = new_output;
Expand Down Expand Up @@ -463,6 +473,10 @@ bool apply_superset_style(
target->border_radius.bottom =
max(style->border_radius.bottom, target->border_radius.bottom);
target->border_radius.left = max(style->border_radius.left, target->border_radius.left);
target->border_cut.top = max(style->border_cut.top, target->border_cut.top);
target->border_cut.right = max(style->border_cut.right, target->border_cut.right);
target->border_cut.bottom = max(style->border_cut.bottom, target->border_cut.bottom);
target->border_cut.left = max(style->border_cut.left, target->border_cut.left);
target->border_size = max(style->border_size, target->border_size);
target->icons = style->icons || target->icons;
target->max_icon_size = max(style->max_icon_size, target->max_icon_size);
Expand Down Expand Up @@ -656,6 +670,8 @@ static bool apply_style_option(struct mako_style *style, const char *name,
style->padding.right = max(style->border_radius.right, style->padding.right);
}
return spec->border_radius;
} else if (strcmp(name, "border-cut") == 0) {
return spec->border_cut = parse_directional(value, &style->border_cut);
} else if (strcmp(name, "max-visible") == 0) {
return style->spec.max_visible = parse_int(value, &style->max_visible);
} else if (strcmp(name, "output") == 0) {
Expand Down Expand Up @@ -907,6 +923,7 @@ int parse_config_arguments(struct mako_config *config, int argc, char **argv) {
{"border-size", required_argument, 0, 0},
{"border-color", required_argument, 0, 0},
{"border-radius", required_argument, 0, 0},
{"border-cut", required_argument, 0, 0},
{"progress-color", required_argument, 0, 0},
{"icons", required_argument, 0, 0},
{"icon-location", required_argument, 0, 0},
Expand Down
6 changes: 6 additions & 0 deletions doc/mako.5.scd
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,12 @@ Supported actions:

Default: 0

*border-cut*=_directional_
Set popup corner rounding style to diagonal cut if not zero. See
*DIRECTIONAL VALUES* for more information.

Default: 0

*progress-color*=[over|source] _color_
Set popup progress indicator color to _color_. See *COLOR* for more
information. To draw the progress indicator on top of the background
Expand Down
3 changes: 2 additions & 1 deletion include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ enum mako_icon_location {
// fields in the mako_style structure should have a counterpart here. Inline
// structs are also mirrored.
struct mako_style_spec {
bool width, height, outer_margin, margin, padding, border_size, border_radius, font,
bool width, height, outer_margin, margin, padding, border_size, border_radius, border_cut, font,
markup, format, text_alignment, actions, default_timeout, ignore_timeout,
icons, max_icon_size, icon_path, icon_border_radius, group_criteria_spec, invisible, history,
icon_location, max_visible, layer, output, anchor;
Expand All @@ -62,6 +62,7 @@ struct mako_style {
struct mako_directional margin;
struct mako_directional padding;
struct mako_directional border_radius;
struct mako_directional border_cut;
int32_t border_size;

bool icons;
Expand Down
56 changes: 54 additions & 2 deletions render.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,53 @@ static void set_rounded_rectangle(cairo_t *cairo, double x, double y, double wid
cairo_close_path(cairo);
}

static void set_rounded_or_cut_rectangle(cairo_t *cairo, double x, double y, double width, double height,
int scale, int radius_top_left, int radius_top_right, int radius_bottom_right, int radius_bottom_left,
int cut_top_left, int cut_top_right, int cut_bottom_right, int cut_bottom_left) {
if (width == 0 || height == 0) {
return;
}
x *= scale;
y *= scale;
width *= scale;
height *= scale;
radius_top_left *= scale;
radius_top_right *= scale;
radius_bottom_right *= scale;
radius_bottom_left *= scale;
double degrees = M_PI / 180.0;

cairo_new_sub_path(cairo);
if (cut_top_left) {
cairo_line_to(cairo, x, y + radius_top_left);
cairo_line_to(cairo, x + radius_top_left, y);
} else {
cairo_arc(cairo, x + radius_top_left, y + radius_top_left, radius_top_left, 180 * degrees, 270 * degrees);
}

if (cut_top_right) {
cairo_line_to(cairo, x + width - radius_top_right, y);
cairo_line_to(cairo, x + width, y + radius_top_right);
} else {
cairo_arc(cairo, x + width - radius_top_right, y + radius_top_right, radius_top_right, -90 * degrees, 0 * degrees);
}

if (cut_bottom_right) {
cairo_line_to(cairo, x + width, y + height - radius_bottom_right);
cairo_line_to(cairo, x + width - radius_bottom_right, y + height);
} else {
cairo_arc(cairo, x + width - radius_bottom_right, y + height - radius_bottom_right, radius_bottom_right, 0 * degrees, 90 * degrees);
}

if (cut_bottom_left) {
cairo_line_to(cairo, x + radius_bottom_left, y + height);
cairo_line_to(cairo, x, y + height - radius_bottom_left);
} else {
cairo_arc(cairo, x + radius_bottom_left, y + height - radius_bottom_left, radius_bottom_left, 90 * degrees, 180 * degrees);
}

cairo_close_path(cairo);
}
static cairo_subpixel_order_t get_cairo_subpixel_order(
enum wl_output_subpixel subpixel) {
switch (subpixel) {
Expand Down Expand Up @@ -106,6 +153,10 @@ static int render_notification(cairo_t *cairo, struct mako_state *state, struct
int radius_top_right = style->border_radius.right;
int radius_bottom_right = style->border_radius.bottom;
int radius_bottom_left = style->border_radius.left;
int cut_top_left = style->border_cut.top;
int cut_top_right = style->border_cut.right;
int cut_bottom_right = style->border_cut.bottom;
int cut_bottom_left = style->border_cut.left;
int icon_radius = style->icon_border_radius;
bool icon_vertical = style->icon_location == MAKO_ICON_LOCATION_TOP ||
style->icon_location == MAKO_ICON_LOCATION_BOTTOM;
Expand Down Expand Up @@ -217,12 +268,13 @@ static int render_notification(cairo_t *cairo, struct mako_state *state, struct
// Define the shape of the notification. The stroke is drawn centered on
// the edge of the fill, so we need to inset the shape by half the
// border_size.
set_rounded_rectangle(cairo,
set_rounded_or_cut_rectangle(cairo,
offset_x + style->border_size / 2.0,
offset_y + style->border_size / 2.0,
notif_background_width,
notif_height - style->border_size,
scale, radius_top_left, radius_top_right, radius_bottom_right, radius_bottom_left);
scale, radius_top_left, radius_top_right, radius_bottom_right, radius_bottom_left,
cut_top_left, cut_top_right, cut_bottom_right, cut_bottom_left);

// Render background, keeping the path.
set_source_u32(cairo, style->colors.background);
Expand Down