>From 5584fbe6402083853b71b3de251670752a5d7af2 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Fri, 14 Apr 2017 10:02:38 +0100 Subject: [PATCH] Add new frame functionality to NS port MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/frame.el (frame-restack): Call ns-frame-restack. * src/keyboard.c (kbd_buffer_get_event) [HAVE_NS]: Enable MOVE_FRAME_EVENT handling. * src/frame.h: * src/frame.c: Enable 'z-group', 'undecorated' and 'parent' frame definitions. * src/nsfns.m: Add x_set_z_group, x_set_parent_frame and x_set_undecorated (Cocoa only) to handler struct. (Fx-create_frame): Handle 'z-code', 'parent-frame' and 'undecorated' frame parameter. (Fns_frame_restack): New function. * src/nsmenu.m (free_frame_tool_bar, update_frame_tool_bar): FRAME_TOOLBAR_HEIGHT is no longer a variable. * src/nsterm.h (NS_PARENT_WINDOW_LEFT_POS, NS_PARENT_WINDOW_TOP_POS): Add #defines to find the screen position of the parent frame. (NS_TOP_POS): Remove defun. (EmacsView): Remove redundant toolbar variables and add createToolbar method. (FRAME_NS_TITLEBAR_HEIGHT, FRAME_TOOLBAR_HEIGHT): Always calculate the values instead of storing them in a variable. * src/nsterm.m (x_set_offset, windowDidMove): Take parent frame position into account when positioning frames. (initFrameFromEmacs): Remove toolbar creation code and handle new frame parameters. (x_set_window_size): Remove toolbar height calculation. (x_set_z_group): (x_set_parent_frame): (x_set_undecorated) [NS_IMPL_COCOA]: New function. (x_destroy_window): Detach parent if child closes. (updateFrameSize): Change NSTRACE message to reflect new reality and no longer reset frame size. (windowWillResize): Don’t change NS window name when the titlebar is invisible. (createToolbar): Move toolbar creation code into it’s own method. (toggleFullScreen): FRAME_TOOLBAR_HEIGHT and FRAME_NS_TITLEBAR_HEIGHT are no longer variables. (windowDidMove): Fire MOVE_FRAME_EVENT Emacs event. --- lisp/frame.el | 4 +- src/frame.c | 2 - src/frame.h | 14 +-- src/keyboard.c | 2 +- src/nsfns.m | 63 +++++++++++- src/nsmenu.m | 8 -- src/nsterm.h | 47 +++++++-- src/nsterm.m | 302 ++++++++++++++++++++++++++++++++++++++++++++------------- 8 files changed, 341 insertions(+), 101 deletions(-) diff --git a/lisp/frame.el b/lisp/frame.el index 86a0e26e39..e632b5943f 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1548,7 +1548,9 @@ frame-restack ((eq frame-type 'x) (x-frame-restack frame1 frame2 above)) ((eq frame-type 'w32) - (w32-frame-restack frame1 frame2 above)))) + (w32-frame-restack frame1 frame2 above)) + ((eq frame-type 'ns) + (ns-frame-restack frame1 frame2 above)))) (error "Cannot restack frames"))) (defun frame-size-changed-p (&optional frame) diff --git a/src/frame.c b/src/frame.c index 282b691c27..681a245ee0 100644 --- a/src/frame.c +++ b/src/frame.c @@ -683,7 +683,6 @@ make_frame (bool mini_p) f->vertical_scroll_bar_type = vertical_scroll_bar_none; f->horizontal_scroll_bars = false; f->want_fullscreen = FULLSCREEN_NONE; -#if ! defined (HAVE_NS) f->undecorated = false; #ifndef HAVE_NTGUI f->override_redirect = false; @@ -692,7 +691,6 @@ make_frame (bool mini_p) f->no_focus_on_map = false; f->no_accept_focus = false; f->z_group = z_group_none; -#endif #if ! defined (USE_GTK) && ! defined (HAVE_NS) f->last_tool_bar_item = -1; #endif diff --git a/src/frame.h b/src/frame.h index 36af6e6780..4aa7c34a29 100644 --- a/src/frame.h +++ b/src/frame.h @@ -75,10 +75,10 @@ struct frame Usually it is nil. */ Lisp_Object title; -#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS) +#if defined (HAVE_WINDOW_SYSTEM) /* This frame's parent frame, if it has one. */ Lisp_Object parent_frame; -#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */ +#endif /* HAVE_WINDOW_SYSTEM */ /* The frame which should receive keystrokes that occur in this frame, or nil if they should go to the frame itself. This is @@ -332,7 +332,7 @@ struct frame bool_bf horizontal_scroll_bars : 1; #endif /* HAVE_WINDOW_SYSTEM */ -#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS) +#if defined (HAVE_WINDOW_SYSTEM) /* True if this is an undecorated frame. */ bool_bf undecorated : 1; @@ -570,7 +570,7 @@ fset_face_alist (struct frame *f, Lisp_Object val) { f->face_alist = val; } -#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS) +#if defined (HAVE_WINDOW_SYSTEM) INLINE void fset_parent_frame (struct frame *f, Lisp_Object val) { @@ -914,7 +914,7 @@ default_pixels_per_inch_y (void) #define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) #endif /* HAVE_WINDOW_SYSTEM */ -#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS) +#if defined (HAVE_WINDOW_SYSTEM) #define FRAME_UNDECORATED(f) ((f)->undecorated) #ifdef HAVE_NTGUI #define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0) @@ -934,7 +934,7 @@ default_pixels_per_inch_y (void) #define FRAME_Z_GROUP_ABOVE_SUSPENDED(f) \ ((f)->z_group == z_group_above_suspended) #define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below) -#else /* not HAVE_WINDOW_SYSTEM or HAVE_NS */ +#else /* not HAVE_WINDOW_SYSTEM */ #define FRAME_UNDECORATED(f) ((void) f, 0) #define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0) #define FRAME_PARENT_FRAME(f) ((void) f, NULL) @@ -945,7 +945,7 @@ default_pixels_per_inch_y (void) #define FRAME_Z_GROUP_NONE(f) ((void) f, true) #define FRAME_Z_GROUP_ABOVE(f) ((void) f, false) #define FRAME_Z_GROUP_BELOW(f) ((void) f, false) -#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */ +#endif /* HAVE_WINDOW_SYSTEM */ /* Whether horizontal scroll bars are currently enabled for frame F. */ #if USE_HORIZONTAL_SCROLL_BARS diff --git a/src/keyboard.c b/src/keyboard.c index 3e50142f7c..c9fa2a9f5e 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -4056,7 +4056,7 @@ kbd_buffer_get_event (KBOARD **kbp, kbd_fetch_ptr = event + 1; } #endif -#if defined (HAVE_X11) || defined (HAVE_NTGUI) +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (HAVE_NS) else if (event->kind == MOVE_FRAME_EVENT) { /* Make an event (move-frame (FRAME)). */ diff --git a/src/nsfns.m b/src/nsfns.m index 8a923dd393..f1a5df8f27 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -972,12 +972,16 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side 0, /* x_set_sticky */ 0, /* x_set_tool_bar_position */ 0, /* x_set_inhibit_double_buffering */ - 0, /* x_set_undecorated */ - 0, /* x_set_parent_frame */ +#ifdef NS_IMPL_COCOA + x_set_undecorated, /* x_set_undecorated */ +#else + 0, /*x_set_undecorated */ +#endif + 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 */ - 0, /* x_set_z_group */ + x_set_z_group, /* x_set_z_group */ 0, /* x_set_override_redirect */ }; @@ -1087,7 +1091,7 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side ptrdiff_t count = specpdl_ptr - specpdl; Lisp_Object display; struct ns_display_info *dpyinfo = NULL; - Lisp_Object parent; + Lisp_Object parent, parent_frame; struct kboard *kb; static int desc_ctr = 1; int x_width = 0, x_height = 0; @@ -1265,6 +1269,25 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, Qx_create_frame_1); + tem = x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN); + FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound); + store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil); + + parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL, + RES_TYPE_SYMBOL); + /* Accept parent-frame iff parent-id was not specified. */ + if (!NILP (parent) + || EQ (parent_frame, Qunbound) + || NILP (parent_frame) + || !FRAMEP (parent_frame) + || !FRAME_LIVE_P (XFRAME (parent_frame))) + parent_frame = Qnil; + + fset_parent_frame (f, parent_frame); + store_frame_param (f, Qparent_frame, parent_frame); + + x_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL); + /* The resources controlling the menu-bar and tool-bar are processed specially at startup, and reflected in the mode variables; ignore them here. */ @@ -1405,6 +1428,37 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side } } +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 +these frames overlap, FRAME2 (partially) obscures FRAME1. If optional +third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This +means that if both frames are visible and the display areas of these +frames overlap, FRAME1 (partially) obscures FRAME2. + +Some window managers may refuse to restack windows. */) + (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above) +{ + struct frame *f1 = decode_live_frame (frame1); + struct frame *f2 = decode_live_frame (frame2); + + if (FRAME_NS_VIEW (f1) && FRAME_NS_VIEW (f2)) + { + NSWindow *window = [FRAME_NS_VIEW (f1) window]; + NSInteger window2 = [[FRAME_NS_VIEW (f2) window] windowNumber]; + NSWindowOrderingMode flag = NILP (above) ? NSWindowBelow : NSWindowAbove; + + [window orderWindow: flag + relativeTo: window2]; + + return Qt; + } + else + { + error ("Cannot restack frames"); + return Qnil; + } +} DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, 0, 1, "", @@ -3134,6 +3188,7 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename defsubr (&Sns_display_monitor_attributes_list); defsubr (&Sns_frame_geometry); defsubr (&Sns_frame_edges); + defsubr (&Sns_frame_restack); defsubr (&Sx_display_mm_width); defsubr (&Sx_display_mm_height); defsubr (&Sx_display_screens); diff --git a/src/nsmenu.m b/src/nsmenu.m index 59ea3855ed..1262c9cb4d 100644 --- a/src/nsmenu.m +++ b/src/nsmenu.m @@ -995,8 +995,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f block_input (); view->wait_for_tool_bar = NO; - FRAME_TOOLBAR_HEIGHT (f) = 0; - /* Note: This trigger an animation, which calls windowDidResize repeatedly. */ f->output_data.ns->in_animation = 1; @@ -1129,12 +1127,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f } #endif - FRAME_TOOLBAR_HEIGHT (f) = - NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) - - FRAME_NS_TITLEBAR_HEIGHT (f); - if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen. - FRAME_TOOLBAR_HEIGHT (f) = 0; - if (oldh != FRAME_TOOLBAR_HEIGHT (f)) [view updateFrameSize:YES]; if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0) diff --git a/src/nsterm.h b/src/nsterm.h index 53d9344cc7..2f8c4269b0 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -430,7 +430,7 @@ char const * nstrace_fullscreen_type_name (int); NSString *workingText; BOOL processingCompose; int fs_state, fs_before_fs, next_maximized; - int tibar_height, tobar_height, bwidth; + int bwidth; int maximized_width, maximized_height; NSWindow *nonfs_window; BOOL fs_is_native; @@ -454,6 +454,7 @@ char const * nstrace_fullscreen_type_name (int); /* Emacs-side interface */ - initFrameFromEmacs: (struct frame *) f; +- (void) createToolbar: (struct frame *)f; - (void) setRows: (int) r andColumns: (int) c; - (void) setWindowClosing: (BOOL)closing; - (EmacsToolbar *) toolbar; @@ -1012,8 +1013,6 @@ struct x_output #define NS_FACE_FOREGROUND(f) ((f)->foreground) #define NS_FACE_BACKGROUND(f) ((f)->background) -#define FRAME_NS_TITLEBAR_HEIGHT(f) ((f)->output_data.ns->titlebar_height) -#define FRAME_TOOLBAR_HEIGHT(f) ((f)->output_data.ns->toolbar_height) #define FRAME_DEFAULT_FACE(f) FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) @@ -1029,6 +1028,25 @@ struct x_output #define XNS_SCROLL_BAR(vec) XSAVE_POINTER (vec, 0) #endif +/* Compute pixel height of the frame's titlebar. */ +#define FRAME_NS_TITLEBAR_HEIGHT(f) \ + (NSHeight([FRAME_NS_VIEW (f) frame]) == 0 ? \ + 0 \ + : (int)(NSHeight([FRAME_NS_VIEW (f) window].frame) \ + - NSHeight([NSWindow contentRectForFrameRect: \ + [[FRAME_NS_VIEW (f) window] frame] \ + styleMask:[[FRAME_NS_VIEW (f) window] styleMask]]))) + +/* Compute pixel height of the toolbar. */ +#define FRAME_TOOLBAR_HEIGHT(f) \ + (([[FRAME_NS_VIEW (f) window] toolbar] == nil \ + || ! [[FRAME_NS_VIEW (f) window] toolbar].isVisible) ? \ + 0 \ + : (int)(NSHeight([NSWindow contentRectForFrameRect: \ + [[FRAME_NS_VIEW (f) window] frame] \ + styleMask:[[FRAME_NS_VIEW (f) window] styleMask]]) \ + - NSHeight([[[FRAME_NS_VIEW (f) window] contentView] frame]))) + /* Compute pixel size for vertical scroll bars */ #define NS_SCROLL_BAR_WIDTH(f) \ (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ @@ -1059,12 +1077,17 @@ struct x_output (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \ - NS_SCROLL_BAR_HEIGHT (f)) : 0) -/* XXX: fix for GNUstep inconsistent accounting for titlebar */ -#ifdef NS_IMPL_GNUSTEP -#define NS_TOP_POS(f) ((f)->top_pos + 18) -#else -#define NS_TOP_POS(f) ((f)->top_pos) -#endif +/* Calculate system coordinates of the left and top of the parent + window or, if there is no parent window, the screen. */ +#define NS_PARENT_WINDOW_LEFT_POS(f) \ + (FRAME_PARENT_FRAME (f) != NULL \ + ? [[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.x : 0) +#define NS_PARENT_WINDOW_TOP_POS(f) \ + (FRAME_PARENT_FRAME (f) != NULL \ + ? ([[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.y \ + + [[FRAME_NS_VIEW (f) window] parentWindow].frame.size.height \ + - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f))) \ + : [[[FRAME_NS_VIEW (f) window] screen] frame].size.height) #define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table) @@ -1185,6 +1208,12 @@ extern int x_display_pixel_width (struct ns_display_info *); /* This in nsterm.m */ extern float ns_antialias_threshold; extern void x_destroy_window (struct frame *f); +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_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, fd_set *exceptfds, struct timespec const *timeout, sigset_t const *sigmask); diff --git a/src/nsterm.m b/src/nsterm.m index 4725991aff..fbbcdbe4bc 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1668,6 +1668,17 @@ -(void)remove -------------------------------------------------------------------------- */ { NSTRACE ("x_destroy_window"); + + /* If this frame has a parent window, detach it as not doing so can + cause a crash in GNUStep. */ + if (FRAME_PARENT_FRAME (f) != NULL) + { + NSWindow *child = [FRAME_NS_VIEW (f) window]; + NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window]; + + [parent removeChildWindow: child]; + } + check_window_system (f); x_free_frame_resources (f); ns_window_num--; @@ -1706,14 +1717,18 @@ -(void)remove - FRAME_TOOLBAR_HEIGHT (f)) : f->top_pos; #ifdef NS_IMPL_GNUSTEP - if (f->left_pos < 100) - f->left_pos = 100; /* don't overlap menu */ + if (FRAME_PARENT_FRAME (f) == NULL) + { + if (f->left_pos < 100) + f->left_pos = 100; /* don't overlap menu */ + } #endif /* Constrain the setFrameTopLeftPoint so we don't move behind the menu bar. */ - NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos), - SCREENMAXBOUND ([fscreen frame].size.height - - NS_TOP_POS (f))); + NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos + + NS_PARENT_WINDOW_LEFT_POS (f)), + SCREENMAXBOUND (NS_PARENT_WINDOW_TOP_POS (f) + - f->top_pos)); NSTRACE_POINT ("setFrameTopLeftPoint", pt); [[view window] setFrameTopLeftPoint: pt]; f->size_hint_flags &= ~(XNegative|YNegative); @@ -1738,7 +1753,6 @@ -(void)remove EmacsView *view = FRAME_NS_VIEW (f); NSWindow *window = [view window]; NSRect wr = [window frame]; - int tb = FRAME_EXTERNAL_TOOL_BAR (f); int pixelwidth, pixelheight; int orig_height = wr.size.height; @@ -1764,25 +1778,6 @@ -(void)remove pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); } - /* If we have a toolbar, take its height into account. */ - if (tb && ! [view isFullscreen]) - { - /* NOTE: previously this would generate wrong result if toolbar not - yet displayed and fixing toolbar_height=32 helped, but - now (200903) seems no longer needed */ - FRAME_TOOLBAR_HEIGHT (f) = - NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)]) - - FRAME_NS_TITLEBAR_HEIGHT (f); -#if 0 - /* Only breaks things here, removed by martin 2015-09-30. */ -#ifdef NS_IMPL_GNUSTEP - FRAME_TOOLBAR_HEIGHT (f) -= 3; -#endif -#endif - } - else - FRAME_TOOLBAR_HEIGHT (f) = 0; - wr.size.width = pixelwidth + f->border_width; wr.size.height = pixelheight; if (! [view isFullscreen]) @@ -1811,6 +1806,150 @@ -(void)remove unblock_input (); } +#ifdef NS_IMPL_COCOA +void +x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* -------------------------------------------------------------------------- + Set frame F's `undecorated' parameter. If non-nil, F's window-system + window is drawn without decorations, title, minimize/maximize boxes + and external borders. This usually means that the window cannot be + dragged, resized, iconified, maximized or deleted with the mouse. If + nil, draw the frame with all the elements listed above unless these + have been suspended via window manager settings. + + GNUStep cannot change an existing window's style. + -------------------------------------------------------------------------- */ +{ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); + NSWindow *window = [view window]; + + if (!EQ (new_value, old_value)) + { + block_input (); + + if (NILP (new_value)) + { + FRAME_UNDECORATED (f) = false; + [window setStyleMask: ((window.styleMask + | NSWindowStyleMaskTitled + | NSWindowStyleMaskResizable + | NSWindowStyleMaskMiniaturizable + | NSWindowStyleMaskClosable) + ^ NSWindowStyleMaskBorderless)]; + + [view createToolbar: f]; + } + else + { + [window setToolbar: nil]; + /* Do I need to release the toolbar here? */ + + FRAME_UNDECORATED (f) = true; + [window setStyleMask: ((window.styleMask | NSWindowStyleMaskBorderless) + ^ (NSWindowStyleMaskTitled + | NSWindowStyleMaskResizable + | NSWindowStyleMaskMiniaturizable + | NSWindowStyleMaskClosable))]; + } + + /* At this point it seems we don't have an active NSResponder, + so some key presses (TAB) are swallowed by the system. */ + [window makeFirstResponder: view]; + + [view updateFrameSize: NO]; + unblock_input (); + } +} +#endif /* NS_IMPL_COCOA */ + +void +x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) +/* -------------------------------------------------------------------------- + Set frame F's `parent-frame' parameter. If non-nil, make F a child + frame of the frame specified by that parameter. Technically, this + makes F's window-system window a child window of the parent frame's + window-system window. If nil, make F's window-system window a + top-level window--a child of its display's root window. + + A child frame's `left' and `top' parameters specify positions + relative to the top-left corner of its parent frame's native + rectangle. On macOS moving a parent frame moves all its child + frames too, keeping their position relative to the parent + unaltered. When a parent frame is iconified or made invisible, its + child frames are made invisible. When a parent frame is deleted, + its child frames are deleted too. + + Whether a child frame has a tool bar may be window-system or window + manager dependent. It's advisable to disable it via the frame + parameter settings. + + Some window managers may not honor this parameter. + -------------------------------------------------------------------------- */ +{ + struct frame *p = NULL; + NSWindow *parent, *child; + + if (!NILP (new_value) + && (!FRAMEP (new_value) + || !FRAME_LIVE_P (p = XFRAME (new_value)) + || !FRAME_X_P (p))) + { + store_frame_param (f, Qparent_frame, old_value); + error ("Invalid specification of `parent-frame'"); + } + + if (p != FRAME_PARENT_FRAME (f)) + { + parent = [FRAME_NS_VIEW (p) window]; + child = [FRAME_NS_VIEW (f) window]; + + block_input (); + [parent addChildWindow: child + ordered: NSWindowAbove]; + unblock_input (); + + fset_parent_frame (f, 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 + window is displayed above all windows that do not have the `above' + property set. If nil, F's window is shown below all windows that + have the `above' property set and above all windows that have the + `below' property set. If `below', F's window is displayed below + all windows that do. + + Some window managers may not honor this parameter. */ +{ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); + NSWindow *window = [view window]; + + if (NILP (new_value)) + { + window.level = NSNormalWindowLevel; + FRAME_Z_GROUP (f) = z_group_none; + } + else if (EQ (new_value, Qabove)) + { + window.level = NSNormalWindowLevel + 1; + FRAME_Z_GROUP (f) = z_group_above; + } + else if (EQ (new_value, Qabove_suspended)) + { + /* Not sure what level this should be. */ + window.level = NSNormalWindowLevel + 1; + FRAME_Z_GROUP (f) = z_group_above_suspended; + } + else if (EQ (new_value, Qbelow)) + { + window.level = NSNormalWindowLevel - 1; + FRAME_Z_GROUP (f) = z_group_below; + } + else + error ("Invalid z-group specification"); +} static void ns_fullscreen_hook (struct frame *f) @@ -2683,7 +2822,7 @@ -(void)remove for (i = 0; i < full_height; i++) cbits[i] = bits[i]; - img = [[EmacsImage alloc] initFromXBM: cbits width: 8 + img = [[EmacsImage alloc] XBM: cbits width: 8 height: full_height fg: 0 bg: 0]; bimgs[p->which - 1] = img; @@ -6399,7 +6538,8 @@ - (void) updateFrameSize: (BOOL) delay; newh = (int)wr.size.height - extra; NSTRACE_SIZE ("New size", NSMakeSize (neww, newh)); - NSTRACE_MSG ("tool_bar_height: %d", emacsframe->tool_bar_height); + NSTRACE_MSG ("FRAME_TOOLBAR_HEIGHT: %d", FRAME_TOOLBAR_HEIGHT (emacsframe)); + NSTRACE_MSG ("FRAME_NS_TITLEBAR_HEIGHT: %d", FRAME_NS_TITLEBAR_HEIGHT (emacsframe)); cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww); rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh); @@ -6424,9 +6564,11 @@ - (void) updateFrameSize: (BOOL) delay; SET_FRAME_GARBAGED (emacsframe); cancel_mouse_face (emacsframe); - wr = NSMakeRect (0, 0, neww, newh); + /* The next two lines appear to be setting the frame to the same + size as it already is. Why are they there? */ + // wr = NSMakeRect (0, 0, neww, newh); - [view setFrame: wr]; + // [view setFrame: wr]; // to do: consider using [NSNotificationCenter postNotificationName:]. [self windowDidMove: // Update top/left. @@ -6489,7 +6631,8 @@ - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize old_title = 0; } } - else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize) + else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize + && [[self window] titleVisibility]) { char *size_title; NSWindow *window = [self window]; @@ -6692,6 +6835,34 @@ - (BOOL)isOpaque } +- (void)createToolbar: (struct frame *)f +{ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); + NSWindow *window = [view window]; + + toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier: + [NSString stringWithFormat: @"Emacs Frame %d", + ns_window_num]]; + [toolbar setVisible: NO]; + [window setToolbar: toolbar]; + + /* Don't set frame garbaged until tool bar is up to date? + This avoids an extra clear and redraw (flicker) at frame creation. */ + if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES; + else wait_for_tool_bar = NO; + + +#ifdef NS_IMPL_COCOA + { + NSButton *toggleButton; + toggleButton = [window standardWindowButton: NSWindowToolbarButton]; + [toggleButton setTarget: self]; + [toggleButton setAction: @selector (toggleToolbar: )]; + } +#endif +} + + - initFrameFromEmacs: (struct frame *)f { NSRect r, wr; @@ -6729,14 +6900,14 @@ - (BOOL)isOpaque maximizing_resize = NO; #endif - win = [[EmacsWindow alloc] + win = [[EmacsFSWindow alloc] initWithContentRect: r - styleMask: (NSWindowStyleMaskResizable | -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - NSWindowStyleMaskTitled | -#endif - NSWindowStyleMaskMiniaturizable | - NSWindowStyleMaskClosable) + styleMask: (FRAME_UNDECORATED (f) + ? NSWindowStyleMaskBorderless + : NSWindowStyleMaskTitled + | NSWindowStyleMaskResizable + | NSWindowStyleMaskMiniaturizable + | NSWindowStyleMaskClosable) backing: NSBackingStoreBuffered defer: YES]; @@ -6746,7 +6917,6 @@ - (BOOL)isOpaque wr = [win frame]; bwidth = f->border_width = wr.size.width - r.size.width; - tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; [win setAcceptsMouseMovedEvents: YES]; [win setDelegate: self]; @@ -6766,42 +6936,36 @@ - (BOOL)isOpaque [win setTitle: name]; /* toolbar support */ - toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier: - [NSString stringWithFormat: @"Emacs Frame %d", - ns_window_num]]; - [win setToolbar: toolbar]; - [toolbar setVisible: NO]; - - /* Don't set frame garbaged until tool bar is up to date? - This avoids an extra clear and redraw (flicker) at frame creation. */ - if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES; - else wait_for_tool_bar = NO; - - -#ifdef NS_IMPL_COCOA - { - NSButton *toggleButton; - toggleButton = [win standardWindowButton: NSWindowToolbarButton]; - [toggleButton setTarget: self]; - [toggleButton setAction: @selector (toggleToolbar: )]; - } -#endif - FRAME_TOOLBAR_HEIGHT (f) = 0; + if (! FRAME_UNDECORATED (f)) + [self createToolbar: f]; tem = f->icon_name; if (!NILP (tem)) [win setMiniwindowTitle: [NSString stringWithUTF8String: SSDATA (tem)]]; + if (FRAME_PARENT_FRAME (f) != NULL) + { + NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window]; + [parent addChildWindow: win + ordered: NSWindowAbove]; + } + + if (!NILP (FRAME_Z_GROUP (f))) + win.level = NSNormalWindowLevel + + (FRAME_Z_GROUP_BELOW (f) ? -1 : 1); + { NSScreen *screen = [win screen]; if (screen != 0) { NSPoint pt = NSMakePoint - (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX), + (IN_BOUND (-SCREENMAX, f->left_pos + + NS_PARENT_WINDOW_LEFT_POS (f), SCREENMAX), IN_BOUND (-SCREENMAX, - [screen frame].size.height - NS_TOP_POS (f), SCREENMAX)); + NS_PARENT_WINDOW_TOP_POS (f) - f->top_pos, + SCREENMAX)); [win setFrameTopLeftPoint: pt]; @@ -6843,9 +7007,15 @@ - (void)windowDidMove: sender return; if (screen != nil) { - emacsframe->left_pos = r.origin.x; + emacsframe->left_pos = r.origin.x - NS_PARENT_WINDOW_LEFT_POS (emacsframe); emacsframe->top_pos = - [screen frame].size.height - (r.origin.y + r.size.height); + NS_PARENT_WINDOW_TOP_POS (emacsframe) - (r.origin.y + r.size.height); + + if (emacs_event) + { + emacs_event->kind = MOVE_FRAME_EVENT; + EV_TRAILER ((id)nil); + } } } @@ -7262,9 +7432,6 @@ - (void)toggleFullScreen: (id)sender [fw setOpaque: NO]; f->border_width = 0; - FRAME_NS_TITLEBAR_HEIGHT (f) = 0; - tobar_height = FRAME_TOOLBAR_HEIGHT (f); - FRAME_TOOLBAR_HEIGHT (f) = 0; nonfs_window = w; @@ -7298,9 +7465,6 @@ - (void)toggleFullScreen: (id)sender [w setOpaque: NO]; f->border_width = bwidth; - FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height; - if (FRAME_EXTERNAL_TOOL_BAR (f)) - FRAME_TOOLBAR_HEIGHT (f) = tobar_height; // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications. -- 2.12.0