From d576216adb21a2b5ae49236e4bf11dd067432204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marks?= Date: Wed, 24 Dec 2025 16:32:04 +0100 Subject: [PATCH] Add ns_set_window_size_and_position * src/frame.c (Fset_frame_size_and_position_pixelwise): Correct docstring typo. * src/nsterm.m (compute_offset): New function of common code. (ns_set_offset): Call compute_offset. (ns_set_window_size_and_position): New function. (ns_create_terminal): Add new function to the hook. --- src/frame.c | 2 +- src/nsterm.m | 80 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/frame.c b/src/frame.c index 3c5df648e3f..398352e9daf 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4561,7 +4561,7 @@ FRAME must be a live frame and defaults to the selected one. WIDTH and HEIGHT must be positive integers and specify the new pixel width and height of FRAME's text area in pixels. If WIDTH or HEIGHT do -not secify a value that is a multiple of FRAME's character sizes, you +not specify a value that is a multiple of FRAME's character sizes, you may have to set `frame-resize-pixelwise' to a non-nil value in order to get the exact size in pixels. diff --git a/src/nsterm.m b/src/nsterm.m index 66b4a3c82e7..6eb1e88a182 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1677,27 +1677,17 @@ Hide the window (X11 semantics) ns_window_num--; } - -void -ns_set_offset (struct frame *f, int xoff, int yoff, int change_grav) -/* -------------------------------------------------------------------------- - External: Position the window - -------------------------------------------------------------------------- */ +static NSPoint +compute_offset (struct frame *f, NSView *view, int xoff, int yoff) { - NSView *view = FRAME_NS_VIEW (f); - NSRect windowFrame = [[view window] frame]; - NSPoint topLeft; - - NSTRACE ("ns_set_offset"); - - block_input (); - /* If there is no parent frame then just convert to screen coordinates, UNLESS we have negative values, in which case I think it's best to position from the bottom and right of the current screen rather than the main screen or whole display. */ NSRect parentRect = ns_parent_window_rect (f); + NSRect windowFrame = [[view window] frame]; + NSPoint topLeft; if (f->size_hint_flags & XNegative) topLeft.x = NSMaxX (parentRect) - NSWidth (windowFrame) + xoff; @@ -1722,6 +1712,25 @@ Hide the window (X11 semantics) topLeft.x = 100; #endif + return topLeft; +} + +void +ns_set_offset (struct frame *f, int xoff, int yoff, int change_grav) +/* -------------------------------------------------------------------------- + External: Position the window + -------------------------------------------------------------------------- */ +{ + NSView *view = FRAME_NS_VIEW (f); + + NSTRACE ("ns_set_offset"); + + if (view == nil) + return; + + block_input (); + + NSPoint topLeft = compute_offset (f, view, xoff, yoff); NSTRACE_POINT ("setFrameTopLeftPoint", topLeft); [[view window] setFrameTopLeftPoint:topLeft]; f->size_hint_flags &= ~(XNegative|YNegative); @@ -1729,7 +1738,6 @@ Hide the window (X11 semantics) unblock_input (); } - static void ns_set_window_size (struct frame *f, bool change_gravity, int width, int height) @@ -1773,6 +1781,47 @@ Hide the window (X11 semantics) unblock_input (); } +static void +ns_set_window_size_and_position (struct frame *f, + int width, int height) +/* -------------------------------------------------------------------------- + Adjust window pixelwise size and position in one operation. + -------------------------------------------------------------------------- */ +{ + EmacsView *view = FRAME_NS_VIEW (f); + NSWindow *window = [view window]; + + NSTRACE ("ns_set_window_size_and_position"); + + if (view == nil) + return; + + block_input (); + + /* Both window frame origin, and the rect that setFrame accepts are + anchored to the bottom-left corner of the window. */ + NSPoint topLeft = compute_offset (f, view, f->left_pos, f->top_pos); + NSPoint bottomLeft = NSMakePoint(topLeft.x, + /* text-area pixels + decorations. */ + topLeft.y - (height + + FRAME_NS_TITLEBAR_HEIGHT(f) + + FRAME_TOOLBAR_HEIGHT(f))); + NSRect frameRect = [window frameRectForContentRect:NSMakeRect (bottomLeft.x, + bottomLeft.y, + width, + height)]; + if (f->output_data.ns->zooming) + f->output_data.ns->zooming = 0; + /* Usually it seems safe to delay changing the frame size, but when a + series of actions are taken with no redisplay between them then we + can end up using old values so don't delay here. */ + change_frame_size (f, width, height, false, NO, false); + [window setFrame:frameRect display:NO]; + f->size_hint_flags &= ~(XNegative|YNegative); + + unblock_input (); +} + void ns_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) /* -------------------------------------------------------------------------- @@ -5721,6 +5770,7 @@ static Lisp_Object ns_new_font (struct frame *f, Lisp_Object font_object, terminal->fullscreen_hook = ns_fullscreen_hook; terminal->iconify_frame_hook = ns_iconify_frame; terminal->set_window_size_hook = ns_set_window_size; + terminal->set_window_size_and_position_hook = ns_set_window_size_and_position; terminal->set_frame_offset_hook = ns_set_offset; terminal->set_frame_alpha_hook = ns_set_frame_alpha; terminal->set_new_font_hook = ns_new_font;