Add mouse support
This commit is contained in:
parent
cc34dab746
commit
1efcc61006
|
@ -68,3 +68,4 @@ sp Switches to previous screen
|
|||
sr Switches to the rightmost screen (the latest)
|
||||
sl Switches to the leftmost screen (the first)
|
||||
```
|
||||
Clickable areas can be defined with \\ab text \\ac command \\ae.
|
||||
|
|
156
bar.c
156
bar.c
|
@ -45,6 +45,17 @@ typedef struct screen_t {
|
|||
xcb_window_t window;
|
||||
} screen_t;
|
||||
|
||||
typedef struct cmd_area_t {
|
||||
struct cmd_area_t *next;
|
||||
struct cmd_area_t *prev;
|
||||
char *cmd;
|
||||
int begin;
|
||||
int end;
|
||||
int begin_x;
|
||||
int end_x;
|
||||
int align;
|
||||
} cmd_area_t;
|
||||
|
||||
static xcb_connection_t *c;
|
||||
static xcb_drawable_t canvas;
|
||||
static xcb_gcontext_t draw_gc;
|
||||
|
@ -59,11 +70,13 @@ static fontset_item_t *sel_font = NULL;
|
|||
static screen_t *screens;
|
||||
static int num_screens;
|
||||
static const unsigned palette[] = {COLOR0,COLOR1,COLOR2,COLOR3,COLOR4,COLOR5,COLOR6,COLOR7,COLOR8,COLOR9,BACKGROUND,FOREGROUND};
|
||||
static cmd_area_t *cmd_area_list_head;
|
||||
static cmd_area_t *cmd_area_list_tail;
|
||||
|
||||
#if XINERAMA
|
||||
static const char *control_characters = "fbulcsr";
|
||||
static const char *control_characters = "afbulcsr";
|
||||
#else
|
||||
static const char *control_characters = "fbulcr";
|
||||
static const char *control_characters = "afbulcr";
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
|
@ -100,6 +113,19 @@ xcb_set_fontset (int i)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
xcb_handle_event (int16_t x)
|
||||
{
|
||||
cmd_area_t *area = cmd_area_list_head;
|
||||
while (area) {
|
||||
if (area->begin <=x && area->end >= x) {
|
||||
system (area->cmd);
|
||||
return;
|
||||
}
|
||||
area = area->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
draw_char (screen_t *screen, int x, int align, wchar_t ch)
|
||||
{
|
||||
|
@ -143,6 +169,84 @@ draw_char (screen_t *screen, int x, int align, wchar_t ch)
|
|||
return ch_width;
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_area_begin (screen_t *screen, int x, int align)
|
||||
{
|
||||
cmd_area_t *area = calloc (1, sizeof (*area));
|
||||
|
||||
area->align = align;
|
||||
area->begin_x = x;
|
||||
|
||||
switch (align) {
|
||||
case ALIGN_L:
|
||||
area->begin = x;
|
||||
break;
|
||||
case ALIGN_C:
|
||||
area->begin = screen->width / 2 + x / 2;
|
||||
break;
|
||||
case ALIGN_R:
|
||||
area->begin = screen->width;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cmd_area_list_head) {
|
||||
cmd_area_list_head = area;
|
||||
cmd_area_list_tail = area;
|
||||
}
|
||||
else {
|
||||
cmd_area_list_tail->next = area;
|
||||
area->prev = cmd_area_list_tail;
|
||||
cmd_area_list_tail = area;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cmd_area_end (screen_t *screen, int x, int align)
|
||||
{
|
||||
cmd_area_t *area = cmd_area_list_tail;
|
||||
area->end_x = x;
|
||||
|
||||
switch (align) {
|
||||
case ALIGN_L:
|
||||
area->end = x;
|
||||
break;
|
||||
case ALIGN_C:
|
||||
area->begin -= (x - area->begin_x) / 2;
|
||||
area->end = screen->width / 2 + x / 2;
|
||||
/*
|
||||
* if there were any other center aligned areas
|
||||
* before this one, adjust their position
|
||||
*/
|
||||
cmd_area_t *a = area->prev;
|
||||
if (a && a->align == ALIGN_C) {
|
||||
int diff = (area->begin_x - a->end_x + area->end - area->begin) / 2;
|
||||
while (a && a->align == ALIGN_C) {
|
||||
a->begin -= diff;
|
||||
a->end -= diff;
|
||||
a = a->prev;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ALIGN_R:
|
||||
area->begin -= (x - area->begin_x);
|
||||
area->end = screen->width;
|
||||
/*
|
||||
* if there were any other right aligned areas
|
||||
* before this one, adjust their position
|
||||
*/
|
||||
a = area->prev;
|
||||
if (a && a->align == ALIGN_R) {
|
||||
int diff = area->begin_x - a->end_x + area->end - area->begin;
|
||||
while (a && a->align == ALIGN_R) {
|
||||
a->begin -= diff;
|
||||
a->end -= diff;
|
||||
a = a->prev;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
parse (char *text)
|
||||
{
|
||||
|
@ -150,6 +254,7 @@ parse (char *text)
|
|||
|
||||
int pos_x = 0;
|
||||
int align = 0;
|
||||
char *cmd_start = 0;
|
||||
screen_t *screen = &screens[0];
|
||||
|
||||
xcb_fill_rect (clear_gc, 0, 0, bar_width, BAR_HEIGHT);
|
||||
|
@ -215,6 +320,26 @@ parse (char *text)
|
|||
align = ALIGN_R;
|
||||
pos_x = 0;
|
||||
break;
|
||||
case 'a':
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
cmd_area_begin (screen, pos_x, align);
|
||||
break;
|
||||
case 'c':
|
||||
if (p++)
|
||||
cmd_start = p;
|
||||
while (p++ && *p != '\0' && *p != '\n' && *p != '\\')
|
||||
;
|
||||
continue;
|
||||
case 'e':
|
||||
cmd_area_end (screen, pos_x, align);
|
||||
size_t cmd_len = (size_t)(p - cmd_start) - 2;
|
||||
cmd_area_list_tail->cmd = calloc (cmd_len + 1, sizeof(char));
|
||||
strncpy (cmd_area_list_tail->cmd, cmd_start, cmd_len);
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
} else { /* utf-8 -> ucs-2 */
|
||||
wchar_t t;
|
||||
|
@ -356,7 +481,7 @@ set_ewmh_atoms ()
|
|||
xcb_window_t
|
||||
create_window(xcb_window_t root, int x, int y, int width, int height, xcb_visualid_t visual) {
|
||||
xcb_window_t window = xcb_generate_id(c);
|
||||
xcb_create_window(c, XCB_COPY_FROM_PARENT, window, root, x, y, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE });
|
||||
xcb_create_window(c, XCB_COPY_FROM_PARENT, window, root, x, y, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, visual, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, (const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_RELEASE });
|
||||
|
||||
xcb_change_window_attributes (c, window, XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){ force_docking });
|
||||
|
||||
|
@ -485,6 +610,17 @@ init (void)
|
|||
xcb_flush (c);
|
||||
}
|
||||
|
||||
static void
|
||||
clear_cmd_area_list (void)
|
||||
{
|
||||
while (cmd_area_list_head) {
|
||||
cmd_area_t *area = cmd_area_list_head;
|
||||
cmd_area_list_head = cmd_area_list_head->next;
|
||||
free (area->cmd);
|
||||
free (area);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cleanup (void)
|
||||
{
|
||||
|
@ -509,6 +645,8 @@ cleanup (void)
|
|||
xcb_free_gc (c, underl_gc);
|
||||
if (c)
|
||||
xcb_disconnect (c);
|
||||
|
||||
clear_cmd_area_list();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -529,6 +667,7 @@ main (int argc, char **argv)
|
|||
|
||||
xcb_generic_event_t *ev;
|
||||
xcb_expose_event_t *expose_ev;
|
||||
xcb_button_release_event_t *button_ev;
|
||||
|
||||
int permanent = 0;
|
||||
|
||||
|
@ -568,17 +707,22 @@ main (int argc, char **argv)
|
|||
}
|
||||
if (pollin[0].revents & POLLIN) { /* New input, process it */
|
||||
fgets (input, sizeof(input), stdin);
|
||||
clear_cmd_area_list();
|
||||
parse (input);
|
||||
redraw = 1;
|
||||
}
|
||||
if (pollin[1].revents & POLLIN) { /* Xserver broadcasted an event */
|
||||
while ((ev = xcb_poll_for_event (c))) {
|
||||
expose_ev = (xcb_expose_event_t *)ev;
|
||||
|
||||
switch (ev->response_type & 0x7F) {
|
||||
case XCB_EXPOSE:
|
||||
switch (ev->response_type & ~0x80) {
|
||||
case XCB_EXPOSE:
|
||||
expose_ev = (xcb_expose_event_t *)ev;
|
||||
if (expose_ev->count == 0) redraw = 1;
|
||||
break;
|
||||
case XCB_BUTTON_RELEASE:
|
||||
button_ev = (xcb_button_release_event_t *)ev;
|
||||
if (button_ev->detail == MOUSE_BUTTON)
|
||||
xcb_handle_event (button_ev->event_x);
|
||||
}
|
||||
|
||||
free (ev);
|
||||
|
|
|
@ -29,3 +29,6 @@
|
|||
#define COLOR8 0x425059
|
||||
#define COLOR9 0xcc6666
|
||||
#define FOREGROUND 0xc5c8c6
|
||||
|
||||
/* Mouse button to react to */
|
||||
#define MOUSE_BUTTON 1
|
||||
|
|
Loading…
Reference in New Issue
Block a user