Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add gradient borders #22

Merged
merged 4 commits into from
Nov 25, 2023
Merged
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
85 changes: 73 additions & 12 deletions src/border.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,52 @@ void border_draw(struct border* border) {

if (border->needs_redraw) {
border->needs_redraw = false;
uint32_t color = border->focused
? g_settings.active_window_color
: g_settings.inactive_window_color;

float r = ((color >> 16) & 0xff) / 255.f;
float g = ((color >> 8) & 0xff) / 255.f;
float b = ((color >> 0) & 0xff) / 255.f;
float a = ((color >> 24) & 0xff) / 255.f;
struct color_style color_style = border->focused
? g_settings.active_window
: g_settings.inactive_window;

CGGradientRef gradient = NULL;
CGPoint gradient_direction[2];
if (color_style.stype == COLOR_STYLE_SOLID) {
uint32_t color = color_style.color;
float a = ((color_style.color >> 24) & 0xff) / 255.f;
float r = ((color_style.color >> 16) & 0xff) / 255.f;
float g = ((color_style.color >> 8) & 0xff) / 255.f;
float b = ((color_style.color >> 0) & 0xff) / 255.f;
CGContextSetRGBFillColor(border->context, r, g, b, a);
CGContextSetRGBStrokeColor(border->context, r, g, b, a);
} else if (color_style.stype == COLOR_STYLE_GRADIENT) {
float a1 = ((color_style.gradient.color1 >> 24) & 0xff) / 255.f;
float a2 = ((color_style.gradient.color2 >> 24) & 0xff) / 255.f;
float r1 = ((color_style.gradient.color1 >> 16) & 0xff) / 255.f;
float r2 = ((color_style.gradient.color2 >> 16) & 0xff) / 255.f;
float g1 = ((color_style.gradient.color1 >> 8) & 0xff) / 255.f;
float g2 = ((color_style.gradient.color2 >> 8) & 0xff) / 255.f;
float b1 = ((color_style.gradient.color1 >> 0) & 0xff) / 255.f;
float b2 = ((color_style.gradient.color2 >> 0) & 0xff) / 255.f;

CGColorRef c[] = { CGColorCreateSRGB(r1, g1, b1, a1),
CGColorCreateSRGB(r2, g2, b2, a2) };
CFArrayRef cfc = CFArrayCreate(NULL,
(const void **)c,
2,
&kCFTypeArrayCallBacks);
gradient = CGGradientCreateWithColors(NULL, cfc, NULL);
CFRelease(cfc);
CGColorRelease(c[0]);
CGColorRelease(c[1]);
CGPoint point1;
CGPoint point2;
if (color_style.gradient.direction == TR_TO_BL) {
gradient_direction[0] = CGPointZero;
gradient_direction[1] = CGPointMake(frame.size.width,
frame.size.height);
} else if (color_style.gradient.direction == TL_TO_BR) {
gradient_direction[0] = CGPointMake(0, frame.size.height);
gradient_direction[1] = CGPointMake(frame.size.width, 0);
}
}

CGContextSetRGBStrokeColor(border->context, r, g, b, a);
CGContextSetRGBFillColor(border->context, r, g, b, a);
CGContextSetLineWidth(border->context, g_settings.border_width);
CGContextClearRect(border->context, frame);
CGContextSaveGState(border->context);
Expand All @@ -121,7 +156,18 @@ void border_draw(struct border* border) {

CGPathRef square_path = CGPathCreateWithRect(square_rect, NULL);
CGContextAddPath(border->context, square_path);
CGContextFillPath(border->context);

if (color_style.stype == COLOR_STYLE_SOLID) {
CGContextFillPath(border->context);
}
else if (color_style.stype == COLOR_STYLE_GRADIENT) {
CGContextClip(border->context);
CGContextDrawLinearGradient(border->context,
gradient,
gradient_direction[0],
gradient_direction[1],
0 );
}
CFRelease(square_path);
} else {
CGPathRef stroke_path = CGPathCreateWithRoundedRect(path_rect,
Expand All @@ -130,10 +176,25 @@ void border_draw(struct border* border) {
NULL );

CGContextAddPath(border->context, stroke_path);
CGContextStrokePath(border->context);

if (color_style.stype == COLOR_STYLE_SOLID) {
CGContextStrokePath(border->context);
}
else if (color_style.stype == COLOR_STYLE_GRADIENT) {
CGContextReplacePathWithStrokedPath(border->context);
CGContextClip(border->context);

CGContextDrawLinearGradient(border->context,
gradient,
gradient_direction[0],
gradient_direction[1],
0 );
}

CFRelease(stroke_path);
}
CFRelease(clip_path);
CGGradientRelease(gradient);

CGContextFlush(border->context);
CGContextRestoreGState(border->context);
Expand Down
19 changes: 17 additions & 2 deletions src/border.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,24 @@
#define BORDER_UPDATE_MASK_ALL (BORDER_UPDATE_MASK_ACTIVE \
| BORDER_UPDATE_MASK_INACTIVE)

struct gradient {
enum { TL_TO_BR, TR_TO_BL } direction;
uint32_t color1;
uint32_t color2;
};

struct color_style {
enum { COLOR_STYLE_GRADIENT, COLOR_STYLE_SOLID } stype;
union {
uint32_t color;
struct gradient gradient;
};
};

struct settings {
uint32_t active_window_color;
uint32_t inactive_window_color;
struct color_style active_window;
struct color_style inactive_window;

float border_width;
char border_style;
};
Expand Down
44 changes: 40 additions & 4 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
pid_t g_pid;
struct table g_windows;
struct mach_server g_mach_server;
struct settings g_settings = { .active_window_color = 0xffe1e3e4,
.inactive_window_color = 0xff494d64,
struct settings g_settings = { .active_window = { .stype = COLOR_STYLE_SOLID,
.color = 0xffe1e3e4 },
.inactive_window = { .stype = COLOR_STYLE_SOLID,
.color = 0xff494d64 },
.border_width = 4.f,
.border_style = BORDER_STYLE_ROUND };

Expand All @@ -35,12 +37,46 @@ static uint32_t parse_settings(struct settings* settings, int count, char** argu
for (int i = 0; i < count; i++) {
if (sscanf(arguments[i],
"active_color=0x%x",
&settings->active_window_color) == 1) {
&settings->active_window.color) == 1) {
settings->active_window.stype = COLOR_STYLE_SOLID;
update_mask |= BORDER_UPDATE_MASK_ACTIVE;
}
else if (sscanf(arguments[i],
"active_color=gradient(top_left=0x%x,bottom_right=0x%x)",
&settings->active_window.gradient.color1,
&settings->active_window.gradient.color2) == 2) {
settings->active_window.stype = COLOR_STYLE_GRADIENT;
settings->active_window.gradient.direction = TL_TO_BR;
update_mask |= BORDER_UPDATE_MASK_ACTIVE;
}
else if (sscanf(arguments[i],
"active_color=gradient(top_right=0x%x,bottom_left=0x%x)",
&settings->active_window.gradient.color1,
&settings->active_window.gradient.color2) == 2) {
settings->active_window.stype = COLOR_STYLE_GRADIENT;
settings->active_window.gradient.direction = TR_TO_BL;
update_mask |= BORDER_UPDATE_MASK_ACTIVE;
}
else if (sscanf(arguments[i],
"inactive_color=0x%x",
&settings->inactive_window_color) == 1) {
&settings->inactive_window.color) == 1) {
settings->inactive_window.stype = COLOR_STYLE_SOLID;
update_mask |= BORDER_UPDATE_MASK_INACTIVE;
}
else if (sscanf(arguments[i],
"inactive_color=gradient(top_left=0x%x,bottom_right=0x%x)",
&settings->inactive_window.gradient.color1,
&settings->inactive_window.gradient.color2) == 2) {
settings->inactive_window.stype = COLOR_STYLE_GRADIENT;
settings->inactive_window.gradient.direction = TL_TO_BR;
update_mask |= BORDER_UPDATE_MASK_INACTIVE;
}
else if (sscanf(arguments[i],
"inactive_color=gradient(top_right=0x%x,bottom_left=0x%x)",
&settings->inactive_window.gradient.color1,
&settings->inactive_window.gradient.color2) == 2) {
settings->inactive_window.stype = COLOR_STYLE_GRADIENT;
settings->inactive_window.gradient.direction = TR_TO_BL;
update_mask |= BORDER_UPDATE_MASK_INACTIVE;
}
else if (sscanf(arguments[i], "width=%f", &settings->border_width) == 1) {
Expand Down