From: "David De La Harpe Golden" <david.delaharpe.golden@gmail.com>
To: rms@gnu.org, emacs-devel@gnu.org
Subject: Re: Improving X selection?
Date: Sun, 3 Feb 2008 11:38:19 +0000 [thread overview]
Message-ID: <8e24944a0802030338i1ce3397yba581ffedbe2f118@mail.gmail.com> (raw)
In-Reply-To: <8e24944a0802011617k66c49283id9478dc3d5168bdf@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2788 bytes --]
On 02/02/2008, David De La Harpe Golden wrote:
> (Some mouse.el interactions need additional options too I think - yet
> another mail to follow with them...)
See attached patch (n.b. depends on previously sent patch
"enhanced-x-selection.diff", guess l should do an aggregate patch with
all proposed stuff...)
Goal here was mouse behaviour that fits in nicely with
select-active-regions, three main issues (one for each button as it
happens...):
*** 1. mouse-set-point vs. select-active-regions issue:
Add a deactivate-mark in mouse-set-point: This prevents copying
different text than expected to primary when select-active-regions is
true and you mouse-1 click to move the point (otherwise it ends up
setting the X11 selection to the region between the mark and new place
you clicked, which is not right).
However blindly deactivating the mark when the mouse is used to set
the point may be a bit too heavy-handed/sweeping, there may be
subtleties I haven't spotted?
*** 2. mouse-save-then-kill-copy-region:
Similar to mouse-drag-copy-region, only for mouse-3 clicks rather than
mouse-1 drags: allows mouse-save-then-kill to possibly:
nil => merely adjust active region
t => original behaviour: single-click: save double-click: kill.
:double => require "one more click" over original behaviour, i
.e. single click just for adjustment of region, double-click for kill
ring save, and triple click for kill.
Note that while select-active-regions is on, adjusting the active
region might set the primary x11 selection, and if
mouse-save-then-kill does interact with the kill ring, it might
(indirectly) set the clipboard x11 selection via the
interprogram-cut-function called by the kill routines.
Not hugely happy with my ad-hoc changes to mouse-save-then-kill code
to add this, I guess the function could be rewritten more clearly, but
at least the "nil" new behaviour is need for mouse interaction to be
unsurprising when select-active-region is on, and I then just thought
the :double behaviour was a useful option to add.
*** 3. mouse-yank-at-click-action,
introduces X11-like lightweight insert operation, allows mouse-2
mouse-yank-at-click to possibly just paste in a selection from
(introduced) interprogram-lightins-function (*) rather than yanking
from kill ring.
x-select-enable-[primary|clipboard|cutbuffer] customizations also expanded,
added a fourth kind of operation, :lightins, to go with the X11
interprogram-lightins-function, that is to say
x-cut-buffer-or-selection-value-for-lightins
* interprogram-[cut|paste]-function and
interprogram-[highlight|lightins]-function are notionally paired. (Of
course in another sense cut/highlight being output from emacs
functions and paste/lightins being input to emacs functions make
pairs), yay for symmetry.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: mouse-behaviours-nice-with-select-active-regions.diff --]
[-- Type: text/x-diff; name=mouse-behaviours-nice-with-select-active-regions.diff, Size: 25536 bytes --]
diff -NarU10 emacs-fsar/lisp/mouse.el emacs/lisp/mouse.el
--- emacs-fsar/lisp/mouse.el 2008-02-02 02:07:23.000000000 +0000
+++ emacs/lisp/mouse.el 2008-02-03 11:34:47.000000000 +0000
@@ -653,24 +653,27 @@
;; window too thin.
(if (< (- x left -1) window-min-width)
(setq x (+ left window-min-width -1)))
;; compute size change needed
(setq growth (- x right -1))
(condition-case nil
(adjust-window-trailing-edge window growth t)
(error nil))))))))))
\f
(defun mouse-set-point (event)
- "Move point to the position clicked on with the mouse.
+ "Move point to the position clicked on with the mouse, deactivating
+region beforehand.
This should be bound to a mouse click event type."
(interactive "e")
(mouse-minibuffer-check event)
+ ; select-active-regions is misleading unless this happens
+ (deactivate-mark)
;; Use event-end in case called from mouse-drag-region.
;; If EVENT is a click, event-end and event-start give same value.
(posn-set-point (event-end event)))
(defvar mouse-last-region-beg nil)
(defvar mouse-last-region-end nil)
(defvar mouse-last-region-tick nil)
(defun mouse-region-match ()
"Return non-nil if there's an active region that was set with the mouse."
@@ -1349,34 +1352,57 @@
The text is saved in the kill ring, as with \\[kill-region]."
(interactive "e")
(mouse-minibuffer-check click)
(let* ((posn (event-start click))
(click-posn (posn-point posn)))
(select-window (posn-window posn))
(if (numberp click-posn)
(kill-region (min (point) click-posn)
(max (point) click-posn)))))
+(defcustom mouse-yank-at-click-action :lightins
+ "Whether mouse-yank-at-click should do a real `yank'
+or use `interprogram-lightins-function' to try an X11-middlebutton-style
+sort of insert.
+
+Yank: a kill-ring yank, which may in turn call `interprogram-paste-function'
+
+LightIns: Call `interprogram-lightins-function', do not use kill ring"
+
+ :type '(choice (const :tag "LightIns" :lightins)
+ (const :tag "Yank" :yank))
+ :group 'mouse)
+
(defun mouse-yank-at-click (click arg)
- "Insert the last stretch of killed text at the position clicked on.
+ "Insert the last stretch of killed text as if by \\[yank] at the
+ position clicked on, if `mouse-yank-at-click-action' is yank.
+
+If `mouse-yank-at-click-action' is lightins insert text
+returned by `interprogram-lightins-function' without
+involving kill ring.
+
Also move point to one end of the text thus inserted (normally the end),
and set mark at the beginning.
Prefix arguments are interpreted as with \\[yank].
If `mouse-yank-at-point' is non-nil, insert at point
regardless of where you click."
(interactive "e\nP")
;; Give temporary modes such as isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
(or mouse-yank-at-point (mouse-set-point click))
- (setq this-command 'yank)
(setq mouse-selection-click-count 0)
- (yank arg))
+ (cond ((eq mouse-yank-at-click-action :lightins)
+ (and interprogram-lightins-function
+ (insert (funcall 'interprogram-lightins-function))))
+ (t
+ (setq this-command 'yank)
+ (yank arg))))
(defun mouse-yank-primary (click)
"Insert the primary selection at the position clicked on.
Move point to the end of the inserted text.
If `mouse-yank-at-point' is non-nil, insert at point
regardless of where you click."
(interactive "e")
;; Give temporary modes such as isearch a chance to turn off.
(run-hooks 'mouse-leave-buffer-hook)
(or mouse-yank-at-point (mouse-set-point click))
@@ -1429,83 +1455,134 @@
(let ((tail buffer-undo-list))
;; Search back in buffer-undo-list for the string
;; that came from deleting one character.
(while (and tail (not (stringp (car (car tail)))))
(setq tail (cdr tail)))
;; Replace it with an entry for the entire deleted text.
(and tail
(setcar tail (cons (car kill-ring) (min beg end))))))
(undo-boundary))
+(defcustom mouse-save-then-kill-copy-region :double
+ "How should mouse-save-then-kill save then kill?
+Never: only adjust active region, never kill.
+Single: save on single click, kill on second click
+Double: adjust active region on first click, save
+on second, kill on third"
+
+:type '(choice (const :tag "Never" nil)
+ (const :tag "Single" t)
+ (const :tag "Double" :double))
+:group 'mouse)
+
+
+
(defun mouse-save-then-kill (click)
"Save text to point in kill ring; the second time, kill the text.
+
+Behaviour depends on `mouse-save-then-kill-copy-region'. If that
+is nil, clicking merely adjusts the region. If :double, single
+clicking adjusts the region, double clicking saves text to kill
+ring, triple clicking kills the text. If nil,
+single clicking saves text to kill ring, double clicking kills.
+
If the text between point and the mouse is the same as what's
at the front of the kill ring, this deletes the text.
Otherwise, it adds the text to the kill ring, like \\[kill-ring-save],
which prepares for a second click to delete the text.
If you have selected words or lines, this command extends the
selection through the word or line clicked on. If you do this
again in a different position, it extends the selection again.
-If you do this twice in the same position, the selection is killed."
+If you do this twice (or three times if :double) in the same
+position, the selection is killed.
+"
(interactive "e")
(let ((before-scroll
(with-current-buffer (window-buffer (posn-window (event-start click)))
point-before-scroll)))
(mouse-minibuffer-check click)
(let ((click-posn (posn-point (event-start click)))
;; Don't let a subsequent kill command append to this one:
;; prevent setting this-command to kill-region.
(this-command this-command))
(if (and (with-current-buffer
(window-buffer (posn-window (event-start click)))
(and (mark t) (> (mod mouse-selection-click-count 3) 0)
;; Don't be fooled by a recent click in some other buffer.
(eq mouse-selection-click-count-buffer
(current-buffer)))))
+ ;; moving by words/lines
(if (not (and (eq last-command 'mouse-save-then-kill)
(equal click-posn
(car (cdr-safe (cdr-safe mouse-save-then-kill-posn))))))
;; Find both ends of the object selected by this click.
(let* ((range
(mouse-start-end click-posn click-posn
mouse-selection-click-count)))
;; Move whichever end is closer to the click.
;; That's what xterm does, and it seems reasonable.
(if (< (abs (- click-posn (mark t)))
(abs (- click-posn (point))))
(set-mark (car range))
(goto-char (nth 1 range)))
- ;; We have already put the old region in the kill ring.
- ;; Replace it with the extended region.
- ;; (It would be annoying to make a separate entry.)
- (kill-new (buffer-substring (point) (mark t)) t)
+
+ (cond ((eq mouse-save-then-kill-copy-region t) ; save on first click
+ ;; We have already put the old region in the kill ring.
+ ;; Replace it with the extended region.
+ ;; (It would be annoying to make a separate entry.)
+ (kill-new (buffer-substring (point) (mark t)) t)
+ ;; Arrange for a repeated mouse-3 to kill this region.
+ (setq mouse-save-then-kill-posn
+ (list (car kill-ring) (point) click-posn)))
+ ((eq mouse-save-then-kill-copy-region :double) ; no save on first click
+ ;; no save on first click, but need to know region from first
+ ;; nil for saved kill ring top used to indicate limbo between second and third clicks
+ (setq mouse-save-then-kill-posn
+ (list nil (point) click-posn))))
(mouse-set-region-1)
- ;; Arrange for a repeated mouse-3 to kill this region.
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn))
(mouse-show-mark))
- ;; If we click this button again without moving it,
- ;; that time kill.
- (mouse-save-then-kill-delete-region (mark) (point))
- (setq mouse-selection-click-count 0)
- (setq mouse-save-then-kill-posn nil))
- (if (and (eq last-command 'mouse-save-then-kill)
+ (cond ((eq mouse-save-then-kill-copy-region t) ; kill on second click
+ ;; If we click this button again without moving it,
+ ;; that time kill.
+ (mouse-save-then-kill-delete-region (mark) (point))
+ (setq mouse-selection-click-count 0)
+ (setq mouse-save-then-kill-posn nil))
+ ((eq mouse-save-then-kill-copy-region :double) ;save on second/kill on third
+ (if (car-safe mouse-save-then-kill-posn) ; kill on third
+ (progn
+ (mouse-save-then-kill-delete-region (mark) (point))
+ (setq mouse-selection-click-count 0)
+ (setq mouse-save-then-kill-posn nil))
+ (progn ; save on second
+ (kill-new (buffer-substring (point) (mark t)) t)
+ (setq mouse-save-then-kill-posn
+ (list (car kill-ring) (point) click-posn)))))))
+ ;; moving by chars
+ (if (and (eq last-command 'mouse-save-then-kill)
mouse-save-then-kill-posn
- (eq (car mouse-save-then-kill-posn) (car kill-ring))
- (equal (cdr mouse-save-then-kill-posn) (list (point) click-posn)))
- ;; If this is the second time we've called
- ;; mouse-save-then-kill, delete the text from the buffer.
- (progn
- (mouse-save-then-kill-delete-region (point) (mark))
- ;; After we kill, another click counts as "the first time".
- (setq mouse-save-then-kill-posn nil))
+ (equal (cdr-safe mouse-save-then-kill-posn) (list (point) click-posn)))
+ (cond ((eq mouse-save-then-kill-copy-region t) ; kill on second click
+ ;; If this is the second time we've called
+ ;; mouse-save-then-kill, delete the text from the buffer.
+ (mouse-save-then-kill-delete-region (point) (mark))
+ ;; After we kill, another click counts as "the first time".
+ (setq mouse-save-then-kill-posn nil))
+ ((eq mouse-save-then-kill-copy-region :double) ; save on second / kill on third
+ (if (car-safe mouse-save-then-kill-posn) ; kill on third
+ (progn
+ (mouse-save-then-kill-delete-region (point) (mark))
+ (setq mouse-save-then-kill-posn nil))
+ (progn ; save on second
+ (kill-new (buffer-substring (point) (mark t)) t)
+ (setq mouse-save-then-kill-posn
+ (list (car kill-ring) (point) click-posn))))))
;; This is not a repetition.
;; We are adjusting an old selection or creating a new one.
(if (or (and (eq last-command 'mouse-save-then-kill)
mouse-save-then-kill-posn)
(and mark-active transient-mark-mode)
(and (memq last-command
'(mouse-drag-region mouse-set-region))
(or mark-even-if-inactive
(not transient-mark-mode))))
;; We have a selection or suitable region, so adjust it.
@@ -1513,31 +1590,39 @@
(new (posn-point posn)))
(select-window (posn-window posn))
(if (numberp new)
(progn
;; Move whichever end of the region is closer to the click.
;; That is what xterm does, and it seems reasonable.
(if (<= (abs (- new (point))) (abs (- new (mark t))))
(goto-char new)
(set-mark new))
(setq deactivate-mark nil)))
- (kill-new (buffer-substring (point) (mark t)) t))
+ (and (eq mouse-save-then-kill-copy-region t) ; save on first click
+ (kill-new (buffer-substring (point) (mark t)) t)))
;; Set the mark where point is, then move where clicked.
(mouse-set-mark-fast click)
(if before-scroll
(goto-char before-scroll))
(exchange-point-and-mark) ;Why??? --Stef
- (kill-new (buffer-substring (point) (mark t))))
- (mouse-show-mark)
+ (and (eq mouse-save-then-kill-copy-region t) ; save on first click
+ (kill-new (buffer-substring (point) (mark t)))))
+ (cond ((eq mouse-save-then-kill-copy-region t) ; save on first click
+ (setq mouse-save-then-kill-posn
+ (list (car kill-ring) (point) click-posn)))
+ ((eq mouse-save-then-kill-copy-region :double) ; no save on first click
+ ;; no save on first click, but need to know region from first
+ ;; nil for saved kill ring top used to indicate limbo between second and third clicks
+ (setq mouse-save-then-kill-posn
+ (list nil (point) click-posn))))
(mouse-set-region-1)
- (setq mouse-save-then-kill-posn
- (list (car kill-ring) (point) click-posn)))))))
+ (mouse-show-mark))))))
\f
(global-set-key [M-mouse-1] 'mouse-start-secondary)
(global-set-key [M-drag-mouse-1] 'mouse-set-secondary)
(global-set-key [M-down-mouse-1] 'mouse-drag-secondary)
(global-set-key [M-mouse-3] 'mouse-secondary-save-then-kill)
(global-set-key [M-mouse-2] 'mouse-yank-secondary)
(defconst mouse-secondary-overlay
(let ((ol (make-overlay (point-min) (point-min))))
(delete-overlay ol)
diff -NarU10 emacs-fsar/lisp/simple.el emacs/lisp/simple.el
--- emacs-fsar/lisp/simple.el 2008-02-02 02:07:19.000000000 +0000
+++ emacs/lisp/simple.el 2008-02-03 04:52:54.000000000 +0000
@@ -2603,20 +2603,52 @@
system supports multiple selections. The first string will be
used as the pasted text, but the other will be placed in the
kill ring for easy access via `yank-pop'.
Note that the function should return a string only if a program other
than Emacs has provided a string for pasting; if Emacs provided the
most recent string, the function should return nil. If it is
difficult to tell whether Emacs or some other program provided the
current string, it is probably good enough to return nil if the string
is equal (according to `string=') to the last text Emacs provided.")
+
+(defvar interprogram-lightins-function nil
+ "Function to call to get text made available for highlight-insertion from other programs.
+
+Some window systems (okay one window system, X11) provide a
+facility for immediately inserting text highlighted in one program
+into another, bypassing the clipboard.
+
+This variable holds a function that Emacs calls to obtain
+text that other programs have provided for such 'lightweight
+insertion'. The convention has developed on X11
+that this lightweight highlight/insertion should be entirely
+independent from the clipboard proper.
+
+The function should be called with no arguments. If the function
+returns nil, then no other program has provided such text. If the
+function returns a string, then the caller of the function
+\(usually `mouse-yank-at-click') will insert this string
+into the buffer... without affecting the kill ring. This may
+seem slightly strange, but is intended and now typical
+behaviour on X11 desktops. If you DO want mouse-yank-at-click to
+affect the kill ring, as it has done in the past in emacs,
+adjust `mouse-yank-at-click-action' to have it use the kill
+ring \(and thereby potentially `interprogram-paste-function'), which
+on X11 at least \(the only relevant platform at the moment) can
+in turn be adjusted to pull in PRIMARY as well as or instead of
+CLIPBOARD via `x-select-enable-primary'.
+
+Note that the function should return a string if available
+whether or not a program other than Emacs provided the string,
+this is so that emacs->emacs highlight/lightins interactions
+work as expected.")
\f
;;;; The kill ring data structure.
(defvar kill-ring nil
"List of killed text sequences.
Since the kill ring is supposed to interact nicely with cut-and-paste
facilities offered by window systems, use of this variable should
interact nicely with `interprogram-cut-function' and
diff -NarU10 emacs-fsar/lisp/term/x-win.el emacs/lisp/term/x-win.el
--- emacs-fsar/lisp/term/x-win.el 2008-02-02 02:07:32.000000000 +0000
+++ emacs/lisp/term/x-win.el 2008-02-03 05:49:25.000000000 +0000
@@ -2161,66 +2161,84 @@
functions (typically something like C-x or C-c in those programs)
Highlight: Set if merely highlighting text (setting the active region)
in Emacs should immediately put it in the clipboard, if
`select-active-regions' is also set. This is unusual for recent X11
applications, typically highlighted text is placed in the PRIMARY X11
selection, for 'highlight/middlebutton' style X11 transfer.
See `x-select-enable-primary'.
It is recommended to unset `mouse-drag-copy-region' and
-set `transient-mark-mode' if Highlight is set here."
+set `transient-mark-mode' if Highlight is set here.
+
+LightIns: Set if the CLIPBOARD selection should be checked for
+lightweight insert operations \( `mouse-yank-at-click'
+with `mouse-yank-at-click-action' set to LightIns). This is not
+customary on X11, and even if you do want the middle mouse
+button (i.e. mouse-2 typically bound to mouse-yank-at-click)
+to pull in the clipboard like historic emacs, it is likely you want
+to set mouse-yank-at-click-action to Yank and set Paste here instead
+so that the Kill Ring is side-effected by the operation. Clear as mud."
:type '(choice (const :tag "None" nil)
(const :tag "All" t)
(set :tag "Choose" (const :tag "Cut/Copy" :cut)
(const :tag "Paste" :paste)
- (const :tag "Highlight" :highlight)))
+ (const :tag "Highlight" :highlight)
+ (const :tag "LightIns" :lightins)))
:group 'killing)
-(defcustom x-select-enable-primary '(:highlight)
+(defcustom x-select-enable-primary '(:highlight :lightins)
"What cut/copy/paste/highlight ops should involve PRIMARY.
In X11, PRIMARY is associated with 'highlight/middlebutton-insert' style
data interchange.
Cut/Copy: Set if Killing (e.g. C-w/M-w) in emacs should place text in the
PRIMARY X11 selection. i.e. if you want to paste killed text into other
programs on your desktop with the other programs' primary insertion
function (typically a middle-button-click). This is not usual for X11
applications, typically Cut/Copied text is placed in the CLIPBOARD X11
selection, for clipboard-style X11 transfer.
See `x-select-enable-clipboard'
Paste: Set if Yanking (e.g. C-y) in emacs should check the primary selection
for text placed there with other programs' primary selection
functions (typically highlighting the text in other X11 programs makes it
available as the primary selection). It is not usual in X11 to do so, however
it may be convenient to do so in emacs, as it reduces mousing, allowing easy
keyboard insertion of the primary selection. Note that if both
`x-select-enable-clipboard' and this have Paste set, the clipboard
-currently takes precendence when yanking.
+currently takes precendence when yanking. You might want to
+set `mouse-yank-at-click-action' to Yank if you set this, rather than
+setting LightIns here.
Highlight: Set if merely highlighting text (an active region) in emacs should
immediately put it in the primary selection, if `select-active-regions' is
set. This is usual for recent X11 programs, and allows you to insert the text
into the other program with their primary insertion function (typically
middle-button-click).
It is recommended to unset `mouse-drag-copy-region' and
-set `transient-mark-mode' if Highlight is set here."
+set `transient-mark-mode' if Highlight is set here.
+
+LightIns: Set if the PRIMARY selection should be checked for
+lightweight insert operations \( `mouse-yank-at-click'
+with `mouse-yank-at-click-action' set to LightIns). This is normal
+on X11."
:type '(choice (const :tag "None" nil)
(const :tag "All" t)
(set :tag "Choose" (const :tag "Cut/Copy" :cut)
(const :tag "Paste" :paste)
- (const :tag "Highlight" :highlight)))
+ (const :tag "Highlight" :highlight)
+ (const :tag "LightIns" :lightins)))
:group 'killing)
(defcustom x-select-enable-cutbuffer nil
"What cut/copy/paste/highlight ops shold involve legacy Cut Buffer 0.
In X, cut buffers have long been superseded by clipboard and primary
selections. However, some old X programs use them. If you
need to exchange data between emacs and such programs via
X cut buffers, you may want to set this to a non-nil value.
@@ -2229,27 +2247,32 @@
place text into X Cut Buffer 0
Paste: Set if Yanking (e.g. C-y) in Emacs should check
X Cut Buffer 0 for text.
Highlight: Set if merely highlighting text (an active region)
in emacs should immediately put it in X Cut Buffer 0, if
`select-active-regions' is also set.
It is recommended to unset `mouse-drag-copy-region' and
-set `transient-mark-mode' if Highlight is set here."
+set `transient-mark-mode' if Highlight is set here.
+
+LightIns: Set if X Cut Buffer 0 should be checked for
+lightweight insert operations \( `mouse-yank-at-click'
+with `mouse-yank-at-click-action' set to LightIns)."
:type '(choice (const :tag "None" nil)
(const :tag "All" t)
(set :tag "Choose" (const :tag "Cut/Copy" :cut)
(const :tag "Paste" :paste)
- (const :tag "Highlight" :highlight)))
+ (const :tag "Highlight" :highlight)
+ (const :tag "LightIns" :lightins)))
:group 'killing)
(defun x-select-text-for-op (op text &optional push)
"Make TEXT, a string, the primary and/or clipboard X selection.
This function matches OP against `x-select-enable-primary'
and `x-select-enable-clipboard'. OP must be one of :cut
or :highlight, corresponding to use as an `interprogram-cut-function'
or `interprogram-highlight-function'
@@ -2444,24 +2467,90 @@
;; saw multiple possible selections and ask the user which was the
;; one they wanted.
;; This code is still a big improvement because now the user can
;; futz with the current selection and get emacs to pay attention
;; to the cut buffer again (previously as soon as clipboard or
;; primary had been set the cut buffer would essentially never be
;; checked again).
(or clip-text primary-text cut-text)
)))
+
+;; Return the value of the current X selection for a "lightweight insertion"
+;; that is not intended to interact with the kill ring. No, really.
+;; Consult the selection, and the cut buffer. Treat empty strings
+;; as if they were unset.
+;; If this function is called twice and finds the same text,
+;; unlike x-cut-buffer-or-selection-value, it should return the same text.
+;; See interprogram-lightins-function docstring...
+(defun x-cut-buffer-or-selection-value-for-lightins ()
+ ;; With multi-tty, this function may be called from a tty frame.
+ (when (eq (framep (selected-frame)) 'x)
+ (let (clip-text primary-text cut-text)
+ (when (or (eq x-select-enable-clipboard t)
+ (member :lightins x-select-enable-clipboard))
+ (setq clip-text (x-selection-value 'CLIPBOARD))
+ (if (string= clip-text "") (setq clip-text nil)))
+
+ (when (or (eq x-select-enable-primary t)
+ (member :lightins x-select-enable-primary))
+ (setq primary-text (x-selection-value 'PRIMARY)))
+
+ (when (or (eq x-select-enable-cutbuffer t)
+ (member :lightins x-select-enable-cutbuffer))
+ (setq cut-text (x-get-cut-buffer 0))
+ ;; try to decode cut buffer.
+ (setq cut-text
+ (let ((next-coding (or next-selection-coding-system 'iso-latin-1)))
+ (cond ;; check cut buffer
+ ((or (not cut-text) (string= cut-text ""))
+ nil)
+ (t ;; ICCCM says cut buffer always contain ISO-Latin-1, but
+ ;; use next-selection-coding-system if not nil.
+ (decode-coding-string
+ cut-text next-coding)))))
+
+ ;; As we have done one selection, clear this now.
+ (setq next-selection-coding-system nil))
+
+ ;; At this point we have recorded the current values for the
+ ;; selection from clipboard (if we are supposed to) primary,
+ ;; and cut buffer. So return the first one that has changed
+ ;; (which is the first non-null one).
+ ;;
+ ;; NOTE: There will be cases where more than one of these has
+ ;; changed and the new values differ. This indicates that
+ ;; something like the following has happened since the last time
+ ;; we looked at the selections: Application X set all the
+ ;; selections, then Application Y set only one or two of them (say
+ ;; just the cut-buffer). In this case since we don't have
+ ;; timestamps there is no way to know what the 'correct' value to
+ ;; return is. The nice thing to do would be to tell the user we
+ ;; saw multiple possible selections and ask the user which was the
+ ;; one they wanted.
+ ;; This code is still a big improvement because now the user can
+ ;; futz with the current selection and get emacs to pay attention
+ ;; to the cut buffer again (previously as soon as clipboard or
+ ;; primary had been set the cut buffer would essentially never be
+ ;; checked again).
+ (or clip-text primary-text cut-text)
+ )))
+
+
+
+
+
;; Arrange for the kill and yank functions to set and check the clipboard.
(setq interprogram-cut-function 'x-select-text)
(setq interprogram-paste-function 'x-cut-buffer-or-selection-value)
(setq interprogram-highlight-function 'x-select-text-for-highlight)
+(setq interprogram-lightins-function 'x-cut-buffer-or-selection-value-for-lightins)
(defun x-clipboard-yank ()
"Insert the clipboard contents, or the last stretch of killed text."
(interactive "*")
(let ((clipboard-text (x-selection-value 'CLIPBOARD))
(x-select-enable-clipboard t))
(if (and clipboard-text (> (length clipboard-text) 0))
(kill-new clipboard-text))
(yank)))
next prev parent reply other threads:[~2008-02-03 11:38 UTC|newest]
Thread overview: 101+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-15 10:20 Improving X selection? Horsley, Tom
2007-10-15 11:06 ` Jan Djärv
2007-10-16 4:10 ` Richard Stallman
2007-10-16 23:29 ` David De La Harpe Golden
2007-10-17 1:05 ` David De La Harpe Golden
2007-12-25 21:13 ` Richard Stallman
2008-01-28 19:52 ` David De La Harpe Golden
2008-01-29 0:59 ` David De La Harpe Golden
2008-02-01 19:15 ` David De La Harpe Golden
2008-02-02 0:17 ` David De La Harpe Golden
2008-02-03 11:38 ` David De La Harpe Golden [this message]
2008-02-03 12:44 ` Jan D.
2008-02-03 13:12 ` David De La Harpe Golden
2008-02-04 21:02 ` David De La Harpe Golden
2008-02-05 3:38 ` David De La Harpe Golden
2008-02-05 7:08 ` Jan Djärv
2008-02-07 3:57 ` David De La Harpe Golden
2008-02-07 4:23 ` Miles Bader
2008-02-07 4:59 ` David De La Harpe Golden
2008-02-07 9:07 ` Jason Rumney
2008-02-07 16:32 ` David De La Harpe Golden
2008-02-07 17:11 ` David De La Harpe Golden
2008-02-07 17:13 ` Jason Rumney
2008-02-07 19:46 ` Stefan Monnier
2008-02-10 18:42 ` Richard Stallman
2008-02-11 17:46 ` David De La Harpe Golden
2008-02-07 17:25 ` Stefan Monnier
2008-02-07 17:39 ` David De La Harpe Golden
2008-02-07 17:51 ` David De La Harpe Golden
2008-02-07 19:54 ` Stefan Monnier
2008-02-07 15:14 ` Stefan Monnier
2008-02-07 16:15 ` David De La Harpe Golden
2008-02-07 18:01 ` Stephen J. Turnbull
2008-02-07 18:07 ` David De La Harpe Golden
2008-02-07 19:21 ` Stephen J. Turnbull
2008-02-08 1:19 ` Miles Bader
2008-02-08 1:42 ` David De La Harpe Golden
2008-02-07 18:22 ` David De La Harpe Golden
2008-02-07 19:45 ` Stefan Monnier
2008-02-07 20:39 ` David De La Harpe Golden
2008-02-07 21:25 ` Stephen J. Turnbull
2008-02-07 21:41 ` David De La Harpe Golden
2008-02-08 0:22 ` Stephen J. Turnbull
2008-02-08 1:26 ` David De La Harpe Golden
2008-02-07 22:43 ` Stefan Monnier
2008-02-08 2:50 ` David De La Harpe Golden
2008-02-08 13:26 ` OT [was Re: Improving X selection?] Tom Horsley
2008-02-08 15:30 ` David De La Harpe Golden
2008-02-08 16:07 ` OT Stefan Monnier
2008-02-08 16:43 ` OT David De La Harpe Golden
2008-02-08 14:41 ` Improving X selection? Stefan Monnier
2008-02-08 15:21 ` David De La Harpe Golden
2008-02-17 3:38 ` David De La Harpe Golden
2008-02-17 3:55 ` David De La Harpe Golden
2008-02-07 21:01 ` Tom Horsley
2008-02-07 21:18 ` David De La Harpe Golden
2008-02-07 21:36 ` Tom Horsley
2008-02-07 21:40 ` David De La Harpe Golden
2008-02-07 22:51 ` Stefan Monnier
[not found] ` <8e24944a0802071042u43d68f04pc8492ad8ce07aa18@mail.gmail.com>
2008-02-07 18:44 ` Fwd: " David De La Harpe Golden
2008-02-03 16:18 ` Richard Stallman
2008-02-03 18:29 ` David De La Harpe Golden
2008-02-05 5:58 ` David De La Harpe Golden
2008-02-05 6:23 ` Miles Bader
2008-02-05 6:56 ` David De La Harpe Golden
2008-02-03 16:18 ` Richard Stallman
-- strict thread matches above, loose matches on Subject: below --
2007-10-12 14:50 Tom Horsley
2007-10-14 16:29 ` Richard Stallman
2007-10-14 17:25 ` Jeremy Maitin-Shepard
2007-10-15 6:19 ` Jan Djärv
2007-10-15 6:21 ` Jan Djärv
2007-10-15 6:41 ` Eli Zaretskii
2007-10-15 6:55 ` Miles Bader
2007-10-15 8:16 ` Jan Djärv
2007-10-15 14:21 ` Stefan Monnier
2007-10-15 18:30 ` Richard Stallman
2007-10-15 19:26 ` Jeremy Maitin-Shepard
2007-10-15 20:03 ` Andreas Schwab
2007-10-15 20:22 ` Jeremy Maitin-Shepard
2007-10-16 8:02 ` Frank Schmitt
2007-10-16 7:27 ` Jan Djärv
2007-10-16 10:08 ` René Kyllingstad
2007-10-16 13:15 ` Stefan Monnier
2008-08-18 15:29 ` René Kyllingstad
2008-08-18 18:47 ` David De La Harpe Golden
2008-08-18 19:16 ` David Hansen
2008-08-19 8:06 ` Frank Schmitt
2008-08-25 15:34 ` Juri Linkov
2008-08-25 15:56 ` Frank Schmitt
2008-08-28 17:45 ` David De La Harpe Golden
2008-08-28 17:58 ` Frank Schmitt
2008-08-28 18:19 ` David De La Harpe Golden
2008-08-29 5:53 ` David Hansen
2008-08-30 4:08 ` David De La Harpe Golden
2008-08-31 7:41 ` David Hansen
2008-08-20 22:41 ` David De La Harpe Golden
2008-08-25 15:34 ` Juri Linkov
2008-08-26 3:09 ` David Hansen
2008-08-26 8:03 ` David De La Harpe Golden
2008-08-26 8:41 ` David Hansen
2007-10-16 7:26 ` Jan Djärv
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=8e24944a0802030338i1ce3397yba581ffedbe2f118@mail.gmail.com \
--to=david.delaharpe.golden@gmail.com \
--cc=emacs-devel@gnu.org \
--cc=rms@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.