From 924c84ed4be18b41790d93218e7c56d223233446 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 17 May 2014 23:27:38 -0400 Subject: basic implementation of selections still need to draw the selection, and look into how selections persist after the application is closed (cut buffers?) --- src/window-xlib.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++---- src/window-xlib.h | 1 + 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/src/window-xlib.c b/src/window-xlib.c index 6f49715..e02db3d 100644 --- a/src/window-xlib.c +++ b/src/window-xlib.c @@ -102,7 +102,7 @@ static int runes_window_backend_handle_builtin_button_press( static void runes_window_backend_start_selection( RunesTerm *t, int xpixel, int ypixel); static void runes_window_backend_stop_selection( - RunesTerm *t, int xpixel, int ypixel); + RunesTerm *t, int xpixel, int ypixel, Time time); static struct runes_loc runes_window_backend_get_mouse_position( RunesTerm *t, int xpixel, int ypixel); static void runes_window_backend_handle_expose_event( @@ -113,6 +113,10 @@ static void runes_window_backend_handle_focus_event( RunesTerm *t, XFocusChangeEvent *e); static void runes_window_backend_handle_selection_notify_event( RunesTerm *t, XSelectionEvent *e); +static void runes_window_backend_handle_selection_clear_event( + RunesTerm *t, XSelectionClearEvent *e); +static void runes_window_backend_handle_selection_request_event( + RunesTerm *t, XSelectionRequestEvent *e); void runes_window_backend_create_window(RunesTerm *t, int argc, char *argv[]) { @@ -385,6 +389,14 @@ static void runes_window_backend_process_event(uv_work_t *req, int status) runes_window_backend_handle_selection_notify_event( t, &e->xselection); break; + case SelectionRequest: + runes_window_backend_handle_selection_request_event( + t, &e->xselectionrequest); + break; + case SelectionClear: + runes_window_backend_handle_selection_clear_event( + t, &e->xselectionclear); + break; case ClientMessage: { Atom a = e->xclient.data.l[0]; if (a == w->atoms[RUNES_ATOM_WM_DELETE_WINDOW]) { @@ -796,7 +808,7 @@ static int runes_window_backend_handle_builtin_button_press( if (e->type == ButtonRelease) { switch (e->button) { case Button1: - runes_window_backend_stop_selection(t, e->x, e->y); + runes_window_backend_stop_selection(t, e->x, e->y, e->time); return 1; break; default: @@ -835,15 +847,24 @@ static void runes_window_backend_start_selection( t->scr.grid->selection_start = runes_window_backend_get_mouse_position( t, xpixel, ypixel); t->scr.grid->selection_end = t->scr.grid->selection_start; - runes_warn("started selection at (%d, %d)\n", t->scr.grid->selection_start.row, t->scr.grid->selection_start.col); } static void runes_window_backend_stop_selection( - RunesTerm *t, int xpixel, int ypixel) + RunesTerm *t, int xpixel, int ypixel, Time time) { + RunesWindowBackend *w = &t->w; + t->scr.grid->selection_end = runes_window_backend_get_mouse_position( t, xpixel, ypixel); - runes_warn("stopped selection at (%d, %d)\n", t->scr.grid->selection_end.row, t->scr.grid->selection_end.col); + + if ((t->scr.grid->selection_start.row == t->scr.grid->selection_end.row) && (t->scr.grid->selection_start.col == t->scr.grid->selection_end.col)) { + XSetSelectionOwner(w->dpy, XA_PRIMARY, None, time); + w->has_selection = 0; + } + else { + XSetSelectionOwner(w->dpy, XA_PRIMARY, w->w, time); + w->has_selection = (XGetSelectionOwner(w->dpy, XA_PRIMARY) == w->w); + } } static struct runes_loc runes_window_backend_get_mouse_position( @@ -946,3 +967,49 @@ static void runes_window_backend_handle_selection_notify_event( XFree(buf); } } + +static void runes_window_backend_handle_selection_clear_event( + RunesTerm *t, XSelectionClearEvent *e) +{ + RunesWindowBackend *w = &t->w; + + UNUSED(e); + + w->has_selection = 0; +} + +static void runes_window_backend_handle_selection_request_event( + RunesTerm *t, XSelectionRequestEvent *e) +{ + RunesWindowBackend *w = &t->w; + XSelectionEvent selection; + + selection.type = SelectionNotify; + selection.serial = e->serial; + selection.send_event = e->send_event; + selection.display = e->display; + selection.requestor = e->requestor; + selection.selection = e->selection; + selection.target = e->target; + selection.property = e->property; + selection.time = e->time; + + if (e->target == XA_STRING || e->target == w->atoms[RUNES_ATOM_UTF8_STRING]) { + char *contents; + size_t len; + + runes_screen_get_string( + t, &t->scr.grid->selection_start, &t->scr.grid->selection_end, + &contents, &len); + XChangeProperty( + w->dpy, e->requestor, e->property, + e->target, 8, PropModeReplace, + (unsigned char *)contents, len); + free(contents); + } + else { + selection.property = None; + } + + XSendEvent(w->dpy, e->requestor, False, NoEventMask, (XEvent *)&selection); +} diff --git a/src/window-xlib.h b/src/window-xlib.h index 70f7516..10d3417 100644 --- a/src/window-xlib.h +++ b/src/window-xlib.h @@ -28,6 +28,7 @@ struct runes_window { Atom atoms[RUNES_NUM_ATOMS]; char visual_bell_is_ringing: 1; + char has_selection: 1; }; typedef struct { -- cgit v1.2.3-54-g00ecf