Created
July 16, 2025 19:14
-
-
Save bynect/58448cb94ca6c3c596525b916d7c4993 to your computer and use it in GitHub Desktop.
Simple bar for Xorg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <signal.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <xcb/xcb.h> | |
#include <xcb/xcb_aux.h> | |
#include <xcb/xcb_icccm.h> | |
#include <xcb/xcb_ewmh.h> | |
#include <cairo.h> | |
#include <cairo-xcb.h> | |
#include <math.h> | |
typedef struct { | |
int width, height; | |
int x, y; | |
int screen_n; | |
xcb_screen_t *scr; | |
xcb_connection_t *connection; | |
xcb_ewmh_connection_t ewmh; | |
xcb_drawable_t win; | |
unsigned int white; | |
xcb_visualtype_t *visual_type; | |
cairo_t *cr; | |
cairo_surface_t *surface; | |
} Bar; | |
#define MARGIN_LEFT 0.5 | |
#define MARGIN_RIGHT 0.5 | |
#define MARGIN_TOP 0.2 | |
#define HEIGHT_PERC 2 | |
#define CALC_PERC(tot, perc) (((tot)*(perc))/100) | |
void bar_create(Bar *bar) { | |
xcb_screen_iterator_t iter; | |
xcb_depth_iterator_t depth_iter; | |
bar->connection = xcb_connect(NULL, &bar->screen_n); | |
iter = xcb_setup_roots_iterator(xcb_get_setup(bar->connection)); | |
for (; iter.rem; --bar->screen_n, xcb_screen_next(&iter)) { | |
if (bar->screen_n == 0) { | |
bar->scr = iter.data; | |
break; | |
} | |
} | |
printf("screen.width: %d, screen.height: %d\n", bar->scr->width_in_pixels, bar->scr->height_in_pixels); | |
bar->width = bar->scr->width_in_pixels \ | |
- CALC_PERC(bar->scr->width_in_pixels, MARGIN_LEFT) \ | |
- CALC_PERC(bar->scr->width_in_pixels, MARGIN_RIGHT); | |
bar->height = CALC_PERC(bar->scr->height_in_pixels, HEIGHT_PERC); | |
printf("bar.width: %d, bar.height: %d\n", bar->width, bar->height); | |
bar->x = CALC_PERC(bar->scr->width_in_pixels, MARGIN_LEFT); | |
bar->y = CALC_PERC(bar->scr->height_in_pixels, MARGIN_TOP); | |
printf("bar.x: %d, bar.y: %d\n", bar->x, bar->y); | |
bar->win = xcb_generate_id(bar->connection); | |
bar->white = bar->scr->black_pixel; | |
xcb_create_window(bar->connection, XCB_COPY_FROM_PARENT, | |
bar->win, bar->scr->root, | |
bar->x, bar->y, | |
bar->width, bar->height, | |
5, | |
XCB_WINDOW_CLASS_INPUT_OUTPUT, | |
bar->scr->root_visual, | |
XCB_CW_BACK_PIXEL, | |
&bar->white); | |
xcb_map_window(bar->connection, bar->win); | |
xcb_flush(bar->connection); | |
xcb_size_hints_t hints; | |
xcb_icccm_size_hints_set_min_size(&hints, bar->width, bar->height); | |
xcb_icccm_size_hints_set_max_size(&hints, bar->width, bar->height); | |
xcb_icccm_size_hints_set_max_size(&hints, bar->width, bar->height); | |
xcb_icccm_size_hints_set_position(&hints, 1, bar->x, bar->y); | |
xcb_icccm_set_wm_size_hints(bar->connection, bar->win, XCB_ATOM_WM_NORMAL_HINTS, &hints); | |
xcb_icccm_set_wm_name(bar->connection, bar->win, XCB_ATOM_STRING, 8, strlen("bar"), "bar"); | |
xcb_ewmh_init_atoms(bar->connection, &bar->ewmh); | |
xcb_ewmh_set_wm_window_type(&bar->ewmh, bar->win, 1, &bar->ewmh._NET_WM_WINDOW_TYPE_DOCK); | |
xcb_flush(bar->connection); | |
depth_iter = xcb_screen_allowed_depths_iterator(bar->scr); | |
for (; depth_iter.rem; xcb_depth_next(&depth_iter)) { | |
xcb_visualtype_iterator_t visual_iter; | |
visual_iter = xcb_depth_visuals_iterator(depth_iter.data); | |
for (; visual_iter.rem; xcb_visualtype_next(&visual_iter)) { | |
if (bar->scr->root_visual == visual_iter.data->visual_id) { | |
bar->visual_type = visual_iter.data; | |
goto visual_found; | |
} | |
} | |
} | |
visual_found: ; | |
bar->surface = cairo_xcb_surface_create(bar->connection, bar->win, bar->visual_type, bar->width, bar->height); | |
bar->cr = cairo_create(bar->surface); | |
//cairo_select_font_face(bar->cr, "Hack", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); | |
//cairo_set_font_size(bar->cr, 12.0); | |
//cairo_set_source_rgb(bar->cr, 1.0, 1.0, 1.0); | |
//cairo_move_to(bar->cr, 10.0, 50.0); | |
//cairo_show_text(bar->cr, "Hello, world"); | |
double x = 0; | |
double y = 0; | |
double width = bar->width; | |
double height = bar->height; | |
double aspect = 1.0; | |
double corner_radius = height / 10; | |
double radius = corner_radius / aspect; | |
double degrees = M_PI / 180.0; | |
cairo_new_sub_path(bar->cr); | |
cairo_arc(bar->cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees); | |
cairo_arc(bar->cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees); | |
cairo_arc(bar->cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees); | |
cairo_arc(bar->cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees); | |
cairo_close_path(bar->cr); | |
cairo_set_source_rgb(bar->cr, 0.5, 0.5, 0.5); | |
cairo_fill_preserve(bar->cr); | |
cairo_set_source_rgba(bar->cr, 0.5, 0, 0, 0.5); | |
cairo_set_line_width(bar->cr, 10.0); | |
cairo_stroke(bar->cr); | |
cairo_surface_flush(bar->surface); | |
xcb_flush(bar->connection); | |
} | |
void bar_destroy(Bar *bar) { | |
cairo_destroy(bar->cr); | |
cairo_surface_destroy(bar->surface); | |
xcb_disconnect(bar->connection); | |
} | |
static volatile int keep_going = 1; | |
void handle_sig(int no) | |
{ | |
keep_going = 0; | |
} | |
int main() { | |
Bar bar; | |
bar_create(&bar); | |
signal(SIGINT, handle_sig); | |
while (keep_going) { | |
sleep(1); | |
printf("heartbeat elapsed\n"); | |
} | |
bar_destroy(&bar); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment