Add mouse support

This commit is contained in:
Jurica Vukadin 2014-01-13 17:46:03 +01:00
parent cc34dab746
commit 1efcc61006
3 changed files with 154 additions and 6 deletions

View File

@ -68,3 +68,4 @@ 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)
``` ```
Clickable areas can be defined with \\ab text \\ac command \\ae.

154
bar.c
View File

@ -45,6 +45,17 @@ typedef struct screen_t {
xcb_window_t window; xcb_window_t window;
} screen_t; } 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_connection_t *c;
static xcb_drawable_t canvas; static xcb_drawable_t canvas;
static xcb_gcontext_t draw_gc; static xcb_gcontext_t draw_gc;
@ -59,11 +70,13 @@ static fontset_item_t *sel_font = NULL;
static screen_t *screens; static screen_t *screens;
static int num_screens; static int num_screens;
static const unsigned palette[] = {COLOR0,COLOR1,COLOR2,COLOR3,COLOR4,COLOR5,COLOR6,COLOR7,COLOR8,COLOR9,BACKGROUND,FOREGROUND}; 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 #if XINERAMA
static const char *control_characters = "fbulcsr"; static const char *control_characters = "afbulcsr";
#else #else
static const char *control_characters = "fbulcr"; static const char *control_characters = "afbulcr";
#endif #endif
static inline void 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 int
draw_char (screen_t *screen, int x, int align, wchar_t ch) 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; 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 void
parse (char *text) parse (char *text)
{ {
@ -150,6 +254,7 @@ parse (char *text)
int pos_x = 0; int pos_x = 0;
int align = 0; int align = 0;
char *cmd_start = 0;
screen_t *screen = &screens[0]; screen_t *screen = &screens[0];
xcb_fill_rect (clear_gc, 0, 0, bar_width, BAR_HEIGHT); xcb_fill_rect (clear_gc, 0, 0, bar_width, BAR_HEIGHT);
@ -215,6 +320,26 @@ 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 (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 */ } else { /* utf-8 -> ucs-2 */
wchar_t t; wchar_t t;
@ -356,7 +481,7 @@ set_ewmh_atoms ()
xcb_window_t xcb_window_t
create_window(xcb_window_t root, int x, int y, int width, int height, xcb_visualid_t visual) { 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_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 }); xcb_change_window_attributes (c, window, XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){ force_docking });
@ -485,6 +610,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)
{ {
@ -509,6 +645,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
@ -529,6 +667,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;
int permanent = 0; int permanent = 0;
@ -568,17 +707,22 @@ main (int argc, char **argv)
} }
if (pollin[0].revents & POLLIN) { /* New input, process it */ if (pollin[0].revents & POLLIN) { /* New input, process it */
fgets (input, sizeof(input), stdin); fgets (input, sizeof(input), stdin);
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_event (button_ev->event_x);
} }
free (ev); free (ev);

View File

@ -29,3 +29,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