summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--text.c55
1 files changed, 52 insertions, 3 deletions
diff --git a/text.c b/text.c
index 187c301..24cfb3e 100644
--- a/text.c
+++ b/text.c
@@ -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();