Add mouse support

This commit is contained in:
Jurica Vukadin 2014-02-14 12:51:07 +01:00
parent 6fb75424e8
commit 372c5bf8dc
3 changed files with 163 additions and 5 deletions

View File

@ -68,3 +68,13 @@ sp Switches to previous screen
sr Switches to the rightmost screen (the latest) sr Switches to the rightmost screen (the latest)
sl Switches to the leftmost screen (the first) sl Switches to the leftmost screen (the first)
``` ```
Mouse support
-------------
You can have any number of clickable areas defined.
```
ab Begins a new clickable area
ac The command to execute when clicked
ae Ends the current clickable area
```

155
bar.c
View File

@ -34,6 +34,17 @@ typedef struct monitor_t {
struct monitor_t *prev, *next; struct monitor_t *prev, *next;
} monitor_t; } monitor_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 struct config_t { static struct config_t {
int place_bottom; int place_bottom;
int force_docking; int force_docking;
@ -66,6 +77,9 @@ static const uint32_t palette[] = {
COLOR0,COLOR1,COLOR2,COLOR3,COLOR4,COLOR5,COLOR6,COLOR7,COLOR8,COLOR9,BACKGROUND,FOREGROUND 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;
void void
set_bg (int i) set_bg (int i)
{ {
@ -130,10 +144,102 @@ draw_char (monitor_t *mon, font_t *cur_font, int x, int align, int underline, ui
return ch_width; return ch_width;
} }
void
xcb_handle_mouse_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;
}
}
void
cmd_area_begin (monitor_t *mon, 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 + mon->x;
break;
case ALIGN_C:
area->begin = mon->width / 2 + x / 2 + mon->x;
break;
case ALIGN_R:
area->begin = mon->width + mon->x;
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;
}
}
void
cmd_area_end (monitor_t *mon, int x, int align)
{
cmd_area_t *area = cmd_area_list_tail;
area->end_x = x;
switch (align) {
case ALIGN_L:
area->end = x + mon->x;
break;
case ALIGN_C:
area->begin -= (x - area->begin_x) / 2;
area->end = mon->width / 2 + x / 2 + mon->x;
/*
* 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 = mon->width + mon->x;
/*
* 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 void
parse (char *text) parse (char *text)
{ {
char *p = text; char *p = text;
char *cmd_start = 0;
int pos_x = 0; int pos_x = 0;
int align = 0; int align = 0;
@ -151,7 +257,7 @@ parse (char *text)
if (*p == '\0' || *p == '\n') if (*p == '\0' || *p == '\n')
return; return;
if (*p == '^' && p++ && *p != '^' && strchr ("_-fbulcrs", *p)) { if (*p == '^' && p++ && *p != '^' && strchr ("_-afbulcrs", *p)) {
switch (*p++) { switch (*p++) {
case 'f': case 'f':
set_fg (isdigit(*p) ? *p-'0' : 11); set_fg (isdigit(*p) ? *p-'0' : 11);
@ -214,6 +320,25 @@ parse (char *text)
align = ALIGN_R; align = ALIGN_R;
pos_x = 0; pos_x = 0;
break; break;
case 'a':
switch (*p) {
case 'b':
cmd_area_begin (cur_mon, pos_x, align);
break;
case 'c':
cmd_start = ++p;
while (*p != '\0' && *p != '\n' && *p != '^')
p++;
continue;
case 'e':
cmd_area_end (cur_mon, 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 */ } else { /* utf-8 -> ucs-2 */
uint8_t *utf = (uint8_t *)p; uint8_t *utf = (uint8_t *)p;
@ -369,7 +494,8 @@ monitor_new (int x, int y, int width, int height)
x, win_y, width, cfg.height, 0, x, win_y, width, cfg.height, 0,
XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual, XCB_WINDOW_CLASS_INPUT_OUTPUT, scr->root_visual,
XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK, XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK,
(const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE }); (const uint32_t []){ palette[10], XCB_EVENT_MASK_EXPOSURE
| XCB_EVENT_MASK_BUTTON_RELEASE });
xcb_change_window_attributes (c, ret->window, XCB_CW_OVERRIDE_REDIRECT, xcb_change_window_attributes (c, ret->window, XCB_CW_OVERRIDE_REDIRECT,
(const uint32_t []){ cfg.force_docking }); (const uint32_t []){ cfg.force_docking });
@ -621,6 +747,17 @@ init (void)
xcb_flush (c); 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 void
cleanup (void) cleanup (void)
{ {
@ -650,6 +787,8 @@ cleanup (void)
xcb_free_gc (c, underl_gc); xcb_free_gc (c, underl_gc);
if (c) if (c)
xcb_disconnect (c); xcb_disconnect (c);
clear_cmd_area_list();
} }
void void
@ -705,7 +844,7 @@ parse_font_list (char *str)
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
char input[1024] = {0, }; char input[2048] = {0, };
struct pollfd pollin[2] = { struct pollfd pollin[2] = {
{ .fd = STDIN_FILENO, .events = POLLIN }, { .fd = STDIN_FILENO, .events = POLLIN },
{ .fd = -1 , .events = POLLIN }, { .fd = -1 , .events = POLLIN },
@ -713,6 +852,7 @@ main (int argc, char **argv)
xcb_generic_event_t *ev; xcb_generic_event_t *ev;
xcb_expose_event_t *expose_ev; xcb_expose_event_t *expose_ev;
xcb_button_release_event_t *button_ev;
char ch; char ch;
while ((ch = getopt (argc, argv, "hg:bdf:a:o:p")) != -1) { while ((ch = getopt (argc, argv, "hg:bdf:a:o:p")) != -1) {
@ -764,17 +904,22 @@ main (int argc, char **argv)
if (fgets (input, sizeof(input), stdin) == NULL) if (fgets (input, sizeof(input), stdin) == NULL)
break; /* EOF received */ break; /* EOF received */
clear_cmd_area_list();
parse (input); parse (input);
redraw = 1; redraw = 1;
} }
if (pollin[1].revents & POLLIN) { /* Xserver broadcasted an event */ if (pollin[1].revents & POLLIN) { /* Xserver broadcasted an event */
while ((ev = xcb_poll_for_event (c))) { while ((ev = xcb_poll_for_event (c))) {
expose_ev = (xcb_expose_event_t *)ev;
switch (ev->response_type & 0x7F) { switch (ev->response_type & ~0x80) {
case XCB_EXPOSE: case XCB_EXPOSE:
expose_ev = (xcb_expose_event_t *)ev;
if (expose_ev->count == 0) redraw = 1; if (expose_ev->count == 0) redraw = 1;
break; break;
case XCB_BUTTON_RELEASE:
button_ev = (xcb_button_release_event_t *)ev;
if (button_ev->detail == MOUSE_BUTTON)
xcb_handle_mouse_event (button_ev->root_x);
} }
free (ev); free (ev);

View File

@ -13,3 +13,6 @@
#define COLOR8 0x425059 #define COLOR8 0x425059
#define COLOR9 0xcc6666 #define COLOR9 0xcc6666
#define FOREGROUND 0xc5c8c6 #define FOREGROUND 0xc5c8c6
/* Mouse button to react to */
#define MOUSE_BUTTON 1