From 692ff6949171ecde08828e57361660a10d69b8fc Mon Sep 17 00:00:00 2001 From: sf-exg Date: Sun, 24 Jan 2010 21:53:13 +0000 Subject: [PATCH] Add support for copying to clipboard (based on patch by Dana Jansens). --- src/command.C | 2 +- src/main.C | 2 ++ src/rxvt.h | 10 ++++-- src/rxvtperl.xs | 7 ++-- src/rxvttoolkit.C | 15 +++++---- src/rxvttoolkit.h | 3 +- src/screen.C | 82 ++++++++++++++++++++++++++++++++++++++--------- 7 files changed, 91 insertions(+), 30 deletions(-) diff --git a/src/command.C b/src/command.C index e9c2a168..60a87dbd 100644 --- a/src/command.C +++ b/src/command.C @@ -1464,7 +1464,7 @@ rxvt_term::x_cb (XEvent &ev) break; case SelectionClear: - selection_clear (); + selection_clear (ev.xselectionclear.selection == xa[XA_CLIPBOARD]); break; case SelectionNotify: diff --git a/src/main.C b/src/main.C index 88bd0e57..9d8acc69 100644 --- a/src/main.C +++ b/src/main.C @@ -239,6 +239,7 @@ rxvt_term::~rxvt_term () if (display) { selection_clear (); + selection_clear (true); #ifdef USE_XIM im_destroy (); @@ -273,6 +274,7 @@ rxvt_term::~rxvt_term () free (allocated [i]); free (selection.text); + free (selection.clip_text); // TODO: manage env vars in child only(!) free (env_display); free (env_term); diff --git a/src/rxvt.h b/src/rxvt.h index 6897414e..a8cd77c6 100644 --- a/src/rxvt.h +++ b/src/rxvt.h @@ -914,6 +914,8 @@ struct selection_t row_col_t beg; /* beginning of selection <= mark */ row_col_t mark; /* point of initial click <= end */ row_col_t end; /* one character past end point */ + wchar_t *clip_text; /* text copied to the clipboard */ + unsigned int clip_len; /* length of clipboard text */ }; /* ------------------------------------------------------------------------- */ @@ -1046,7 +1048,8 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen Atom *xa; /* ---------- */ Time selection_time, - selection_request_time; + selection_request_time, + clipboard_time; pid_t cmd_pid; /* process id of child */ char * incr_buf; size_t incr_buf_size, incr_buf_fill; @@ -1453,9 +1456,10 @@ struct rxvt_term : zero_initialized, rxvt_vars, rxvt_screen void selection_property (Window win, Atom prop) NOTHROW; void selection_request (Time tm, int selnum = Sel_Primary) NOTHROW; int selection_request_other (Atom target, int selnum) NOTHROW; - void selection_clear () NOTHROW; + void selection_clear (bool clipboard = false) NOTHROW; + void clipboard_copy (Time tm); void selection_make (Time tm); - bool selection_grab (Time tm) NOTHROW; + bool selection_grab (Time tm, bool clipboard = false) NOTHROW; void selection_start_colrow (int col, int row) NOTHROW; void selection_delimit_word (enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) NOTHROW; void selection_extend_colrow (int32_t col, int32_t row, int button3, int buttonpress, int clickchange) NOTHROW; diff --git a/src/rxvtperl.xs b/src/rxvtperl.xs index af2dfd9f..dc2e555e 100644 --- a/src/rxvtperl.xs +++ b/src/rxvtperl.xs @@ -1596,7 +1596,10 @@ rxvt_term::selection_screen (int screen = -1) RETVAL void -rxvt_term::selection_clear () +rxvt_term::selection_clear (bool clipboard = false) + +void +rxvt_term::clipboard_copy (Time eventtime) void rxvt_term::selection_make (Time eventtime, bool rect = false) @@ -1606,7 +1609,7 @@ rxvt_term::selection_make (Time eventtime, bool rect = false) THIS->selection_make (eventtime); int -rxvt_term::selection_grab (Time eventtime) +rxvt_term::selection_grab (Time eventtime, bool clipboard = false) void rxvt_term::selection (SV *newtext = 0) diff --git a/src/rxvttoolkit.C b/src/rxvttoolkit.C index 4fb4ef9a..6f999f35 100644 --- a/src/rxvttoolkit.C +++ b/src/rxvttoolkit.C @@ -299,6 +299,7 @@ rxvt_screen::clear () rxvt_display::rxvt_display (const char *id) : refcounted (id) , selection_owner (0) +, clipboard_owner (0) { x_ev .set (this); flush_ev.set (this); @@ -602,17 +603,17 @@ void rxvt_display::unreg (xevent_watcher *w) } } -void rxvt_display::set_selection_owner (rxvt_term *owner) +void rxvt_display::set_selection_owner (rxvt_term *owner, bool clipboard) { - if (selection_owner && selection_owner != owner) - { - rxvt_term *owner = selection_owner; + rxvt_term * &cur_owner = !clipboard ? selection_owner : clipboard_owner; - owner->selection_clear (); - owner->flush (); + if (cur_owner && cur_owner != owner) + { + cur_owner->selection_clear (clipboard); + cur_owner->flush (); } - selection_owner = owner; + cur_owner = owner; } #ifdef USE_XIM diff --git a/src/rxvttoolkit.h b/src/rxvttoolkit.h index 8b87e989..4f915648 100644 --- a/src/rxvttoolkit.h +++ b/src/rxvttoolkit.h @@ -237,6 +237,7 @@ struct rxvt_display : refcounted int screen; Window root; rxvt_term *selection_owner; + rxvt_term *clipboard_owner; Atom xa[NUM_XA]; bool is_local; #ifdef POINTER_BLANK @@ -255,7 +256,7 @@ struct rxvt_display : refcounted } Atom atom (const char *name); - void set_selection_owner (rxvt_term *owner); + void set_selection_owner (rxvt_term *owner, bool clipboard); void reg (xevent_watcher *w); void unreg (xevent_watcher *w); diff --git a/src/screen.C b/src/screen.C index 83717e9a..0b9ddf0e 100644 --- a/src/screen.C +++ b/src/screen.C @@ -233,6 +233,8 @@ rxvt_term::scr_reset () selection.op = SELECTION_CLEAR; selection.screen = PRIMARY; selection.clicks = 0; + selection.clip_text = NULL; + selection.clip_len = 0; } else { @@ -2946,16 +2948,42 @@ rxvt_term::selection_request_other (Atom target, int selnum) NOTHROW * EXT: SelectionClear */ void -rxvt_term::selection_clear () NOTHROW +rxvt_term::selection_clear (bool clipboard) NOTHROW { - want_refresh = 1; - free (selection.text); - selection.text = NULL; - selection.len = 0; - CLEAR_SELECTION (); + if (!clipboard) + { + want_refresh = 1; + free (selection.text); + selection.text = NULL; + selection.len = 0; + CLEAR_SELECTION (); - if (display->selection_owner == this) - display->selection_owner = 0; + if (display->selection_owner == this) + display->selection_owner = 0; + } + else + { + free (selection.clip_text); + selection.clip_text = NULL; + selection.clip_len = 0; + + if (display->clipboard_owner == this) + display->clipboard_owner = 0; + } +} + +void +rxvt_term::clipboard_copy (Time tm) +{ + if (selection.len > 0) + { + free (selection.clip_text); + selection.clip_len = selection.len; + selection.clip_text = (wchar_t *) malloc (sizeof (wchar_t) * selection.clip_len); + memcpy (selection.clip_text, selection.text, + sizeof (wchar_t) * selection.clip_len); + selection_grab (tm, true); + } } /* ------------------------------------------------------------------------- */ @@ -3091,19 +3119,30 @@ rxvt_term::selection_make (Time tm) } bool -rxvt_term::selection_grab (Time tm) NOTHROW +rxvt_term::selection_grab (Time tm, bool clipboard) NOTHROW { - selection_time = tm; + Atom sel; - XSetSelectionOwner (dpy, XA_PRIMARY, vt, tm); - if (XGetSelectionOwner (dpy, XA_PRIMARY) == vt) + if (!clipboard) + { + selection_time = tm; + sel = XA_PRIMARY; + } + else { - display->set_selection_owner (this); + clipboard_time = tm; + sel = xa[XA_CLIPBOARD]; + } + + XSetSelectionOwner (dpy, sel, vt, tm); + if (XGetSelectionOwner (dpy, sel) == vt) + { + display->set_selection_owner (this, clipboard); return true; } else { - selection_clear (); + selection_clear (clipboard); return false; } @@ -3608,12 +3647,18 @@ rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW /* TODO: Handle MULTIPLE */ } #endif - else if (rq.target == xa[XA_TIMESTAMP] && selection.text) + else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == XA_PRIMARY && selection.text) { XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 32, PropModeReplace, (unsigned char *)&selection_time, 1); ev.property = rq.property; } + else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == xa[XA_CLIPBOARD] && selection.clip_text) + { + XChangeProperty (dpy, rq.requestor, rq.property, rq.target, + 32, PropModeReplace, (unsigned char *)&clipboard_time, 1); + ev.property = rq.property; + } else if (rq.target == XA_STRING || rq.target == xa[XA_TEXT] || rq.target == xa[XA_COMPOUND_TEXT] @@ -3654,11 +3699,16 @@ rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW style = enc_compound_text; } - if (selection.text) + if (rq.selection == XA_PRIMARY && selection.text) { cl = selection.text; selectlen = selection.len; } + else if (rq.selection == xa[XA_CLIPBOARD] && selection.clip_text) + { + cl = selection.clip_text; + selectlen = selection.clip_len; + } else { cl = L""; -- 2.34.1