summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2021-09-15 22:41:49 +0200
committerAki <please@ignore.pl>2021-09-15 22:41:49 +0200
commitd4f7d26a6179034637cb302b4850c8febd5df01a (patch)
tree81e7e909fb47c078075c19e9dd06a52cfd55c15a
parent80722aeda0df83efa844e72e44b94c2d7f676b74 (diff)
downloadtext-d4f7d26a6179034637cb302b4850c8febd5df01a.zip
text-d4f7d26a6179034637cb302b4850c8febd5df01a.tar.gz
text-d4f7d26a6179034637cb302b4850c8febd5df01a.tar.bz2
Added handler for hyperlink clicking
-rw-r--r--text.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/text.c b/text.c
index 256e804..9560edd 100644
--- a/text.c
+++ b/text.c
@@ -40,6 +40,7 @@ struct State
int height;
int pointer_x;
int pointer_y;
+ int follow; // TODO: Rethink how pointer events are handled.
xcb_connection_t * c;
xcb_screen_t * s;
xcb_visualtype_t * v;
@@ -54,6 +55,7 @@ enum Actions
ACTION_ARRANGE = 1 << 1,
ACTION_CLOSE = 1 << 2,
ACTION_POINTER = 1 << 3,
+ ACTION_CLICK = 1 << 4,
};
struct Layout
@@ -67,7 +69,7 @@ int setup(struct State *);
void finalize(struct State *, struct Layout *);
int handle(struct State *, xcb_generic_event_t *);
xcb_visualtype_t * find_visual(xcb_screen_t *);
-PangoAttribute * find_link_under(PangoLayout *, PangoAttrList *, int, int);
+PangoAttribute * find_link_under(struct State *, PangoLayout *, PangoAttrList *, int, int);
void arrange(struct State *, struct Layout *, union Command[]);
void draw(struct State *, struct Layout *);
PangoAttribute * attr_hyperlink_new(const char *);
@@ -109,7 +111,7 @@ int main(int argc, const char ** argv)
struct State state;
if (-1 == setup(&state))
{
- dprintf(2, "Could not connect to X server\n"); // TODO: Helpful (specific) errors.
+ dprintf(2, "Could not connect to X server\n");
return 1;
}
struct Layout layout = {.desc = NULL, .size = 0, .v = NULL};
@@ -120,10 +122,12 @@ 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 | ACTION_POINTER) & actions) // TODO: Separate implementation for pointer.
+ // TODO: Arranging, rearranging and (obviously) reacting to pointer events are all different things.
+ if ((ACTION_ARRANGE | ACTION_POINTER | ACTION_CLICK) & actions)
arrange(&state, &layout, body);
if ((ACTION_REDRAW | ACTION_POINTER) & actions)
draw(&state, &layout);
+ state.follow = 0;
}
finalize(&state, &layout);
}
@@ -143,7 +147,7 @@ int setup(struct State * state)
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_POINTER_MOTION,
+ XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS,
};
xcb_create_window(
state->c, XCB_COPY_FROM_PARENT, state->w, state->s->root, 0, 0, initial_width, initial_height, 0,
@@ -154,6 +158,7 @@ int setup(struct State * state)
xcb_flush(state->c);
state->pointer_x = 0;
state->pointer_y = 0;
+ state->follow = 0;
return 0;
}
@@ -188,6 +193,15 @@ int handle(struct State * state, xcb_generic_event_t * e)
state->pointer_x = motion->event_x;
state->pointer_y = motion->event_y;
break;
+ case XCB_BUTTON_PRESS:
+ break;
+ case XCB_BUTTON_RELEASE:
+ ;
+ xcb_button_release_event_t * button = (xcb_button_release_event_t *) e;
+ if (1 == button->detail)
+ state->follow = 1;
+ actions |= ACTION_CLICK;
+ break;
case XCB_CONFIGURE_NOTIFY:
;
actions |= ACTION_ARRANGE;
@@ -221,7 +235,7 @@ xcb_visualtype_t * find_visual(xcb_screen_t * screen)
}
-PangoAttribute * find_link_under(PangoLayout * layout, PangoAttrList * attrs, int x, int y)
+PangoAttribute * find_link_under(struct State * state, PangoLayout * layout, PangoAttrList * attrs, int x, int y)
{
int index;
int trailing;
@@ -245,6 +259,13 @@ PangoAttribute * find_link_under(PangoLayout * layout, PangoAttrList * attrs, in
attr = pango_attr_foreground_new(0xffff, 0x0000, 0x0000);
attr->start_index = start;
attr->end_index = end;
+ if (state->follow)
+ {
+ state->follow = 0;
+ PangoAttribute * link = pango_attr_iterator_get(iter, PANGO_CUSTOM_ATTR_HYPERLINK);
+ if (NULL != link)
+ printf("%s\n", ((PangoAttrString *) link)->value);
+ }
goto done;
}
done:
@@ -264,7 +285,7 @@ void arrange(struct State * state, struct Layout * layout, union Command body[])
if (size != layout->size)
{
for (int i = 0; i < layout->size; ++i)
- g_object_unref(layout->v[i]); /// TODO-maybe: Reuse already existing layouts of blocks.
+ g_object_unref(layout->v[i]);
layout->v = malloc(sizeof(PangoLayout *) * size);
if (NULL == layout->v)
abort(); // TODO: Be more graceful?
@@ -280,18 +301,18 @@ void arrange(struct State * state, struct Layout * layout, union Command body[])
{
case COMMAND_SPAN:
;
- PangoAttribute * attr = pango_attr_foreground_new(0x0000, 0x0000, 0xffff);
+ PangoAttribute * attr = attr_hyperlink_new(c->span.uri);
attr->start_index = c->span.start;
attr->end_index = c->span.end;
pango_attr_list_change(attrs, attr);
- attr = attr_hyperlink_new(c->span.uri);
+ attr = pango_attr_foreground_new(0x0000, 0x0000, 0xffff);
attr->start_index = c->span.start;
attr->end_index = c->span.end;
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);
+ attr = find_link_under(state, 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);