diff options
-rw-r--r-- | lisp/mouse.el | 3 | ||||
-rw-r--r-- | lisp/term/haiku-win.el | 5 | ||||
-rw-r--r-- | lisp/term/ns-win.el | 5 | ||||
-rw-r--r-- | src/haikufns.c | 10 | ||||
-rw-r--r-- | src/haikuselect.c | 77 | ||||
-rw-r--r-- | src/haikuterm.c | 9 | ||||
-rw-r--r-- | src/haikuterm.h | 4 | ||||
-rw-r--r-- | src/nsfns.m | 49 | ||||
-rw-r--r-- | src/nsmenu.m | 9 | ||||
-rw-r--r-- | src/nsselect.m | 12 | ||||
-rw-r--r-- | src/nsterm.h | 27 | ||||
-rw-r--r-- | src/nsterm.m | 48 | ||||
-rw-r--r-- | src/xfns.c | 3 |
13 files changed, 221 insertions, 40 deletions
diff --git a/lisp/mouse.el b/lisp/mouse.el index 6a2b1738f71..11014fa1c5f 100644 --- a/lisp/mouse.el +++ b/lisp/mouse.el @@ -3103,6 +3103,9 @@ is copied instead of being cut." ;; tooltip. (mouse-fine-grained-tracking t) (was-tooltip-mode tooltip-mode) + ;; System tooltips tend to flicker and in general work + ;; incorrectly. + (use-system-tooltips nil) ;; Whether or not some text was ``cut'' from Emacs to another ;; program and the cleaanup code should not try modifying the ;; region. diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 58217513902..f99d332bd2b 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -367,7 +367,7 @@ take effect on menu items until the menu bar is updated again." (setq haiku-drag-track-function #'haiku-dnd-drag-handler) (defun x-begin-drag (targets &optional action frame _return-frame - allow-current-frame _follow-tooltip) + allow-current-frame follow-tooltip) "SKIP: real doc in xfns.c." (unless haiku-dnd-selection-value (error "No local value for XdndSelection")) @@ -409,7 +409,8 @@ take effect on menu items until the menu bar is updated again." action) 'XdndActionCopy) (haiku-drag-message (or frame (selected-frame)) - message allow-current-frame)))) + message allow-current-frame + follow-tooltip)))) (add-variable-watcher 'use-system-tooltips #'haiku-use-system-tooltips-watcher) diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 0d46a895ce8..ac1007f94fe 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -896,7 +896,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (ns-get-selection selection-symbol target-type)) (defun x-begin-drag (targets &optional action frame return-frame - allow-current-frame _follow-tooltip) + allow-current-frame follow-tooltip) "SKIP: real doc in xfns.c." (unless ns-dnd-selection-value (error "No local value for XdndSelection")) @@ -921,7 +921,8 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (expand-file-name ns-dnd-selection-value)))) pasteboard)))) - (ns-begin-drag frame pasteboard action return-frame allow-current-frame))) + (ns-begin-drag frame pasteboard action return-frame + allow-current-frame follow-tooltip))) (defun ns-handle-drag-motion (frame x y) "Handle mouse movement on FRAME at X and Y during drag-and-drop. diff --git a/src/haikufns.c b/src/haikufns.c index 6a79eede0e7..0b8bf89d85a 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -50,6 +50,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ /* The frame of the currently visible tooltip. */ Lisp_Object tip_frame; +/* The X and Y deltas of the last call to `x-show-tip'. */ +Lisp_Object tip_dx, tip_dy; + /* The window-system window corresponding to the frame of the currently visible tooltip. */ static Window tip_window; @@ -2352,6 +2355,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, else CHECK_FIXNUM (dy); + tip_dx = dx; + tip_dy = dy; + if (use_system_tooltips) { int root_x, root_y; @@ -3165,6 +3171,10 @@ syms_of_haikufns (void) staticpro (&tip_last_string); tip_last_parms = Qnil; staticpro (&tip_last_parms); + tip_dx = Qnil; + staticpro (&tip_dx); + tip_dy = Qnil; + staticpro (&tip_dy); DEFVAR_LISP ("x-max-tooltip-size", Vx_max_tooltip_size, doc: /* SKIP: real doc in xfns.c. */); diff --git a/src/haikuselect.c b/src/haikuselect.c index 80604252cb9..b69fcfff13e 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -33,6 +33,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ the nested event loop inside be_drag_message. */ struct frame *haiku_dnd_frame; +/* Whether or not to move the tip frame during drag-and-drop. */ +bool haiku_dnd_follow_tooltip; + static void haiku_lisp_to_message (Lisp_Object, void *); static enum haiku_clipboard @@ -752,10 +755,13 @@ haiku_unwind_drag_message (void *message) { haiku_dnd_frame = NULL; BMessage_delete (message); + + if (haiku_dnd_follow_tooltip) + Fx_hide_tip (); } DEFUN ("haiku-drag-message", Fhaiku_drag_message, Shaiku_drag_message, - 2, 3, 0, + 2, 4, 0, doc: /* Begin dragging MESSAGE from FRAME. MESSAGE an alist of strings, denoting message field names, to a list @@ -789,8 +795,12 @@ FRAME is a window system frame that must be visible, from which the drag will originate. ALLOW-SAME-FRAME, if nil or not specified, means that MESSAGE will be -ignored if it is dropped on top of FRAME. */) - (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame) +ignored if it is dropped on top of FRAME. + +FOLLOW-TOOLTIP, if non-nil, will cause any non-system tooltip +currently being displayed to move along with the mouse pointer. */) + (Lisp_Object frame, Lisp_Object message, Lisp_Object allow_same_frame, + Lisp_Object follow_tooltip) { specpdl_ref idx; void *be_message; @@ -804,15 +814,18 @@ ignored if it is dropped on top of FRAME. */) error ("Frame is invisible"); haiku_dnd_frame = f; + haiku_dnd_follow_tooltip = !NILP (follow_tooltip); be_message = be_create_simple_message (); record_unwind_protect_ptr (haiku_unwind_drag_message, be_message); haiku_lisp_to_message (message, be_message); + rc = be_drag_message (FRAME_HAIKU_VIEW (f), be_message, !NILP (allow_same_frame), block_input, unblock_input, process_pending_signals, haiku_should_quit_drag); + FRAME_DISPLAY_INFO (f)->grabbed = 0; if (rc) @@ -918,6 +931,44 @@ after it starts. */) return SAFE_FREE_UNBIND_TO (depth, Qnil); } +static void +haiku_dnd_compute_tip_xy (int *root_x, int *root_y) +{ + int min_x, min_y, max_x, max_y; + int width, height; + + width = FRAME_PIXEL_WIDTH (XFRAME (tip_frame)); + height = FRAME_PIXEL_HEIGHT (XFRAME (tip_frame)); + + min_x = 0; + min_y = 0; + be_get_screen_dimensions (&max_x, &max_y); + + if (*root_y + XFIXNUM (tip_dy) <= min_y) + *root_y = min_y; /* Can happen for negative dy */ + else if (*root_y + XFIXNUM (tip_dy) + height <= max_y) + /* It fits below the pointer */ + *root_y += XFIXNUM (tip_dy); + else if (height + XFIXNUM (tip_dy) + min_y <= *root_y) + /* It fits above the pointer. */ + *root_y -= height + XFIXNUM (tip_dy); + else + /* Put it on the top. */ + *root_y = min_y; + + if (*root_x + XFIXNUM (tip_dx) <= min_x) + *root_x = 0; /* Can happen for negative dx */ + else if (*root_x + XFIXNUM (tip_dx) + width <= max_x) + /* It fits to the right of the pointer. */ + *root_x += XFIXNUM (tip_dx); + else if (width + XFIXNUM (tip_dx) + min_x <= *root_x) + /* It fits to the left of the pointer. */ + *root_x -= width + XFIXNUM (tip_dx); + else + /* Put it left justified on the screen -- it ought to fit that way. */ + *root_x = min_x; +} + static Lisp_Object haiku_note_drag_motion_1 (void *data) { @@ -936,6 +987,26 @@ haiku_note_drag_motion_2 (enum nonlocal_exit exit, Lisp_Object error) void haiku_note_drag_motion (void) { + struct frame *tip_f; + int x, y; + + if (FRAMEP (tip_frame) && haiku_dnd_follow_tooltip + && FIXNUMP (tip_dx) && FIXNUMP (tip_dy)) + { + tip_f = XFRAME (tip_frame); + + if (FRAME_LIVE_P (tip_f)) + { + BView_get_mouse (FRAME_HAIKU_VIEW (haiku_dnd_frame), + &x, &y); + BView_convert_to_screen (FRAME_HAIKU_VIEW (haiku_dnd_frame), + &x, &y); + + haiku_dnd_compute_tip_xy (&x, &y); + BWindow_set_offset (FRAME_HAIKU_WINDOW (tip_f), x, y); + } + } + internal_catch_all (haiku_note_drag_motion_1, NULL, haiku_note_drag_motion_2); } diff --git a/src/haikuterm.c b/src/haikuterm.c index 55e8640ec21..d47e61e60dd 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -3286,10 +3286,15 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit) if (FRAME_TOOLTIP_P (f)) { /* Dismiss the tooltip if the mouse moves onto a - tooltip frame. FIXME: for some reason we don't get - leave notification events for this. */ + tooltip frame (except when drag-and-drop is in + progress and we are trying to move the tooltip + along with the mouse pointer). FIXME: for some + reason we don't get leave notification events for + this. */ if (any_help_event_p + && !(be_drag_and_drop_in_progress () + && haiku_dnd_follow_tooltip) && !((EQ (track_mouse, Qdrag_source) || EQ (track_mouse, Qdropping)) && gui_mouse_grabbed (x_display_list))) diff --git a/src/haikuterm.h b/src/haikuterm.h index 41b1a85b000..ea20289b5d1 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -219,7 +219,11 @@ extern struct haiku_display_info *x_display_list; extern struct font_driver const haikufont_driver; extern Lisp_Object tip_frame; +extern Lisp_Object tip_dx; +extern Lisp_Object tip_dy; + extern struct frame *haiku_dnd_frame; +extern bool haiku_dnd_follow_tooltip; extern frame_parm_handler haiku_frame_parm_handlers[]; diff --git a/src/nsfns.m b/src/nsfns.m index 1593338dc95..d4cf4f5ffae 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -63,6 +63,9 @@ static EmacsTooltip *ns_tooltip = nil; /* The frame of the currently visible tooltip, or nil if none. */ static Lisp_Object tip_frame; +/* The X and Y deltas of the last call to `x-show-tip'. */ +static Lisp_Object tip_dx, tip_dy; + /* The window-system window corresponding to the frame of the currently visible tooltip. */ static NSWindow *tip_window; @@ -3243,6 +3246,9 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, else CHECK_FIXNUM (dy); + tip_dx = dx; + tip_dy = dy; + if (use_system_tooltips) { NSSize size; @@ -3794,6 +3800,45 @@ all_nonzero_ascii (unsigned char *str, ptrdiff_t n) } @end +void +ns_move_tooltip_to_mouse_location (NSPoint screen_point) +{ + int root_x, root_y; + NSSize size; + NSWindow *window; + struct frame *tip_f; + + if (!FIXNUMP (tip_dx) || !FIXNUMP (tip_dy)) + return; + + if (ns_tooltip) + size = [ns_tooltip frame].size; + else if (!FRAMEP (tip_frame) + || !FRAME_LIVE_P (XFRAME (tip_frame))) + return; + else + { + tip_f = XFRAME (tip_frame); + window = [FRAME_NS_VIEW (tip_f) window]; + size = [window frame].size; + } + + root_x = screen_point.x; + root_y = screen_point.y; + + /* We can directly use `compute_tip_xy' here, since it doesn't cons + nearly as much as it does on X. */ + compute_tip_xy (NULL, Qnil, tip_dx, tip_dy, (int) size.width, + (int) size.height, &root_x, &root_y); + + if (ns_tooltip) + [ns_tooltip moveTo: NSMakePoint (root_x, root_y)]; + else + [window setFrame: NSMakeRect (root_x, root_y, + size.width, size.height) + display: YES]; +} + /* ========================================================================== Lisp interface declaration @@ -3902,6 +3947,10 @@ Default is t. */); staticpro (&tip_last_string); tip_last_parms = Qnil; staticpro (&tip_last_parms); + tip_dx = Qnil; + staticpro (&tip_dx); + tip_dy = Qnil; + staticpro (&tip_dy); #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1080 defsubr (&Ssystem_move_file_to_trash); diff --git a/src/nsmenu.m b/src/nsmenu.m index 028d19f597a..d02d7bae4b5 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -1497,6 +1497,15 @@ update_frame_tool_bar (struct frame *f) [timer retain]; } +- (void) moveTo: (NSPoint) screen_point +{ + [win setFrame: NSMakeRect (screen_point.x, + screen_point.y, + [self frame].size.width, + [self frame].size.height) + display: YES]; +} + - (void) hide { [win close]; diff --git a/src/nsselect.m b/src/nsselect.m index 6831090aa20..c46bfeaf42a 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -703,7 +703,7 @@ ns_dnd_action_from_operation (NSDragOperation operation) } } -DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 5, 0, +DEFUN ("ns-begin-drag", Fns_begin_drag, Sns_begin_drag, 3, 6, 0, doc: /* Begin a drag-and-drop operation on FRAME. FRAME must be a window system frame. PBOARD is an alist of (TYPE @@ -729,9 +729,12 @@ other non-nil value means to do the same, but to wait for the mouse to leave FRAME first. If ALLOW-SAME-FRAME is nil, dropping on FRAME will result in the drop -being ignored. */) +being ignored. + +FOLLOW-TOOLTIP means the same thing it does in `x-begin-drag'. */) (Lisp_Object frame, Lisp_Object pboard, Lisp_Object action, - Lisp_Object return_frame, Lisp_Object allow_same_frame) + Lisp_Object return_frame, Lisp_Object allow_same_frame, + Lisp_Object follow_tooltip) { struct frame *f, *return_to; NSPasteboard *pasteboard; @@ -761,7 +764,8 @@ being ignored. */) forPasteboard: pasteboard withMode: mode returnFrameTo: &return_to - prohibitSame: (BOOL) NILP (allow_same_frame)]; + prohibitSame: (BOOL) NILP (allow_same_frame) + followTooltip: (BOOL) !NILP (follow_tooltip)]; if (return_to) { diff --git a/src/nsterm.h b/src/nsterm.h index 37bff6260a0..c4fdc7054f7 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -426,6 +426,7 @@ enum ns_return_frame_mode struct frame *dnd_return_frame; enum ns_return_frame_mode dnd_mode; BOOL dnd_allow_same_frame; + BOOL dnd_move_tooltip_with_frame; } #ifdef NS_IMPL_GNUSTEP @@ -446,7 +447,8 @@ enum ns_return_frame_mode forPasteboard: (NSPasteboard *) pasteboard withMode: (enum ns_return_frame_mode) mode returnFrameTo: (struct frame **) frame_return - prohibitSame: (BOOL) prohibit_same_frame; + prohibitSame: (BOOL) prohibit_same_frame + followTooltip: (BOOL) follow_tooltip; - (BOOL) mustNotDropOn: (NSView *) receiver; @end @@ -630,19 +632,21 @@ enum ns_return_frame_mode #else @interface EmacsTooltip : NSObject #endif - { - NSWindow *win; - NSTextField *textField; - NSTimer *timer; - } +{ + NSWindow *win; + NSTextField *textField; + NSTimer *timer; +} + - (instancetype) init; -- (void) setText: (char *)text; -- (void) setBackgroundColor: (NSColor *)col; -- (void) setForegroundColor: (NSColor *)col; -- (void) showAtX: (int)x Y: (int)y for: (int)seconds; +- (void) setText: (char *) text; +- (void) setBackgroundColor: (NSColor *) col; +- (void) setForegroundColor: (NSColor *) col; +- (void) showAtX: (int) x Y: (int) y for: (int) seconds; - (void) hide; - (BOOL) isActive; - (NSRect) frame; +- (void) moveTo: (NSPoint) screen_point; @end @@ -1140,6 +1144,9 @@ extern const char *ns_get_pending_menu_title (void); #endif /* Implemented in nsfns, published in nsterm. */ +#ifdef __OBJC__ +extern void ns_move_tooltip_to_mouse_location (NSPoint); +#endif extern void ns_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval); extern void ns_set_scroll_bar_default_width (struct frame *f); diff --git a/src/nsterm.m b/src/nsterm.m index 4663ac85d84..b0eb86bfb09 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -9629,35 +9629,45 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) selected_op = operation; } -#ifdef NS_IMPL_COCOA - (void) draggedImage: (NSImage *) dragged_image movedTo: (NSPoint) screen_point { + NSPoint mouse_loc; +#ifdef NS_IMPL_COCOA NSInteger window_number; NSWindow *w; +#endif - if (dnd_mode == RETURN_FRAME_NEVER) - return; + mouse_loc = [NSEvent mouseLocation]; - window_number = [NSWindow windowNumberAtPoint: [NSEvent mouseLocation] - belowWindowWithWindowNumber: 0]; - w = [NSApp windowWithWindowNumber: window_number]; +#ifdef NS_IMPL_COCOA + if (dnd_mode != RETURN_FRAME_NEVER) + { + window_number = [NSWindow windowNumberAtPoint: mouse_loc + belowWindowWithWindowNumber: 0]; + w = [NSApp windowWithWindowNumber: window_number]; - if (!w || w != self) - dnd_mode = RETURN_FRAME_NOW; + if (!w || w != self) + dnd_mode = RETURN_FRAME_NOW; - if (dnd_mode != RETURN_FRAME_NOW - || ![[w delegate] isKindOfClass: [EmacsView class]]) - return; + if (dnd_mode != RETURN_FRAME_NOW + || ![[w delegate] isKindOfClass: [EmacsView class]]) + goto out; - dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; + dnd_return_frame = ((EmacsView *) [w delegate])->emacsframe; - /* FIXME: there must be a better way to leave the event loop. */ - [NSException raise: @"" - format: @"Must return DND frame"]; -} + /* FIXME: there must be a better way to leave the event loop. */ + [NSException raise: @"" + format: @"Must return DND frame"]; + } #endif + out: + + if (dnd_move_tooltip_with_frame) + ns_move_tooltip_to_mouse_location (mouse_loc); +} + - (BOOL) mustNotDropOn: (NSView *) receiver { return ([receiver window] == self @@ -9669,6 +9679,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) withMode: (enum ns_return_frame_mode) mode returnFrameTo: (struct frame **) frame_return prohibitSame: (BOOL) prohibit_same_frame + followTooltip: (BOOL) follow_tooltip { NSImage *image; #ifdef NS_IMPL_COCOA @@ -9681,6 +9692,7 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) dnd_mode = mode; dnd_return_frame = NULL; dnd_allow_same_frame = !prohibit_same_frame; + dnd_move_tooltip_with_frame = follow_tooltip; /* Now draw transparency onto the image. */ [image lockFocus]; @@ -9728,6 +9740,10 @@ nswindow_orderedIndex_sort (id w1, id w2, void *c) #endif unblock_input (); + /* The drop happened, so delete the tooltip. */ + if (follow_tooltip) + Fx_hide_tip (); + /* Assume all buttons have been released since the drag-and-drop operation is now over. */ if (!dnd_return_frame) diff --git a/src/xfns.c b/src/xfns.c index 15e96183e3b..43d4d27372e 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -6884,7 +6884,8 @@ mouse buttons are released on top of FRAME. If FOLLOW-TOOLTIP is non-nil, any tooltip currently being displayed will be moved to follow the mouse pointer while the drag is in -progress. +progress. Note that this does not work with system tooltips (tooltips +created when `use-system-tooltips' is non-nil). This function will sometimes return immediately if no mouse buttons are currently held down. It should only be called when it is known |