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)
sl Switches to the leftmost screen (the first)
```
Clickable areas can be defined with \\ab text \\ac command \\ae.

156
bar.c
View File

@ -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);

View File

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