From d812d20fbc3e1eff0f10443baed801adda9031cd Mon Sep 17 00:00:00 2001 From: Alan Third Date: Thu, 20 Apr 2017 15:25:56 +0100 Subject: [PATCH] Add no-accept-focus and frame-list-z-order to NS port * lisp/frame.el (frame-list-z-order): Add NS. * src/nsfns.m: Add x_set_no_accept_focus to handler struct. (Fx_create_frame): Handle no-accept-focus parameter. (ns_window_is_ancestor): (Fns_frame_list_z_order): New functions. * src/nsterm.m (x_set_no_accept_focus): New function. (initFrameFromEmacs): Use EmacsWindow instead of EmacsFSWindow for non-fullscreen windows. (EmacsWindow:canBecomeKeyWindow): New function. --- lisp/frame.el | 6 ++++- src/nsfns.m | 61 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/nsterm.h | 2 ++ src/nsterm.m | 22 ++++++++++++++++++- 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/lisp/frame.el b/lisp/frame.el index e632b5943fc..cec262499d1 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1500,6 +1500,7 @@ keys and their meanings." (declare-function x-frame-list-z-order "xfns.c" (&optional display)) (declare-function w32-frame-list-z-order "w32fns.c" (&optional display)) +(declare-function ns-frame-list-z-order "nsfns.m" (&optional display)) (defun frame-list-z-order (&optional display) "Return list of Emacs' frames, in Z (stacking) order. @@ -1517,10 +1518,13 @@ Return nil if DISPLAY contains no Emacs frame." ((eq frame-type 'x) (x-frame-list-z-order display)) ((eq frame-type 'w32) - (w32-frame-list-z-order display))))) + (w32-frame-list-z-order display)) + ((eq frame-type 'ns) + (ns-frame-list-z-order display))))) (declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above)) (declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above)) +(declare-function ns-frame-restack "nsfns.m" (frame1 frame2 &optional above)) (defun frame-restack (frame1 frame2 &optional above) "Restack FRAME1 below FRAME2. diff --git a/src/nsfns.m b/src/nsfns.m index f1a5df8f27e..3a37df95759 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -973,14 +973,14 @@ frame_parm_handler ns_frame_parm_handlers[] = 0, /* x_set_tool_bar_position */ 0, /* x_set_inhibit_double_buffering */ #ifdef NS_IMPL_COCOA - x_set_undecorated, /* x_set_undecorated */ + x_set_undecorated, #else 0, /*x_set_undecorated */ #endif - x_set_parent_frame, /* x_set_parent_frame */ + x_set_parent_frame, 0, /* x_set_skip_taskbar */ 0, /* x_set_no_focus_on_map */ - 0, /* x_set_no_accept_focus */ + x_set_no_accept_focus, x_set_z_group, /* x_set_z_group */ 0, /* x_set_override_redirect */ }; @@ -1287,6 +1287,8 @@ This function is an internal primitive--use `make-frame' instead. */) store_frame_param (f, Qparent_frame, parent_frame); x_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); + x_default_parameter (f, parms, Qno_accept_focus, Qnil, + NULL, NULL, RES_TYPE_BOOLEAN); /* The resources controlling the menu-bar and tool-bar are processed specially at startup, and reflected in the mode @@ -1428,6 +1430,58 @@ x_focus_frame (struct frame *f, bool noactivate) } } +static BOOL +ns_window_is_ancestor (NSWindow *win, NSWindow *candidate) +/* Test whether CANDIDATE is an ancestor window of WIN. */ +{ + if (candidate == NULL) + return NO; + else if (win == candidate) + return YES; + else + return ns_window_is_ancestor(win, [candidate parentWindow]); +} + +DEFUN ("ns-frame-list-z-order", Fns_frame_list_z_order, + Sns_frame_list_z_order, 0, 1, 0, + doc: /* Return list of Emacs' frames, in Z (stacking) order. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be either a frame or a display name (a string). If +omitted or nil, that stands for the selected frame's display. Return +nil if TERMINAL contains no Emacs frame. + +As a special case, if TERMINAL is non-nil and specifies a live frame, +return the child frames of that frame in Z (stacking) order. + +Frames are listed from topmost (first) to bottommost (last). */) + (Lisp_Object terminal) +{ + NSArray *list = [NSApp orderedWindows]; + Lisp_Object frames = Qnil; + + if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal))) + { + /* Filter LIST to just those that are ancestors of TERMINAL. */ + NSWindow *win = [FRAME_NS_VIEW (XFRAME (terminal)) window]; + + NSPredicate *ancestor_pred = + [NSPredicate predicateWithBlock:^BOOL(id candidate, NSDictionary *bind) { + return ns_window_is_ancestor (win, [(NSWindow *)candidate parentWindow]); + }]; + + list = [[NSApp orderedWindows] filteredArrayUsingPredicate: ancestor_pred]; + } + + for (NSWindow *win in [list reverseObjectEnumerator]) + { + Lisp_Object frame; + XSETFRAME (frame, ((EmacsView *)[win delegate])->emacsframe); + frames = Fcons(frame, frames); + } + + return frames; +} + DEFUN ("ns-frame-restack", Fns_frame_restack, Sns_frame_restack, 2, 3, 0, doc: /* Restack FRAME1 below FRAME2. This means that if both frames are visible and the display areas of @@ -3188,6 +3242,7 @@ be used as the image of the icon representing the frame. */); defsubr (&Sns_display_monitor_attributes_list); defsubr (&Sns_frame_geometry); defsubr (&Sns_frame_edges); + defsubr (&Sns_frame_list_z_order); defsubr (&Sns_frame_restack); defsubr (&Sx_display_mm_width); defsubr (&Sx_display_mm_height); diff --git a/src/nsterm.h b/src/nsterm.h index 2f8c4269b0b..9285178d190 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1212,6 +1212,8 @@ extern void x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); +extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, + Lisp_Object old_value); extern void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value); extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, diff --git a/src/nsterm.m b/src/nsterm.m index c53957f9338..4e88297bc04 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1912,6 +1912,21 @@ x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_valu } } +void +x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* Set frame F's `no-accept-focus' parameter which, if non-nil, hints + * that F's window-system window does not want to receive input focus + * via mouse clicks or by moving the mouse into it. + * + * If non-nil, this may have the unwanted side-effect that a user cannot + * scroll a non-selected frame with the mouse. + * + * Some window managers may not honor this parameter. */ +{ + if (!EQ (new_value, old_value)) + FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value); +} + void x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) /* Set frame F's `z-group' parameter. If `above', F's window-system @@ -6900,7 +6915,7 @@ not_in_argv (NSString *arg) maximizing_resize = NO; #endif - win = [[EmacsFSWindow alloc] + win = [[EmacsWindow alloc] initWithContentRect: r styleMask: (FRAME_UNDECORATED (f) ? NSWindowStyleMaskBorderless @@ -8130,6 +8145,11 @@ not_in_argv (NSString *arg) [super setFrameTopLeftPoint:point]; } + +- (BOOL)canBecomeKeyWindow +{ + return !FRAME_NO_ACCEPT_FOCUS (((EmacsView *)[self delegate])->emacsframe); +} @end /* EmacsWindow */ -- 2.39.2