diff options
-rw-r--r-- | text.c | 55 |
1 files changed, 52 insertions, 3 deletions
@@ -37,6 +37,8 @@ struct State { int width; int height; + int pointer_x; + int pointer_y; xcb_connection_t * c; xcb_screen_t * s; xcb_visualtype_t * v; @@ -50,6 +52,7 @@ enum Actions ACTION_REDRAW = 1 << 0, ACTION_ARRANGE = 1 << 1, ACTION_CLOSE = 1 << 2, + ACTION_POINTER = 1 << 3, }; struct Layout @@ -100,9 +103,9 @@ int main(int argc, const char ** argv) int actions = handle(&state, e); // Obviously, right now this may have at most one action. if (ACTION_CLOSE & actions) break; - if (ACTION_ARRANGE & actions) + if ((ACTION_ARRANGE | ACTION_POINTER) & actions) // TODO: Separate implementation for pointer. arrange(&state, &layout, body); - if (ACTION_REDRAW & actions) + if ((ACTION_REDRAW | ACTION_POINTER) & actions) draw(&state, &layout); } finalize(&state, &layout); @@ -122,7 +125,8 @@ int setup(struct State * state) const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; const uint32_t values[] = { state->s->white_pixel, - XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_STRUCTURE_NOTIFY, + XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_STRUCTURE_NOTIFY | + XCB_EVENT_MASK_POINTER_MOTION, }; xcb_create_window( state->c, XCB_COPY_FROM_PARENT, state->w, state->s->root, 0, 0, initial_width, initial_height, 0, @@ -131,6 +135,8 @@ int setup(struct State * state) state->ctx = cairo_create(state->surface); xcb_map_window(state->c, state->w); xcb_flush(state->c); + state->pointer_x = 0; + state->pointer_y = 0; return 0; } @@ -158,6 +164,13 @@ int handle(struct State * state, xcb_generic_event_t * e) case XCB_EXPOSE: actions |= ACTION_REDRAW; break; + case XCB_MOTION_NOTIFY: + ; + actions |= ACTION_POINTER; + xcb_motion_notify_event_t * motion = (xcb_motion_notify_event_t *) e; + state->pointer_x = motion->event_x; + state->pointer_y = motion->event_y; + break; case XCB_CONFIGURE_NOTIFY: ; actions |= ACTION_ARRANGE; @@ -191,6 +204,38 @@ xcb_visualtype_t * find_visual(xcb_screen_t * screen) } +PangoAttribute * find_link_under(PangoLayout * layout, PangoAttrList * attrs, int x, int y) +{ + int index; + int trailing; + int found = pango_layout_xy_to_index(layout, x * PANGO_SCALE, y * PANGO_SCALE, &index, &trailing); + PangoAttribute * attr = NULL; + if (!found) + return NULL; + PangoAttrIterator * iter = pango_attr_list_get_iterator(attrs); + for (int next = TRUE; next; next = pango_attr_iterator_next(iter)) + { + attr = pango_attr_iterator_get(iter, PANGO_ATTR_FOREGROUND); + if (NULL == attr) + continue; + int start, end; + pango_attr_iterator_range(iter, &start, &end); + if (start > index || index > end) + { + attr = NULL; + continue; + } + attr = pango_attr_foreground_new(0xffff, 0x0000, 0x0000); + attr->start_index = start; + attr->end_index = end; + goto done; + } +done: + pango_attr_iterator_destroy(iter); + return attr; +} + + void arrange(struct State * state, struct Layout * layout, union Command body[]) { if (NULL == layout->desc) @@ -224,6 +269,10 @@ void arrange(struct State * state, struct Layout * layout, union Command body[]) pango_attr_list_change(attrs, attr); break; case COMMAND_BLOCK: + ; + attr = find_link_under(layout->v[i], attrs, state->pointer_x - MARGIN, state->pointer_y - MARGIN); + if (NULL != attr) + pango_attr_list_change(attrs, attr); pango_layout_set_attributes(layout->v[i], attrs); // TODO-maybe: Don't reset everything? pango_attr_list_unref(attrs); attrs = pango_attr_list_new(); |