diff options
author | Po Lu <luangruo@yahoo.com> | 2022-03-16 17:03:19 +0800 |
---|---|---|
committer | Po Lu <luangruo@yahoo.com> | 2022-03-16 17:03:19 +0800 |
commit | e8d7139b4e069f4641a7e11261541acb4c5fff7b (patch) | |
tree | d70f006c6e91a65071079f374e9634b43a08bd5a | |
parent | 1babe5fb2d7575fb15e515fffd3387d60a975553 (diff) | |
download | emacs-e8d7139b4e069f4641a7e11261541acb4c5fff7b.tar.gz |
Fix minor bugs with XDND support
* lisp/mouse.el (mouse-drag-and-drop-region): Report more
selection targets for the benefit of Qt and Mozilla.
* lisp/select.el (xselect--encode-string)
(selection-converter-alist): Add new selection targets.
* src/xterm.c (x_dnd_get_window_proxy): New function.
(x_dnd_get_target_window): New argument proto_out, and return
first window with XdndAware instead of bottommost window.
(handle_one_xevent): Use new argument `proto_out'.
-rw-r--r-- | lisp/mouse.el | 4 | ||||
-rw-r--r-- | lisp/select.el | 11 | ||||
-rw-r--r-- | src/xterm.c | 116 |
3 files changed, 89 insertions, 42 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el index 4eead399252..3e7ae246975 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3100,7 +3100,9 @@ is copied instead of being cut." (x-hide-tip) (gui-set-selection 'XdndSelection value-selection) (let ((drag-action-or-frame - (x-begin-drag '("UTF8_STRING" "STRING") + (x-begin-drag '("UTF8_STRING" "text/plain" + "text/plain;charset=utf-8" + "STRING" "TEXT" "COMPOUND_TEXT") (if mouse-drag-and-drop-region-cut-when-buffers-differ 'XdndActionMove 'XdndActionCopy) diff --git a/lisp/select.el b/lisp/select.el index 42b50c44e6c..e9bc5451171 100644 --- a/lisp/select.el +++ b/lisp/select.el @@ -485,7 +485,8 @@ two markers or an overlay. Otherwise, it is nil." (if eight-bit 'C_STRING 'STRING)))))))) (cond - ((eq type 'UTF8_STRING) + ((or (eq type 'UTF8_STRING) + (eq type 'text/plain\;charset=utf-8)) (if (or (not coding) (not (eq (coding-system-type coding) 'utf-8))) (setq coding 'utf-8)) @@ -497,6 +498,12 @@ two markers or an overlay. Otherwise, it is nil." (setq coding 'iso-8859-1)) (setq str (encode-coding-string str coding))) + ((eq type 'text/plain) + (if (or (not coding) + (not (eq (coding-system-type coding) 'charset))) + (setq coding 'ascii)) + (setq str (encode-coding-string str coding))) + ((eq type 'COMPOUND_TEXT) (if (or (not coding) (not (eq (coding-system-type coding) 'iso-2022))) @@ -630,6 +637,8 @@ This function returns the string \"emacs\"." (COMPOUND_TEXT . xselect-convert-to-string) (STRING . xselect-convert-to-string) (UTF8_STRING . xselect-convert-to-string) + (text/plain . xselect-convert-to-string) + (text/plain\;charset=utf-8 . xselect-convert-to-string) (TARGETS . xselect-convert-to-targets) (LENGTH . xselect-convert-to-length) (DELETE . xselect-convert-to-delete) diff --git a/src/xterm.c b/src/xterm.c index d01d3e7cce3..83651376bfd 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -795,23 +795,21 @@ static struct frame *x_dnd_frame; #define X_DND_SUPPORTED_VERSION 5 +static int x_dnd_get_window_proto (struct x_display_info *, Window); +static Window x_dnd_get_window_proxy (struct x_display_info *, Window); + static Window x_dnd_get_target_window (struct x_display_info *dpyinfo, - int root_x, int root_y) + int root_x, int root_y, int *proto_out) { Window child_return, child, dummy, proxy; - int dest_x_return, dest_y_return; - int rc; - int actual_format; - unsigned long actual_size, bytes_remaining; - unsigned char *tmp_data; - XWindowAttributes attrs; - Atom actual_type; - + int dest_x_return, dest_y_return, rc, proto; child_return = dpyinfo->root_window; dest_x_return = root_x; dest_y_return = root_y; + proto = -1; + /* Not strictly necessary, but satisfies GCC. */ child = dpyinfo->root_window; @@ -832,8 +830,33 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, break; } + proxy = x_dnd_get_window_proxy (dpyinfo, child_return); + + if (proxy != None) + { + proto = x_dnd_get_window_proto (dpyinfo, proxy); + + if (proto != -1) + { + *proto_out = proto; + + x_uncatch_errors_after_check (); + return proxy; + } + } + if (child_return) { + proto = x_dnd_get_window_proto (dpyinfo, child_return); + + if (proto != -1) + { + *proto_out = proto; + x_uncatch_errors_after_check (); + + return child_return; + } + rc = XTranslateCoordinates (dpyinfo->display, child, child_return, dest_x_return, dest_y_return, @@ -850,36 +873,47 @@ x_dnd_get_target_window (struct x_display_info *dpyinfo, x_uncatch_errors_after_check (); } - if (child != None) - { - x_catch_errors (dpyinfo->display); - rc = XGetWindowProperty (dpyinfo->display, child, - dpyinfo->Xatom_XdndProxy, - 0, 1, False, XA_WINDOW, - &actual_type, &actual_format, - &actual_size, &bytes_remaining, - &tmp_data); - - if (!x_had_errors_p (dpyinfo->display) - && rc == Success - && actual_type == XA_WINDOW - && actual_format == 32 - && actual_size == 1) - { - proxy = *(Window *) tmp_data; - XFree (tmp_data); + *proto_out = x_dnd_get_window_proto (dpyinfo, child); + return child; +} + +static Window +x_dnd_get_window_proxy (struct x_display_info *dpyinfo, Window wdesc) +{ + int rc, actual_format; + unsigned long actual_size, bytes_remaining; + unsigned char *tmp_data; + XWindowAttributes attrs; + Atom actual_type; + Window proxy; - /* Verify the proxy window exists. */ - XGetWindowAttributes (dpyinfo->display, proxy, &attrs); + proxy = None; + x_catch_errors (dpyinfo->display); + rc = XGetWindowProperty (dpyinfo->display, wdesc, + dpyinfo->Xatom_XdndProxy, + 0, 1, False, XA_WINDOW, + &actual_type, &actual_format, + &actual_size, &bytes_remaining, + &tmp_data); - if (!x_had_errors_p (dpyinfo->display)) - child = proxy; - } + if (!x_had_errors_p (dpyinfo->display) + && rc == Success + && actual_type == XA_WINDOW + && actual_format == 32 + && actual_size == 1) + { + proxy = *(Window *) tmp_data; + XFree (tmp_data); - x_uncatch_errors_after_check (); + /* Verify the proxy window exists. */ + XGetWindowAttributes (dpyinfo->display, proxy, &attrs); + + if (x_had_errors_p (dpyinfo->display)) + proxy = None; } + x_uncatch_errors_after_check (); - return child; + return proxy; } static int @@ -11616,10 +11650,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { Window target; + int target_proto; target = x_dnd_get_target_window (dpyinfo, event->xmotion.x_root, - event->xmotion.y_root); + event->xmotion.y_root, + &target_proto); if (target != x_dnd_last_seen_window) { @@ -11643,8 +11679,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, x_dnd_wanted_action = None; x_dnd_last_seen_window = target; - x_dnd_last_protocol_version - = x_dnd_get_window_proto (dpyinfo, target); + x_dnd_last_protocol_version = target_proto; if (target != None && x_dnd_last_protocol_version != -1) x_dnd_send_enter (x_dnd_frame, target, @@ -12849,10 +12884,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, && dpyinfo == FRAME_DISPLAY_INFO (x_dnd_frame)) { Window target; + int target_proto; target = x_dnd_get_target_window (dpyinfo, xev->root_x, - xev->root_y); + xev->root_y, + &target_proto); if (target != x_dnd_last_seen_window) { @@ -12875,8 +12912,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, } x_dnd_last_seen_window = target; - x_dnd_last_protocol_version - = x_dnd_get_window_proto (dpyinfo, target); + x_dnd_last_protocol_version = target_proto; if (target != None && x_dnd_last_protocol_version != -1) x_dnd_send_enter (x_dnd_frame, target, |