aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2022-07-15 16:19:41 +0800
committerPo Lu2022-07-15 16:19:52 +0800
commit200938b95d1b73d03ce758e69a69d4fb198be4e8 (patch)
tree16d187bd8747d8bed5dd84c58cef71c7b2d35498
parentffe4a5dac0dbc9fd85064200ed7b46b4ab3b910a (diff)
downloademacs-200938b95d1b73d03ce758e69a69d4fb198be4e8.tar.gz
emacs-200938b95d1b73d03ce758e69a69d4fb198be4e8.zip
Fix generated drag-and-drop mouse rectangles
* lisp/x-dnd.el (x-dnd-get-drop-width-height): Handle window width and height correctly. Remove unused parameter. (x-dnd-after-move-frame): New function. (move-frame-functions): Add new hook. (x-dnd-compute-root-window-position): New function. (x-dnd-get-drop-x-y): Use that instead of `left' and `top' parameters, which include the title bar. (x-dnd-handle-xdnd): Update accordingly. * src/xfns.c (Fx_translate_coordinates): New function. (syms_of_xfns): New defsym.
-rw-r--r--lisp/x-dnd.el48
-rw-r--r--src/xfns.c88
2 files changed, 122 insertions, 14 deletions
diff --git a/lisp/x-dnd.el b/lisp/x-dnd.el
index 92899e7a0c6..b25d2ea3d9d 100644
--- a/lisp/x-dnd.el
+++ b/lisp/x-dnd.el
@@ -588,6 +588,7 @@ message (format 32) that caused EVENT to be generated."
588 588
589(declare-function x-change-window-property "xfns.c" 589(declare-function x-change-window-property "xfns.c"
590 (prop value &optional frame type format outer-P window-id)) 590 (prop value &optional frame type format outer-P window-id))
591(declare-function x-translate-coordinates "xfns.c")
591 592
592(defun x-dnd-init-xdnd-for-frame (frame) 593(defun x-dnd-init-xdnd-for-frame (frame)
593 "Set the XdndAware property for FRAME to indicate that we do XDND." 594 "Set the XdndAware property for FRAME to indicate that we do XDND."
@@ -595,33 +596,53 @@ message (format 32) that caused EVENT to be generated."
595 '(5) ;; The version of XDND we support. 596 '(5) ;; The version of XDND we support.
596 frame "ATOM" 32 t)) 597 frame "ATOM" 32 t))
597 598
598(defun x-dnd-get-drop-width-height (frame w accept) 599(defun x-dnd-get-drop-width-height (w accept)
599 "Return the width/height to be sent in a XdndStatus message. 600 "Return the width/height to be sent in a XdndStatus message.
600FRAME is the frame and W is the window where the drop happened. 601W is the window where the drop happened.
601If ACCEPT is nil return 0 (empty rectangle), 602If ACCEPT is nil return 0 (empty rectangle),
602otherwise if W is a window, return its width/height, 603otherwise if W is a window, return its width/height,
603otherwise return the frame width/height." 604otherwise return the frame width/height."
604 (if accept 605 (if accept
605 (if (windowp w) ;; w is not a window if dropping on the menu bar, 606 (if (windowp w) ;; w is not a window if dropping on the menu bar,
606 ;; scroll bar or tool bar. 607 ;; scroll bar or tool bar.
607 (let ((edges (window-inside-pixel-edges w))) 608 (cons (window-pixel-width)
608 (cons 609 (window-pixel-height))
609 (- (nth 2 edges) (nth 0 edges)) ;; right - left 610 ;; Don't confine to mouse rect if w is not a window.
610 (- (nth 3 edges) (nth 1 edges)))) ;; bottom - top 611 ;; Otherwise, we won't get position events once the mouse does
611 (cons (frame-pixel-width frame) 612 ;; move into a window.
612 (frame-pixel-height frame))) 613 0)
613 0)) 614 0))
614 615
616(defun x-dnd-after-move-frame (frame)
617 "Handle FRAME moving to a different position.
618Clear any cached root window position."
619 (set-frame-parameter frame 'dnd-root-window-position
620 nil))
621
622(add-hook 'move-frame-functions #'x-dnd-after-move-frame)
623
624(defun x-dnd-compute-root-window-position (frame)
625 "Return the position of FRAME's edit widget relative to the root window.
626The value is a cons of (X . Y), describing the position of
627FRAME's edit widget (inner window) relative to the root window of
628its screen."
629 (or (frame-parameter frame 'dnd-root-window-position)
630 (let* ((result (x-translate-coordinates frame))
631 (param (cons (car result) (cadr result))))
632 (unless result
633 (error "Frame isn't on the same screen as its root window"))
634 (prog1 param
635 (set-frame-parameter frame 'dnd-root-window-position param)))))
636
615(defun x-dnd-get-drop-x-y (frame w) 637(defun x-dnd-get-drop-x-y (frame w)
616 "Return the x/y coordinates to be sent in a XdndStatus message. 638 "Return the x/y coordinates to be sent in a XdndStatus message.
617Coordinates are required to be absolute. 639Coordinates are required to be absolute.
618FRAME is the frame and W is the window where the drop happened. 640FRAME is the frame and W is the window where the drop happened.
619If W is a window, return its absolute coordinates, 641If W is a window, return its absolute coordinates,
620otherwise return the frame coordinates." 642otherwise return the frame coordinates."
621 (let* ((frame-left (or (car-safe (cdr-safe (frame-parameter frame 'left))) 643 (let* ((position (x-dnd-compute-root-window-position frame))
622 (frame-parameter frame 'left))) 644 (frame-left (car position))
623 (frame-top (or (car-safe (cdr-safe (frame-parameter frame 'top))) 645 (frame-top (cdr position)))
624 (frame-parameter frame 'top))))
625 (if (windowp w) 646 (if (windowp w)
626 (let ((edges (window-inside-pixel-edges w))) 647 (let ((edges (window-inside-pixel-edges w)))
627 (cons 648 (cons
@@ -700,8 +721,7 @@ FORMAT is 32 (not used). MESSAGE is the data part of an XClientMessageEvent."
700 ;; widget bounds". 721 ;; widget bounds".
701 (+ (if dnd-indicate-insertion-point 2 0) accept) 722 (+ (if dnd-indicate-insertion-point 2 0) accept)
702 (x-dnd-get-drop-x-y frame window) 723 (x-dnd-get-drop-x-y frame window)
703 (x-dnd-get-drop-width-height 724 (x-dnd-get-drop-width-height window (eq accept 1))
704 frame window (eq accept 1))
705 ;; The no-toolkit Emacs build can actually 725 ;; The no-toolkit Emacs build can actually
706 ;; receive drops from programs that speak 726 ;; receive drops from programs that speak
707 ;; versions of XDND earlier than 3 (such as 727 ;; versions of XDND earlier than 3 (such as
diff --git a/src/xfns.c b/src/xfns.c
index 748ea10c952..1a65698f490 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -7833,6 +7833,92 @@ Otherwise, the return value is a vector with the following fields:
7833 return prop_attr; 7833 return prop_attr;
7834} 7834}
7835 7835
7836
7837/***********************************************************************
7838 Coordinate management
7839 ***********************************************************************/
7840
7841DEFUN ("x-translate-coordinates", Fx_translate_coordinates,
7842 Sx_translate_coordinates,
7843 1, 5, 0, doc: /* Translate coordinates from FRAME.
7844Translate the given coordinates SOURCE-X and SOURCE-Y from
7845SOURCE-WINDOW's coordinate space to that of DEST-WINDOW, on FRAME.
7846
7847If SOURCE-X and SOURCE-Y are nil, use 0 instead.
7848
7849FRAME can either be a terminal or a frame. If nil, it defaults to the
7850selected frame. SOURCE-WINDOW must be an X window ID, 0 (which means
7851to use the root window), or nil, which means to use FRAME's inner
7852window. DEST-WINDOW must be another X window ID, or nil (which means
7853to use the root window).
7854
7855Return a list of (X Y CHILD) if the given coordinates are on the same
7856screen, or nil otherwise, where X and Y are the coordinates in
7857DEST-WINDOW's coordinate space, and CHILD is the window ID of any
7858mapped child in DEST-WINDOW at those coordinates, or nil if there is
7859no such window. */)
7860 (Lisp_Object frame, Lisp_Object source_window,
7861 Lisp_Object dest_window, Lisp_Object source_x,
7862 Lisp_Object source_y)
7863{
7864 struct x_display_info *dpyinfo;
7865 struct frame *source_frame;
7866 int dest_x, dest_y;
7867 Window child_return, src, dest;
7868 Bool rc;
7869
7870 dpyinfo = check_x_display_info (frame);
7871 dest_x = 0;
7872 dest_y = 0;
7873
7874 if (!NILP (source_x))
7875 {
7876 CHECK_FIXNUM (source_x);
7877 dest_x = XFIXNUM (source_x);
7878 }
7879
7880 if (!NILP (source_y))
7881 {
7882 CHECK_FIXNUM (source_y);
7883 dest_y = XFIXNUM (source_y);
7884 }
7885
7886 if (!NILP (source_window))
7887 CONS_TO_INTEGER (source_window, Window, src);
7888 else
7889 {
7890 source_frame = decode_window_system_frame (frame);
7891 src = FRAME_X_WINDOW (source_frame);
7892 }
7893
7894 if (!src)
7895 src = dpyinfo->root_window;
7896
7897 if (!NILP (dest_window))
7898 CONS_TO_INTEGER (dest_window, Window, dest);
7899 else
7900 dest = dpyinfo->root_window;
7901
7902 block_input ();
7903 x_catch_errors (dpyinfo->display);
7904 rc = XTranslateCoordinates (dpyinfo->display, src, dest,
7905 dest_x, dest_y, &dest_x, &dest_y,
7906 &child_return);
7907 x_check_errors (dpyinfo->display,
7908 "Couldn't translate coordinates: %s");
7909 x_uncatch_errors_after_check ();
7910 unblock_input ();
7911
7912 if (!rc)
7913 return Qnil;
7914
7915 return list3 (make_int (dest_x),
7916 make_int (dest_y),
7917 (child_return != None
7918 ? make_uint (child_return)
7919 : Qnil));
7920}
7921
7836/*********************************************************************** 7922/***********************************************************************
7837 Tool tips 7923 Tool tips
7838 ***********************************************************************/ 7924 ***********************************************************************/
@@ -10003,6 +10089,8 @@ eliminated in future versions of Emacs. */);
10003 defsubr (&Sx_double_buffered_p); 10089 defsubr (&Sx_double_buffered_p);
10004 defsubr (&Sx_begin_drag); 10090 defsubr (&Sx_begin_drag);
10005 defsubr (&Sx_display_set_last_user_time); 10091 defsubr (&Sx_display_set_last_user_time);
10092 defsubr (&Sx_translate_coordinates);
10093
10006 tip_timer = Qnil; 10094 tip_timer = Qnil;
10007 staticpro (&tip_timer); 10095 staticpro (&tip_timer);
10008 tip_frame = Qnil; 10096 tip_frame = Qnil;