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 */
};
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;
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. */
}
}
+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, "",
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);
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;
/* 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;
#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)
#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) \
(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)
/* 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);
-------------------------------------------------------------------------- */
{
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--;
- 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);
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;
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])
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)
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;
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);
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.
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];
}
+- (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;
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];
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];
[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];
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);
+ }
}
}
[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;
[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.