unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize
@ 2020-03-23 18:13 Andrii Kolomoiets
  2020-03-23 19:22 ` Eli Zaretskii
  2020-03-23 23:54 ` Alan Third
  0 siblings, 2 replies; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-03-23 18:13 UTC (permalink / raw)
  To: 40200

1. emacs -Q
2. (setq frame-inhibit-implied-resize t)
3. M-x toggle-frame-maximized
4. C-x b RET (to open *Messages* buffer)
5. M-x tool-bar-mode

After some up-down mouse scroll, buffer text is drawn incorrectly.

Not sure if image attaches are allowed here, so screenshot is on imgur:
https://imgur.com/a/QSSNePE

In GNU Emacs 28.0.50 (build 2, x86_64-apple-darwin19.3.0, NS appkit-1894.30 Version 10.15.3 (Build 19D76))
 of 2020-03-18 built on muffinmac.local
Windowing system distributor 'Apple', version 10.3.1894
System Description:  Mac OS X 10.15.3





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize
  2020-03-23 18:13 bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize Andrii Kolomoiets
@ 2020-03-23 19:22 ` Eli Zaretskii
  2020-03-23 19:47   ` Andrii Kolomoiets
  2020-03-23 23:54 ` Alan Third
  1 sibling, 1 reply; 24+ messages in thread
From: Eli Zaretskii @ 2020-03-23 19:22 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200

> From: Andrii Kolomoiets <andreyk.mad@gmail.com>
> Date: Mon, 23 Mar 2020 20:13:19 +0200
> 
> 1. emacs -Q
> 2. (setq frame-inhibit-implied-resize t)
> 3. M-x toggle-frame-maximized
> 4. C-x b RET (to open *Messages* buffer)
> 5. M-x tool-bar-mode
> 
> After some up-down mouse scroll, buffer text is drawn incorrectly.

I cannot reproduce this, so it's probably Darwin-specific.

> Not sure if image attaches are allowed here

Of course they are.

Thanks.





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize
  2020-03-23 19:22 ` Eli Zaretskii
@ 2020-03-23 19:47   ` Andrii Kolomoiets
  0 siblings, 0 replies; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-03-23 19:47 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 40200

On 23 Mar 2020, at 21:22, Eli Zaretskii <eliz@gnu.org> wrote:
> 
>> From: Andrii Kolomoiets <andreyk.mad@gmail.com>
>> Date: Mon, 23 Mar 2020 20:13:19 +0200
>> 
>> 1. emacs -Q
>> 2. (setq frame-inhibit-implied-resize t)
>> 3. M-x toggle-frame-maximized
>> 4. C-x b RET (to open *Messages* buffer)
>> 5. M-x tool-bar-mode
>> 
>> After some up-down mouse scroll, buffer text is drawn incorrectly.
> 
> I cannot reproduce this, so it's probably Darwin-specific.

It is Darwin-specific. I marked the subject with "NS". Or should the subject contain "macos" for Darwin-specific bugs?

>> Not sure if image attaches are allowed here
> 
> Of course they are.

Got it, thanks.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize
  2020-03-23 18:13 bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize Andrii Kolomoiets
  2020-03-23 19:22 ` Eli Zaretskii
@ 2020-03-23 23:54 ` Alan Third
  2020-03-25 22:28   ` bug#40200: [PATCH] Fix NS frame resizing issues (bug#40200, bug#28872) Alan Third
  1 sibling, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-03-23 23:54 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200

On Mon, Mar 23, 2020 at 08:13:19PM +0200, Andrii Kolomoiets wrote:
> 1. emacs -Q
> 2. (setq frame-inhibit-implied-resize t)
> 3. M-x toggle-frame-maximized
> 4. C-x b RET (to open *Messages* buffer)
> 5. M-x tool-bar-mode
> 
> After some up-down mouse scroll, buffer text is drawn incorrectly.
> 
> Not sure if image attaches are allowed here, so screenshot is on imgur:
> https://imgur.com/a/QSSNePE

As far as I’m aware images are allowed.

This is surprisingly complicated! It appears that when the tool‐bar is
removed the window doesn’t change size so there is no resize event
sent. I’ve added an NSView resize notification on my local copy and it
now draws OK, but it doesn’t inform Emacs that the frame size has
changed so it leaves a blank space at the bottom of the frame. I think
I’ve seen this happen before on occasion.

It looks to me like the right thing to do here is to add this resize
notification and use it to replace the window resize based system we
use at the moment.

The current resizing code is a little spaghetti‐like as it has built
up over time to do various things, so refactoring it is potentially
troublesome. Perhaps it will simplify things, though.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: [PATCH] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-23 23:54 ` Alan Third
@ 2020-03-25 22:28   ` Alan Third
  2020-03-26 17:35     ` bug#28872: " Andrii Kolomoiets
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-03-25 22:28 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200, 28872, aaronjensen

* src/nsmenu.m (update_frame_tool_bar): Remove reference to
updateFrameSize.
* src/nsterm.h: Remove definition of updateFrameSize.
* src/nsterm.m (ns_set_window_size):
(ns_set_undecorated):
([EmacsView windowDidResize:]):
([EmacsView windowDidExitFullScreen]):
(ns_judge_scroll_bars): Remove references to updateFrameSize.
([EmacsView dealloc]): Unset resize notification.
([EmacsView updateFrameSize:]): Remove function.
([EmacsView viewWillStartLiveResize]):
([EmacsView viewDidResize]): New functions.
([EmacsView initFrameFromEmacs:]): Set up resize notification.
([EmacsView toggleFullScreen:]): Set frame to the size of the
contentview, not the whole window, and remove reference to
updateFrameSize.
---
 src/nsmenu.m |   2 -
 src/nsterm.h |   1 -
 src/nsterm.m | 191 ++++++++++++++++++++++-----------------------------
 3 files changed, 81 insertions(+), 113 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 67f9a45a40..b7e4cbd565 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1141,8 +1141,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
     }
 #endif
 
-  if (oldh != FRAME_TOOLBAR_HEIGHT (f))
-    [view updateFrameSize:YES];
   if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
     {
       view->wait_for_tool_bar = NO;
diff --git a/src/nsterm.h b/src/nsterm.h
index 8396a542f7..c454c1ff36 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -462,7 +462,6 @@ #define NS_DRAW_TO_BUFFER 1
 - (void) setWindowClosing: (BOOL)closing;
 - (EmacsToolbar *) toolbar;
 - (void) deleteWorkingText;
-- (void) updateFrameSize: (BOOL) delay;
 - (void) handleFS;
 - (void) setFSValue: (int)value;
 - (void) toggleFullScreen: (id) sender;
diff --git a/src/nsterm.m b/src/nsterm.m
index 04fc051223..41780c9a42 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1864,7 +1864,6 @@ Hide the window (X11 semantics)
 
   [window setFrame: wr display: YES];
 
-  [view updateFrameSize: NO];
   unblock_input ();
 }
 
@@ -1913,7 +1912,6 @@ Hide the window (X11 semantics)
          so some key presses (TAB) are swallowed by the system.  */
       [window makeFirstResponder: view];
 
-      [view updateFrameSize: NO];
       unblock_input ();
     }
 }
@@ -5024,9 +5022,6 @@ in certain situations (rapid incoming events).
       if ([view judge])
         removed = YES;
     }
-
-  if (removed)
-    [eview updateFrameSize: NO];
 }
 
 /* ==========================================================================
@@ -6198,6 +6193,13 @@ - (void) setWindowClosing: (BOOL)closing
 - (void)dealloc
 {
   NSTRACE ("[EmacsView dealloc]");
+
+  /* Clear the view resize notification.  */
+  [[NSNotificationCenter defaultCenter]
+    removeObserver:self
+              name:NSViewFrameDidChangeNotification
+            object:nil];
+
   [toolbar release];
   if (fs_state == FULLSCREEN_BOTH)
     [nonfs_window release];
@@ -7039,103 +7041,6 @@ - (BOOL)windowShouldClose: (id)sender
   return NO;
 }
 
-- (void) updateFrameSize: (BOOL) delay
-{
-  NSWindow *window = [self window];
-  NSRect wr = [window frame];
-  int extra = 0;
-  int oldc = cols, oldr = rows;
-  int oldw = FRAME_PIXEL_WIDTH (emacsframe);
-  int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
-  int neww, newh;
-
-  NSTRACE ("[EmacsView updateFrameSize:]");
-  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
-  NSTRACE_RECT ("Original frame", wr);
-  NSTRACE_MSG  ("Original columns: %d", cols);
-  NSTRACE_MSG  ("Original rows: %d", rows);
-
-  if (! [self isFullscreen])
-    {
-      int toolbar_height;
-#ifdef NS_IMPL_GNUSTEP
-      // GNUstep does not always update the tool bar height.  Force it.
-      if (toolbar && [toolbar isVisible])
-          update_frame_tool_bar (emacsframe);
-#endif
-
-      toolbar_height = FRAME_TOOLBAR_HEIGHT (emacsframe);
-      if (toolbar_height < 0)
-        toolbar_height = 35;
-
-      extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
-        + toolbar_height;
-    }
-
-  if (wait_for_tool_bar)
-    {
-      /* The toolbar height is always 0 in fullscreen and undecorated
-         frames, so don't wait for it to become available.  */
-      if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0
-          && FRAME_UNDECORATED (emacsframe) == false
-          && ! [self isFullscreen])
-        {
-          NSTRACE_MSG ("Waiting for toolbar");
-          return;
-        }
-      wait_for_tool_bar = NO;
-    }
-
-  neww = (int)wr.size.width - emacsframe->border_width;
-  newh = (int)wr.size.height - extra;
-
-  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
-  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);
-
-  if (cols < MINWIDTH)
-    cols = MINWIDTH;
-
-  if (rows < MINHEIGHT)
-    rows = MINHEIGHT;
-
-  NSTRACE_MSG ("New columns: %d", cols);
-  NSTRACE_MSG ("New rows: %d", rows);
-
-  if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
-    {
-      NSView *view = FRAME_NS_VIEW (emacsframe);
-
-      change_frame_size (emacsframe,
-                         FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
-                         FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
-                         0, delay, 0, 1);
-      SET_FRAME_GARBAGED (emacsframe);
-      cancel_mouse_face (emacsframe);
-
-      /* The next two lines set the frame to the same size as we've
-         already set above.  We need to do this when we switch back
-         from non-native fullscreen, in other circumstances it appears
-         to be a noop.  (bug#28872) */
-      wr = NSMakeRect (0, 0, neww, newh);
-      [view setFrame: wr];
-#ifdef NS_DRAW_TO_BUFFER
-      [self createDrawingBuffer];
-#endif
-
-      // To do: consider using [NSNotificationCenter postNotificationName:].
-      [self windowDidMove: // Update top/left.
-	      [NSNotification notificationWithName:NSWindowDidMoveNotification
-					    object:[view window]]];
-    }
-  else
-    {
-      NSTRACE_MSG ("No change");
-    }
-}
 
 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
 /* Normalize frame to gridded text size.  */
@@ -7277,15 +7182,21 @@ - (void)windowDidResize: (NSNotification *)notification
   sz = [self windowWillResize: theWindow toSize: sz];
 #endif /* NS_IMPL_GNUSTEP */
 
-  if (cols > 0 && rows > 0)
-    {
-      [self updateFrameSize: YES];
-    }
-
   ns_send_appdefined (-1);
 }
 
 #ifdef NS_IMPL_COCOA
+- (void)viewWillStartLiveResize
+{
+  NSTRACE ("[EmacsView viewWillStartLiveResize]");
+
+  /* We just want a blank frame during live resizes.  Redisplaying the
+     contents is too slow, and stretching the contents looks
+     weird.  */
+  ns_clear_frame (emacsframe);
+}
+
+
 - (void)viewDidEndLiveResize
 {
   NSTRACE ("[EmacsView viewDidEndLiveResize]");
@@ -7302,6 +7213,60 @@ - (void)viewDidEndLiveResize
 #endif /* NS_IMPL_COCOA */
 
 
+- (void)viewDidResize:(NSNotification *)notification
+{
+  NSRect frame = [self frame];
+  int oldw, oldh;
+  int neww, newh;
+
+#ifdef NS_DRAW_TO_BUFFER
+  CGFloat scale = [[self window] backingScaleFactor];
+  oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
+  oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
+#else
+  oldw = FRAME_PIXEL_WIDTH (emacsframe);
+  oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+#endif
+  neww = (int)NSWidth (frame);
+  newh = (int)NSHeight (frame);
+
+  NSTRACE ("[EmacsView viewDidResize]");
+  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+
+  /* Don't want to do anything when the actual view size hasn't
+     changed. */
+  if ((oldh == newh && oldw == neww))
+    {
+      NSTRACE_MSG ("No change");
+      return;
+    }
+
+  cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
+  rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
+
+  if (cols < MINWIDTH)
+    cols = MINWIDTH;
+
+  if (rows < MINHEIGHT)
+    rows = MINHEIGHT;
+
+  NSTRACE_MSG ("New columns: %d", cols);
+  NSTRACE_MSG ("New rows: %d", rows);
+
+  change_frame_size (emacsframe,
+                     FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
+                     FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
+                     0, YES, 0, 1);
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+  ns_clear_frame (emacsframe);
+  SET_FRAME_GARBAGED (emacsframe);
+  cancel_mouse_face (emacsframe);
+}
+
+
 - (void)windowDidBecomeKey: (NSNotification *)notification
 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
 {
@@ -7456,6 +7421,13 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   [self initWithFrame: r];
   [self setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable];
 
+  /* Set up view resize notifications.  */
+  [self setPostsFrameChangedNotifications:YES];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector (viewDidResize:)
+             name:NSViewFrameDidChangeNotification object:nil];
+
   FRAME_NS_VIEW (f) = self;
   emacsframe = f;
 #ifdef NS_IMPL_COCOA
@@ -7902,7 +7874,6 @@ - (void)windowDidExitFullScreen /* provided for direct calls */
     {
       [toolbar setVisible:YES];
       update_frame_tool_bar (emacsframe);
-      [self updateFrameSize:YES];
       [[self window] display];
     }
   else
@@ -8115,11 +8086,11 @@ - (void)toggleFullScreen: (id)sender
       // send notifications.
 
       [self windowWillExitFullScreen];
-      [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
+      [fw setFrame:[[w contentView] frame]
+                    display:YES animate:ns_use_fullscreen_animation];
       [fw close];
       [w makeKeyAndOrderFront:NSApp];
       [self windowDidExitFullScreen];
-      [self updateFrameSize:YES];
     }
 }
 
-- 
2.24.0


-- 
Alan Third





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-25 22:28   ` bug#40200: [PATCH] Fix NS frame resizing issues (bug#40200, bug#28872) Alan Third
@ 2020-03-26 17:35     ` Andrii Kolomoiets
  2020-03-26 21:21       ` bug#28872: [PATCH v2] " Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-03-26 17:35 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, 28872, aaronjensen

[-- Attachment #1: Type: text/plain, Size: 1026 bytes --]

On 26 Mar 2020, at 00:28, Alan Third <alan@idiocy.org> wrote:
> 
> * src/nsmenu.m (update_frame_tool_bar): Remove reference to
> updateFrameSize.
> * src/nsterm.h: Remove definition of updateFrameSize.
> * src/nsterm.m (ns_set_window_size):
> (ns_set_undecorated):
> ([EmacsView windowDidResize:]):
> ([EmacsView windowDidExitFullScreen]):
> (ns_judge_scroll_bars): Remove references to updateFrameSize.
> ([EmacsView dealloc]): Unset resize notification.
> ([EmacsView updateFrameSize:]): Remove function.
> ([EmacsView viewWillStartLiveResize]):
> ([EmacsView viewDidResize]): New functions.
> ([EmacsView initFrameFromEmacs:]): Set up resize notification.
> ([EmacsView toggleFullScreen:]): Set frame to the size of the
> contentview, not the whole window, and remove reference to
> updateFrameSize.

Thanks, Alan!

I've installed this patch and will watch for any issues.

For now Emacs is crashing on fullscreen frame deletion:
1. emacs -Q
2. C-x 5 2
3. F11
4. C-x 5 0

Backtrace from macos problem reporter is attached.

[-- Attachment #2: emacs-crash-fs-close.txt --]
[-- Type: text/plain, Size: 6332 bytes --]

OS Version:            Mac OS X 10.15.3 (19D76)

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGABRT)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000020
Exception Note:        EXC_CORPSE_NOTIFY

VM Regions Near 0x20:
-->
    __TEXT                 000000010254b000-0000000102792000 [ 2332K] r-x/r-x SM=COW  /Users/USER/*/Emacs.app/Contents/MacOS/Emacs

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff6d2097fa __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff6d2c6bc1 pthread_kill + 432
2   libsystem_c.dylib             	0x00007fff6d1203a2 raise + 26
3   org.gnu.Emacs                 	0x0000000102751769 terminate_due_to_signal + 153 (emacs.c:404)
4   org.gnu.Emacs                 	0x00000001027520ab emacs_abort + 15
5   org.gnu.Emacs                 	0x0000000102719e70 ns_term_shutdown + 80 (lisp.h:1586)
6   org.gnu.Emacs                 	0x00000001026097f4 shut_down_emacs + 340 (emacs.c:2462)
7   org.gnu.Emacs                 	0x0000000102751736 terminate_due_to_signal + 102 (emacs.c:385)
8   org.gnu.Emacs                 	0x0000000102629fce handle_fatal_signal + 14
9   org.gnu.Emacs                 	0x000000010262a051 deliver_thread_signal + 129
10  org.gnu.Emacs                 	0x0000000102628a09 deliver_fatal_thread_signal + 9
11  org.gnu.Emacs                 	0x000000010262a108 handle_sigsegv + 168
12  libsystem_platform.dylib      	0x00007fff6d2bb42d _sigtramp + 29
13  ???                           	000000000000000000 0 + 0
14  com.apple.CoreFoundation      	0x00007fff35a1435f __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
15  com.apple.CoreFoundation      	0x00007fff35a142f3 ___CFXRegistrationPost1_block_invoke + 63
16  com.apple.CoreFoundation      	0x00007fff35a14268 _CFXRegistrationPost1 + 372
17  com.apple.CoreFoundation      	0x00007fff35a13ebe ___CFXNotificationPost_block_invoke + 97
18  com.apple.CoreFoundation      	0x00007fff359e37e2 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1575
19  com.apple.CoreFoundation      	0x00007fff359e2c82 _CFXNotificationPost + 1351
20  com.apple.AppKit              	0x00007fff32c23719 -[NSView _postFrameChangeNotification] + 304
21  com.apple.AppKit              	0x00007fff32c1c1a9 -[NSView setFrameSize:] + 2917
22  com.apple.AppKit              	0x00007fff32c2dca2 -[NSView setFrame:] + 423
23  org.gnu.Emacs                 	0x000000010272027c -[EmacsView setFrame:] + 60 (nsterm.m:7346)
24  com.apple.AppKit              	0x00007fff32c412ee -[NSView resizeWithOldSuperviewSize:] + 1193
25  com.apple.AppKit              	0x00007fff32c40a13 -[NSView resizeSubviewsWithOldSize:] + 525
26  com.apple.AppKit              	0x00007fff32c1bcf6 -[NSView setFrameSize:] + 1714
27  com.apple.AppKit              	0x00007fff32c2dca2 -[NSView setFrame:] + 423
28  com.apple.AppKit              	0x00007fff32c3bd38 -[NSThemeFrame setStyleMask:] + 874
29  com.apple.AppKit              	0x00007fff32c3b89e __25-[NSWindow setStyleMask:]_block_invoke + 1939
30  com.apple.AppKit              	0x00007fff32c3b0b3 NSPerformVisuallyAtomicChange + 132
31  com.apple.AppKit              	0x00007fff32c3afbc -[NSWindow setStyleMask:] + 184
32  com.apple.AppKit              	0x00007fff3328d23d -[_NSWindowExitFullScreenTransitionController setupWindowForAfterFullScreenExit] + 106
33  com.apple.AppKit              	0x00007fff33509740 __46-[_NSExitFullScreenTransitionController start]_block_invoke_3 + 57
34  libdispatch.dylib             	0x00007fff6d068583 _dispatch_call_block_and_release + 12
35  libdispatch.dylib             	0x00007fff6d06950e _dispatch_client_callout + 8
36  libdispatch.dylib             	0x00007fff6d074bc4 _dispatch_main_queue_callback_4CF + 1105
37  com.apple.CoreFoundation      	0x00007fff35a5de00 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
38  com.apple.CoreFoundation      	0x00007fff35a1db8a __CFRunLoopRun + 2370
39  com.apple.CoreFoundation      	0x00007fff35a1cbd3 CFRunLoopRunSpecific + 499
40  com.apple.HIToolbox           	0x00007fff3457265d RunCurrentEventLoopInMode + 292
41  com.apple.HIToolbox           	0x00007fff345722a9 ReceiveNextEventCommon + 356
42  com.apple.HIToolbox           	0x00007fff34572127 _BlockUntilNextEventMatchingListInModeWithFilter + 64
43  com.apple.AppKit              	0x00007fff32be2ba4 _DPSNextEvent + 990
44  com.apple.AppKit              	0x00007fff32be1380 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352
45  com.apple.AppKit              	0x00007fff32bd309e -[NSApplication run] + 658
46  org.gnu.Emacs                 	0x000000010271a02d -[EmacsApp run] + 333 (nsterm.m:5644)
47  org.gnu.Emacs                 	0x0000000102726bcc ns_read_socket + 668 (nsterm.m:4598)
48  org.gnu.Emacs                 	0x0000000102617035 gobble_input + 245 (keyboard.c:6887)
49  org.gnu.Emacs                 	0x000000010261a01a detect_input_pending + 250 (lisp.h:1272)
50  org.gnu.Emacs                 	0x00000001026e23ea wait_reading_process_output + 3194 (process.c:5491)
51  org.gnu.Emacs                 	0x00000001025525e8 sit_for + 312 (dispnew.c:6055)
52  org.gnu.Emacs                 	0x0000000102611f1a read_char + 5210 (keyboard.c:2738)
53  org.gnu.Emacs                 	0x000000010260ef2a read_key_sequence + 1722 (keyboard.c:9549)
54  org.gnu.Emacs                 	0x000000010260d72c command_loop_1 + 1340 (keyboard.c:1350)
55  org.gnu.Emacs                 	0x00000001026943d7 internal_condition_case + 263 (eval.c:1357)
56  org.gnu.Emacs                 	0x000000010261d740 command_loop_2 + 48 (lisp.h:1272)
57  org.gnu.Emacs                 	0x0000000102693beb internal_catch + 267 (eval.c:1118)
58  org.gnu.Emacs                 	0x0000000102751b35 command_loop.cold.1 + 69
59  org.gnu.Emacs                 	0x000000010260c7f3 command_loop + 131
60  org.gnu.Emacs                 	0x000000010260c723 recursive_edit_1 + 115 (keyboard.c:714)
61  org.gnu.Emacs                 	0x000000010260c97b Frecursive_edit + 347 (keyboard.c:787)
62  org.gnu.Emacs                 	0x000000010260b561 main + 7425 (emacs.c:2036)
63  libdyld.dylib                 	0x00007fff6d0c27fd start + 1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v2] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-26 17:35     ` bug#28872: " Andrii Kolomoiets
@ 2020-03-26 21:21       ` Alan Third
  2020-03-27  9:45         ` Andrii Kolomoiets
  2020-03-27 13:22         ` Andrii Kolomoiets
  0 siblings, 2 replies; 24+ messages in thread
From: Alan Third @ 2020-03-26 21:21 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200, 28872, aaronjensen

* src/nsmenu.m (update_frame_tool_bar): Remove reference to
updateFrameSize.
* src/nsterm.h: ([EmacsView updateFrameSize]):
([EmacsView setRows:andColumns:]): Remove unused
method definitions.
* src/nsterm.m (ns_set_window_size):
(ns_set_undecorated):
([EmacsView windowDidResize:]):
([EmacsView windowDidExitFullScreen]):
(ns_judge_scroll_bars): Remove references to updateFrameSize.
([EmacsView dealloc]): Unset resize notification and release buffer.
([EmacsView updateFrameSize:]): Remove function.
([EmacsView windowWillResize:toSize:]): Move some code to
viewDidResize.
([EmacsView viewDidResize]): New function.
([EmacsView initFrameFromEmacs:]): Set up resize notification and move
buffer creation until after the prerequisite objects are created.
([EmacsView toggleFullScreen:]): Set frame to the size of the
contentview, not the whole window, and remove reference to
updateFrameSize.
([EmacsView setRows:andColumns:]): Remove unused method.
---
Hopefully this works better.

src/nsmenu.m |   2 -
 src/nsterm.h |   3 -
 src/nsterm.m | 189 ++++++++++++++++++---------------------------------
 3 files changed, 68 insertions(+), 126 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 67f9a45a40..b7e4cbd565 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1141,8 +1141,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
     }
 #endif
 
-  if (oldh != FRAME_TOOLBAR_HEIGHT (f))
-    [view updateFrameSize:YES];
   if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
     {
       view->wait_for_tool_bar = NO;
diff --git a/src/nsterm.h b/src/nsterm.h
index 8396a542f7..3c2e4c2b07 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -439,7 +439,6 @@ #define NS_DRAW_TO_BUFFER 1
 #endif
 @public
    struct frame *emacsframe;
-   int rows, cols;
    int scrollbarsNeedingUpdate;
    EmacsToolbar *toolbar;
    NSRect ns_userRect;
@@ -458,11 +457,9 @@ #define NS_DRAW_TO_BUFFER 1
 /* Emacs-side interface */
 - (instancetype) initFrameFromEmacs: (struct frame *) f;
 - (void) createToolbar: (struct frame *)f;
-- (void) setRows: (int) r andColumns: (int) c;
 - (void) setWindowClosing: (BOOL)closing;
 - (EmacsToolbar *) toolbar;
 - (void) deleteWorkingText;
-- (void) updateFrameSize: (BOOL) delay;
 - (void) handleFS;
 - (void) setFSValue: (int)value;
 - (void) toggleFullScreen: (id) sender;
diff --git a/src/nsterm.m b/src/nsterm.m
index 04fc051223..95ab4390a0 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1864,7 +1864,6 @@ Hide the window (X11 semantics)
 
   [window setFrame: wr display: YES];
 
-  [view updateFrameSize: NO];
   unblock_input ();
 }
 
@@ -1913,7 +1912,6 @@ Hide the window (X11 semantics)
          so some key presses (TAB) are swallowed by the system.  */
       [window makeFirstResponder: view];
 
-      [view updateFrameSize: NO];
       unblock_input ();
     }
 }
@@ -5024,9 +5022,6 @@ in certain situations (rapid incoming events).
       if ([view judge])
         removed = YES;
     }
-
-  if (removed)
-    [eview updateFrameSize: NO];
 }
 
 /* ==========================================================================
@@ -6198,6 +6193,15 @@ - (void) setWindowClosing: (BOOL)closing
 - (void)dealloc
 {
   NSTRACE ("[EmacsView dealloc]");
+
+  /* Clear the view resize notification.  */
+  [[NSNotificationCenter defaultCenter]
+    removeObserver:self
+              name:NSViewFrameDidChangeNotification
+            object:nil];
+
+  CGContextRelease (drawingBuffer);
+
   [toolbar release];
   if (fs_state == FULLSCREEN_BOTH)
     [nonfs_window release];
@@ -7039,108 +7043,12 @@ - (BOOL)windowShouldClose: (id)sender
   return NO;
 }
 
-- (void) updateFrameSize: (BOOL) delay
-{
-  NSWindow *window = [self window];
-  NSRect wr = [window frame];
-  int extra = 0;
-  int oldc = cols, oldr = rows;
-  int oldw = FRAME_PIXEL_WIDTH (emacsframe);
-  int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
-  int neww, newh;
-
-  NSTRACE ("[EmacsView updateFrameSize:]");
-  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
-  NSTRACE_RECT ("Original frame", wr);
-  NSTRACE_MSG  ("Original columns: %d", cols);
-  NSTRACE_MSG  ("Original rows: %d", rows);
-
-  if (! [self isFullscreen])
-    {
-      int toolbar_height;
-#ifdef NS_IMPL_GNUSTEP
-      // GNUstep does not always update the tool bar height.  Force it.
-      if (toolbar && [toolbar isVisible])
-          update_frame_tool_bar (emacsframe);
-#endif
-
-      toolbar_height = FRAME_TOOLBAR_HEIGHT (emacsframe);
-      if (toolbar_height < 0)
-        toolbar_height = 35;
-
-      extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
-        + toolbar_height;
-    }
-
-  if (wait_for_tool_bar)
-    {
-      /* The toolbar height is always 0 in fullscreen and undecorated
-         frames, so don't wait for it to become available.  */
-      if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0
-          && FRAME_UNDECORATED (emacsframe) == false
-          && ! [self isFullscreen])
-        {
-          NSTRACE_MSG ("Waiting for toolbar");
-          return;
-        }
-      wait_for_tool_bar = NO;
-    }
-
-  neww = (int)wr.size.width - emacsframe->border_width;
-  newh = (int)wr.size.height - extra;
-
-  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
-  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);
-
-  if (cols < MINWIDTH)
-    cols = MINWIDTH;
-
-  if (rows < MINHEIGHT)
-    rows = MINHEIGHT;
-
-  NSTRACE_MSG ("New columns: %d", cols);
-  NSTRACE_MSG ("New rows: %d", rows);
-
-  if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
-    {
-      NSView *view = FRAME_NS_VIEW (emacsframe);
-
-      change_frame_size (emacsframe,
-                         FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
-                         FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
-                         0, delay, 0, 1);
-      SET_FRAME_GARBAGED (emacsframe);
-      cancel_mouse_face (emacsframe);
-
-      /* The next two lines set the frame to the same size as we've
-         already set above.  We need to do this when we switch back
-         from non-native fullscreen, in other circumstances it appears
-         to be a noop.  (bug#28872) */
-      wr = NSMakeRect (0, 0, neww, newh);
-      [view setFrame: wr];
-#ifdef NS_DRAW_TO_BUFFER
-      [self createDrawingBuffer];
-#endif
-
-      // To do: consider using [NSNotificationCenter postNotificationName:].
-      [self windowDidMove: // Update top/left.
-	      [NSNotification notificationWithName:NSWindowDidMoveNotification
-					    object:[view window]]];
-    }
-  else
-    {
-      NSTRACE_MSG ("No change");
-    }
-}
 
 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
 /* Normalize frame to gridded text size.  */
 {
   int extra = 0;
+  int cols, rows;
 
   NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
            NSTRACE_ARG_SIZE (frameSize));
@@ -7277,11 +7185,6 @@ - (void)windowDidResize: (NSNotification *)notification
   sz = [self windowWillResize: theWindow toSize: sz];
 #endif /* NS_IMPL_GNUSTEP */
 
-  if (cols > 0 && rows > 0)
-    {
-      [self updateFrameSize: YES];
-    }
-
   ns_send_appdefined (-1);
 }
 
@@ -7302,6 +7205,51 @@ - (void)viewDidEndLiveResize
 #endif /* NS_IMPL_COCOA */
 
 
+- (void)viewDidResize:(NSNotification *)notification
+{
+  NSRect frame = [self frame];
+  int oldw, oldh, neww, newh;
+
+  if (! FRAME_LIVE_P (emacsframe))
+    return;
+
+#ifdef NS_DRAW_TO_BUFFER
+  CGFloat scale = [[self window] backingScaleFactor];
+  oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
+  oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
+#else
+  oldw = FRAME_PIXEL_WIDTH (emacsframe);
+  oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+#endif
+  neww = (int)NSWidth (frame);
+  newh = (int)NSHeight (frame);
+
+  NSTRACE ("[EmacsView viewDidResize]");
+
+  /* Don't want to do anything when the view size hasn't changed. */
+  if ((oldh == newh && oldw == neww))
+    {
+      NSTRACE_MSG ("No change");
+      return;
+    }
+
+  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+
+  change_frame_size (emacsframe,
+                     FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
+                     FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
+                     0, YES, 0, 1);
+
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+  ns_clear_frame (emacsframe);
+  SET_FRAME_GARBAGED (emacsframe);
+  cancel_mouse_face (emacsframe);
+}
+
+
 - (void)windowDidBecomeKey: (NSNotification *)notification
 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
 {
@@ -7463,10 +7411,6 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   maximizing_resize = NO;
 #endif
 
-#ifdef NS_DRAW_TO_BUFFER
-  [self createDrawingBuffer];
-#endif
-
   win = [[EmacsWindow alloc]
             initWithContentRect: r
                       styleMask: (FRAME_UNDECORATED (f)
@@ -7572,6 +7516,17 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   [NSApp registerServicesMenuSendTypes: ns_send_types
                            returnTypes: [NSArray array]];
 
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+
+  /* Set up view resize notifications.  */
+  [self setPostsFrameChangedNotifications:YES];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector (viewDidResize:)
+             name:NSViewFrameDidChangeNotification object:nil];
+
   /* macOS Sierra automatically enables tabbed windows.  We can't
      allow this to be enabled until it's available on a Free system.
      Currently it only happens by accident and is buggy anyway.  */
@@ -7902,7 +7857,6 @@ - (void)windowDidExitFullScreen /* provided for direct calls */
     {
       [toolbar setVisible:YES];
       update_frame_tool_bar (emacsframe);
-      [self updateFrameSize:YES];
       [[self window] display];
     }
   else
@@ -8115,11 +8069,11 @@ - (void)toggleFullScreen: (id)sender
       // send notifications.
 
       [self windowWillExitFullScreen];
-      [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
+      [fw setFrame:[[w contentView] frame]
+                    display:YES animate:ns_use_fullscreen_animation];
       [fw close];
       [w makeKeyAndOrderFront:NSApp];
       [self windowDidExitFullScreen];
-      [self updateFrameSize:YES];
     }
 }
 
@@ -8628,13 +8582,6 @@ - (instancetype)setMiniwindowImage: (BOOL) setMini
 }
 
 
-- (void) setRows: (int) r andColumns: (int) c
-{
-  NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
-  rows = r;
-  cols = c;
-}
-
 - (int) fullscreenState
 {
   return fs_state;
-- 
2.24.0


-- 
Alan Third





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v2] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-26 21:21       ` bug#28872: [PATCH v2] " Alan Third
@ 2020-03-27  9:45         ` Andrii Kolomoiets
  2020-03-27 13:22         ` Andrii Kolomoiets
  1 sibling, 0 replies; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-03-27  9:45 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, 28872, aaronjensen

[-- Attachment #1: Type: text/plain, Size: 601 bytes --]

On 26 Mar 2020, at 23:21, Alan Third <alan@idiocy.org> wrote:
> 
> Hopefully this works better.
> 

It is!

But can the following line be removed?

> +  ns_clear_frame (emacsframe);

This removal resolves following issues for me:

1. Frames have white background color on creation.  This flashing is noticeable while using dark background for default face.

2. I'm experimenting with enabling macos native tabs by replacing NSWindowTabbingModeDisallowed with NSWindowTabbingModePreferred in nsterm.m.  Crash occurs on tabbed frame deletion (s-n s-w). Backtrace is attached.

Thanks!

[-- Attachment #2: emacs-crash-tab-close.txt --]
[-- Type: text/plain, Size: 5618 bytes --]

Exception Type:        EXC_BAD_ACCESS (SIGABRT)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000020
Exception Note:        EXC_CORPSE_NOTIFY

VM Regions Near 0x20:
-->
    __TEXT                 000000010aac2000-000000010ad09000 [ 2332K] r-x/r-x SM=COW  /Users/USER/*/Emacs.app/Contents/MacOS/Emacs

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libsystem_kernel.dylib        	0x00007fff6d2097fa __pthread_kill + 10
1   libsystem_pthread.dylib       	0x00007fff6d2c6bc1 pthread_kill + 432
2   libsystem_c.dylib             	0x00007fff6d1203a2 raise + 26
3   org.gnu.Emacs                 	0x000000010acc87a9 terminate_due_to_signal + 153 (emacs.c:404)
4   org.gnu.Emacs                 	0x000000010acc90eb emacs_abort + 15
5   org.gnu.Emacs                 	0x000000010ac90f60 ns_term_shutdown + 80 (lisp.h:1586)
6   org.gnu.Emacs                 	0x000000010ab808e4 shut_down_emacs + 340 (emacs.c:2462)
7   org.gnu.Emacs                 	0x000000010acc8776 terminate_due_to_signal + 102 (emacs.c:385)
8   org.gnu.Emacs                 	0x000000010aba10be handle_fatal_signal + 14
9   org.gnu.Emacs                 	0x000000010aba1141 deliver_thread_signal + 129
10  org.gnu.Emacs                 	0x000000010ab9faf9 deliver_fatal_thread_signal + 9
11  org.gnu.Emacs                 	0x000000010aba11f8 handle_sigsegv + 168
12  libsystem_platform.dylib      	0x00007fff6d2bb42d _sigtramp + 29
13  ???                           	000000000000000000 0 + 0
14  com.apple.CoreFoundation      	0x00007fff35a1435f __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
15  com.apple.CoreFoundation      	0x00007fff35a142f3 ___CFXRegistrationPost1_block_invoke + 63
16  com.apple.CoreFoundation      	0x00007fff35a14268 _CFXRegistrationPost1 + 372
17  com.apple.CoreFoundation      	0x00007fff35a13ebe ___CFXNotificationPost_block_invoke + 97
18  com.apple.CoreFoundation      	0x00007fff359e37e2 -[_CFXNotificationRegistrar find:object:observer:enumerator:] + 1575
19  com.apple.CoreFoundation      	0x00007fff359e2c82 _CFXNotificationPost + 1351
20  com.apple.AppKit              	0x00007fff32c23719 -[NSView _postFrameChangeNotification] + 304
21  com.apple.AppKit              	0x00007fff32c1c1a9 -[NSView setFrameSize:] + 2917
22  com.apple.AppKit              	0x00007fff32c2dca2 -[NSView setFrame:] + 423
23  org.gnu.Emacs                 	0x000000010ac972ac -[EmacsView setFrame:] + 60 (nsterm.m:7329)
24  com.apple.AppKit              	0x00007fff32c412ee -[NSView resizeWithOldSuperviewSize:] + 1193
25  com.apple.AppKit              	0x00007fff32c40a13 -[NSView resizeSubviewsWithOldSize:] + 525
26  com.apple.AppKit              	0x00007fff32c1bcf6 -[NSView setFrameSize:] + 1714
27  com.apple.AppKit              	0x00007fff32c2dca2 -[NSView setFrame:] + 423
28  com.apple.AppKit              	0x00007fff32c604f7 -[NSThemeFrame _relayoutAuxiliaryViewsOfType:] + 149
29  com.apple.AppKit              	0x00007fff32c6044f -[NSThemeFrame relayoutAuxiliaryViewsOfType:] + 27
30  com.apple.AppKit              	0x00007fff32e284fe -[NSTitlebarViewController removeChildViewControllerAtIndex:] + 430
31  com.apple.AppKit              	0x00007fff3341b9f1 -[NSWindowStackController _removeTabBarAccessoryViewControllerForWindow:] + 212
32  com.apple.AppKit              	0x00007fff3341cc7a -[NSWindowStackController removeWindow:] + 297
33  com.apple.AppKit              	0x00007fff32e988af -[NSWindow(NSWindowTabbing) _doTabbedWindowCleanupForOrderOut] + 97
34  com.apple.AppKit              	0x00007fff3347be55 -[NSWindow _finishClosingWindow] + 73
35  com.apple.AppKit              	0x00007fff32f590cd -[NSWindow _close] + 352
36  org.gnu.Emacs                 	0x000000010ac8dd4a ns_free_frame_resources + 202 (nsterm.m:1705)
37  org.gnu.Emacs                 	0x000000010ac9fd5a ns_destroy_window + 106 (nsterm.m:1733)
38  org.gnu.Emacs                 	0x000000010aad1faa delete_frame + 1642 (frame.c:2137)
39  org.gnu.Emacs                 	0x000000010ac0d891 funcall_subr + 257
40  org.gnu.Emacs                 	0x000000010ac0ce7b Ffuncall + 843
41  org.gnu.Emacs                 	0x000000010ac06459 Ffuncall_interactively + 73 (callint.c:254)
42  org.gnu.Emacs                 	0x000000010ac0ce7b Ffuncall + 843
43  org.gnu.Emacs                 	0x000000010ac07948 Fcall_interactively + 5336
44  org.gnu.Emacs                 	0x000000010ac0d8b1 funcall_subr + 289
45  org.gnu.Emacs                 	0x000000010ac0ce7b Ffuncall + 843
46  org.gnu.Emacs                 	0x000000010ac50737 exec_byte_code + 1815 (bytecode.c:633)
47  org.gnu.Emacs                 	0x000000010ac0ce19 Ffuncall + 745
48  org.gnu.Emacs                 	0x000000010ac0d4ec call1 + 44
49  org.gnu.Emacs                 	0x000000010ab84ab9 command_loop_1 + 2009 (lisp.h:1272)
50  org.gnu.Emacs                 	0x000000010ac0b4c7 internal_condition_case + 263 (eval.c:1357)
51  org.gnu.Emacs                 	0x000000010ab94830 command_loop_2 + 48 (lisp.h:1272)
52  org.gnu.Emacs                 	0x000000010ac0acdb internal_catch + 267 (eval.c:1118)
53  org.gnu.Emacs                 	0x000000010acc8b75 command_loop.cold.1 + 69
54  org.gnu.Emacs                 	0x000000010ab838e3 command_loop + 131
55  org.gnu.Emacs                 	0x000000010ab83813 recursive_edit_1 + 115 (keyboard.c:714)
56  org.gnu.Emacs                 	0x000000010ab83a6b Frecursive_edit + 347 (keyboard.c:787)
57  org.gnu.Emacs                 	0x000000010ab82651 main + 7425 (emacs.c:2036)
58  libdyld.dylib                 	0x00007fff6d0c27fd start + 1

^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v2] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-26 21:21       ` bug#28872: [PATCH v2] " Alan Third
  2020-03-27  9:45         ` Andrii Kolomoiets
@ 2020-03-27 13:22         ` Andrii Kolomoiets
  2020-03-28  1:56           ` Alan Third
  1 sibling, 1 reply; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-03-27 13:22 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, 28872, aaronjensen

On 26 Mar 2020, at 23:21, Alan Third <alan@idiocy.org> wrote:
> Hopefully this works better.

Found another changed behavior:
1. emacs -Q
2. (setq test/frame (make-frame `((parent-frame . ,(selected-frame)))))
3. (modify-frame-parameters test/frame '((height . 1) (top . (- 40))))

Old behavior: child frame is at bottom of the parent frame.

New behavior: child frame is at top of the parent frame.
Child frame moves to bottom after code from step 3 applied one more time.

Step 3 can be replaced with these two steps to achieve old behavior:
(modify-frame-parameters test/frame '((height . 1)))
(modify-frame-parameters test/frame '((top . (- 40))))





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v2] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-27 13:22         ` Andrii Kolomoiets
@ 2020-03-28  1:56           ` Alan Third
  2020-04-04 14:17             ` bug#40200: [PATCH v3] " Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-03-28  1:56 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200, 28872, aaronjensen

On Fri, Mar 27, 2020 at 03:22:08PM +0200, Andrii Kolomoiets wrote:
> On 26 Mar 2020, at 23:21, Alan Third <alan@idiocy.org> wrote:
> > Hopefully this works better.
> 
> Found another changed behavior:
> 1. emacs -Q
> 2. (setq test/frame (make-frame `((parent-frame . ,(selected-frame)))))
> 3. (modify-frame-parameters test/frame '((height . 1) (top . (- 40))))
> 
> Old behavior: child frame is at bottom of the parent frame.

This is wrong.

> New behavior: child frame is at top of the parent frame.

This is wrong too.

> Child frame moves to bottom after code from step 3 applied one more time.

Still wrong.

The bottom of the child frame should be 40 pixels from the bottom of
the parent frame.

This is quite annoying, it means Emacs 27 behaves wrongly. I wonder if
Emacs 26 does too, or has it been broken the whole time?

> Step 3 can be replaced with these two steps to achieve old behavior:
> (modify-frame-parameters test/frame '((height . 1)))
> (modify-frame-parameters test/frame '((top . (- 40))))

I inadvertently made order of operations matter when they shouldn’t.
I’ve got a fix for this, but it’s opening up a whole other can of
worms regarding frame positioning and the reporting of positions.

I think I know what to do but the last time I worked on this we had a
lot of edge cases that weren’t easy to test, with multiple monitors
and spaces. I think I’ll have to look at the old bug reports to work
out how we handle that.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: [PATCH v3] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-03-28  1:56           ` Alan Third
@ 2020-04-04 14:17             ` Alan Third
  2020-04-06  6:57               ` Andrii Kolomoiets
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-04-04 14:17 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200, 28872, aaronjensen

* src/nsmenu.m (update_frame_tool_bar): Remove reference to
updateFrameSize.
* src/nsterm.h: ([EmacsView updateFrameSize]):
([EmacsView setRows:andColumns:]): Remove unused
method definitions.
(NS_PARENT_WINDOW_LEFT_POS):
(NS_PARENT_WINDOW_TOP_POS): Move to nsterm.m.
* src/nsterm.m (ns_parent_window_rect): New function.
(NS_PARENT_WINDOW_LEFT_POS):
(NS_PARENT_WINDOW_TOP_POS): Move to nsterm.m and simplify.
(ns_set_offset): Fix strange behaviours when using negative values.
(ns_set_window_size):
(ns_set_undecorated):
([EmacsView windowDidResize:]):
([EmacsView windowDidExitFullScreen]):
(ns_judge_scroll_bars): Remove references to updateFrameSize.
([EmacsView dealloc]): Unset resize notification and release buffer.
([EmacsView updateFrameSize:]): Remove function.
([EmacsView windowWillResize:toSize:]): Move some code to
viewDidResize.
([EmacsView viewDidResize]): New function.
([EmacsView initFrameFromEmacs:]): Set up resize notification and move
buffer creation until after the prerequisite objects are created.
([EmacsView toggleFullScreen:]): Set frame to the size of the
contentview, not the whole window, and remove reference to
updateFrameSize.
([EmacsView setRows:andColumns:]): Remove unused method.
([EmacsView windowDidMove:]): Tidy up.
---
Once again, I think this is right. Please test and let me know how you
get on.

src/nsmenu.m |   2 -
 src/nsterm.h |  15 ---
 src/nsterm.m | 309 +++++++++++++++++++++++----------------------------
 3 files changed, 142 insertions(+), 184 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 67f9a45a40..b7e4cbd565 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1141,8 +1141,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
     }
 #endif
 
-  if (oldh != FRAME_TOOLBAR_HEIGHT (f))
-    [view updateFrameSize:YES];
   if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
     {
       view->wait_for_tool_bar = NO;
diff --git a/src/nsterm.h b/src/nsterm.h
index 8396a542f7..e142dbd4f0 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -439,7 +439,6 @@ #define NS_DRAW_TO_BUFFER 1
 #endif
 @public
    struct frame *emacsframe;
-   int rows, cols;
    int scrollbarsNeedingUpdate;
    EmacsToolbar *toolbar;
    NSRect ns_userRect;
@@ -458,11 +457,9 @@ #define NS_DRAW_TO_BUFFER 1
 /* Emacs-side interface */
 - (instancetype) initFrameFromEmacs: (struct frame *) f;
 - (void) createToolbar: (struct frame *)f;
-- (void) setRows: (int) r andColumns: (int) c;
 - (void) setWindowClosing: (BOOL)closing;
 - (EmacsToolbar *) toolbar;
 - (void) deleteWorkingText;
-- (void) updateFrameSize: (BOOL) delay;
 - (void) handleFS;
 - (void) setFSValue: (int)value;
 - (void) toggleFullScreen: (id) sender;
@@ -1084,18 +1081,6 @@ #define NS_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f)		\
    (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)	\
     - NS_SCROLL_BAR_HEIGHT (f)) : 0)
 
-/* 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 (FRAME_PARENT_FRAME (f)) window].frame.origin.x : 0)
-#define NS_PARENT_WINDOW_TOP_POS(f)                                     \
-  (FRAME_PARENT_FRAME (f) != NULL                                       \
-   ? ([FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window].frame.origin.y    \
-      + [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window].frame.size.height \
-      - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f)))              \
-   : [[[NSScreen screens] objectAtIndex: 0] frame].size.height)
-
 #define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table)
 
 #define FRAME_FONTSET(f) ((f)->output_data.ns->fontset)
diff --git a/src/nsterm.m b/src/nsterm.m
index 04fc051223..461431622f 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -843,6 +843,32 @@ Free a pool and temporary objects it refers to (callable from C)
 }
 
 
+/* Get the frame rect, in system coordinates, of the parent window or,
+   if there is no parent window, the main screen.  */
+static inline NSRect
+ns_parent_window_rect (struct frame *f)
+{
+  NSRect parentRect;
+
+  if (FRAME_PARENT_FRAME (f) != NULL)
+    {
+      EmacsView *parentView = FRAME_NS_VIEW (FRAME_PARENT_FRAME (f));
+      parentRect = [parentView convertRect:[parentView frame]
+                                    toView:nil];
+      parentRect = [[parentView window] convertRectToScreen:parentRect];
+    }
+  else
+    parentRect = [[[NSScreen screens] objectAtIndex:0] frame];
+
+  return parentRect;
+}
+
+/* Calculate system coordinates of the left and top of the parent
+   window or, if there is no parent window, the main screen.  */
+#define NS_PARENT_WINDOW_LEFT_POS(f) NSMinX (ns_parent_window_rect (f))
+#define NS_PARENT_WINDOW_TOP_POS(f) NSMaxY (ns_parent_window_rect (f))
+
+
 static NSRect
 ns_row_rect (struct window *w, struct glyph_row *row,
                enum glyph_row_area area)
@@ -1741,61 +1767,64 @@ Hide the window (X11 semantics)
    -------------------------------------------------------------------------- */
 {
   NSView *view = FRAME_NS_VIEW (f);
-  NSScreen *screen = [[view window] screen];
+  NSRect windowFrame = [[view window] frame];
+  NSPoint topLeft;
 
   NSTRACE ("ns_set_offset");
 
   block_input ();
 
-  f->left_pos = xoff;
-  f->top_pos = yoff;
+  if (FRAME_PARENT_FRAME (f))
+    {
+      /* Convert the parent frame's view rectangle into screen
+         coords.  */
+      EmacsView *parentView = FRAME_NS_VIEW (FRAME_PARENT_FRAME (f));
+      NSRect parentRect = [parentView convertRect:[parentView frame]
+                                           toView:nil];
+      parentRect = [[parentView window] convertRectToScreen:parentRect];
+
+      if (f->size_hint_flags & XNegative)
+        topLeft.x = NSMaxX (parentRect) - NSWidth (windowFrame) + xoff;
+      else
+        topLeft.x = NSMinX (parentRect) + xoff;
 
-  if (view != nil)
+      if (f->size_hint_flags & YNegative)
+        topLeft.y = NSMinY (parentRect) + NSHeight (windowFrame) - yoff;
+      else
+        topLeft.y = NSMaxY (parentRect) - yoff;
+    }
+  else
     {
-      if (FRAME_PARENT_FRAME (f) == NULL && screen)
-        {
-          f->left_pos = f->size_hint_flags & XNegative
-            ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
-            : f->left_pos;
-          /* We use visibleFrame here to take menu bar into account.
-             Ideally we should also adjust left/top with visibleFrame.origin.  */
-
-          f->top_pos = f->size_hint_flags & YNegative
-            ? ([screen visibleFrame].size.height + f->top_pos
-               - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
-               - FRAME_TOOLBAR_HEIGHT (f))
-            : f->top_pos;
-#ifdef NS_IMPL_GNUSTEP
-	  if (f->left_pos < 100)
-	    f->left_pos = 100;  /* don't overlap menu */
-#endif
-        }
-      else if (FRAME_PARENT_FRAME (f) != NULL)
-        {
-          struct frame *parent = FRAME_PARENT_FRAME (f);
+      /* 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 screenFrame = [[[view window] screen] frame];
 
-          /* On X negative values for child frames always result in
-             positioning relative to the bottom right corner of the
-             parent frame.  */
-          if (f->left_pos < 0)
-            f->left_pos = FRAME_PIXEL_WIDTH (parent) - FRAME_PIXEL_WIDTH (f) + f->left_pos;
+      if (f->size_hint_flags & XNegative)
+        topLeft.x = NSMaxX (screenFrame) - NSWidth (windowFrame) + xoff;
+      else
+        topLeft.x = xoff;
 
-          if (f->top_pos < 0)
-            f->top_pos = FRAME_PIXEL_HEIGHT (parent) + FRAME_TOOLBAR_HEIGHT (parent)
-              - FRAME_PIXEL_HEIGHT (f) + f->top_pos;
-        }
+      if (f->size_hint_flags & YNegative)
+        topLeft.y = NSMinY (screenFrame) + NSHeight (windowFrame) - yoff;
+      else
+        topLeft.y = NSMaxY ([[[NSScreen screens] objectAtIndex:0] frame]) - yoff;
+
+#ifdef NS_IMPL_GNUSTEP
+      /* Don't overlap the menu.
 
-      /* Constrain the setFrameTopLeftPoint so we don't move behind the
-         menu bar.  */
-      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);
+         FIXME: Surely there's a better way than just hardcoding 100
+         in here?  */
+      boundsRect.origin.x = 100;
+#endif
     }
 
+  NSTRACE_POINT ("setFrameTopLeftPoint", topLeft);
+  [[view window] setFrameTopLeftPoint:topLeft];
+  f->size_hint_flags &= ~(XNegative|YNegative);
+
   unblock_input ();
 }
 
@@ -1864,7 +1893,6 @@ Hide the window (X11 semantics)
 
   [window setFrame: wr display: YES];
 
-  [view updateFrameSize: NO];
   unblock_input ();
 }
 
@@ -1913,7 +1941,6 @@ Hide the window (X11 semantics)
          so some key presses (TAB) are swallowed by the system.  */
       [window makeFirstResponder: view];
 
-      [view updateFrameSize: NO];
       unblock_input ();
     }
 }
@@ -5024,9 +5051,6 @@ in certain situations (rapid incoming events).
       if ([view judge])
         removed = YES;
     }
-
-  if (removed)
-    [eview updateFrameSize: NO];
 }
 
 /* ==========================================================================
@@ -6198,6 +6222,15 @@ - (void) setWindowClosing: (BOOL)closing
 - (void)dealloc
 {
   NSTRACE ("[EmacsView dealloc]");
+
+  /* Clear the view resize notification.  */
+  [[NSNotificationCenter defaultCenter]
+    removeObserver:self
+              name:NSViewFrameDidChangeNotification
+            object:nil];
+
+  CGContextRelease (drawingBuffer);
+
   [toolbar release];
   if (fs_state == FULLSCREEN_BOTH)
     [nonfs_window release];
@@ -7039,108 +7072,12 @@ - (BOOL)windowShouldClose: (id)sender
   return NO;
 }
 
-- (void) updateFrameSize: (BOOL) delay
-{
-  NSWindow *window = [self window];
-  NSRect wr = [window frame];
-  int extra = 0;
-  int oldc = cols, oldr = rows;
-  int oldw = FRAME_PIXEL_WIDTH (emacsframe);
-  int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
-  int neww, newh;
-
-  NSTRACE ("[EmacsView updateFrameSize:]");
-  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
-  NSTRACE_RECT ("Original frame", wr);
-  NSTRACE_MSG  ("Original columns: %d", cols);
-  NSTRACE_MSG  ("Original rows: %d", rows);
-
-  if (! [self isFullscreen])
-    {
-      int toolbar_height;
-#ifdef NS_IMPL_GNUSTEP
-      // GNUstep does not always update the tool bar height.  Force it.
-      if (toolbar && [toolbar isVisible])
-          update_frame_tool_bar (emacsframe);
-#endif
-
-      toolbar_height = FRAME_TOOLBAR_HEIGHT (emacsframe);
-      if (toolbar_height < 0)
-        toolbar_height = 35;
-
-      extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
-        + toolbar_height;
-    }
-
-  if (wait_for_tool_bar)
-    {
-      /* The toolbar height is always 0 in fullscreen and undecorated
-         frames, so don't wait for it to become available.  */
-      if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0
-          && FRAME_UNDECORATED (emacsframe) == false
-          && ! [self isFullscreen])
-        {
-          NSTRACE_MSG ("Waiting for toolbar");
-          return;
-        }
-      wait_for_tool_bar = NO;
-    }
-
-  neww = (int)wr.size.width - emacsframe->border_width;
-  newh = (int)wr.size.height - extra;
-
-  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
-  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);
-
-  if (cols < MINWIDTH)
-    cols = MINWIDTH;
-
-  if (rows < MINHEIGHT)
-    rows = MINHEIGHT;
-
-  NSTRACE_MSG ("New columns: %d", cols);
-  NSTRACE_MSG ("New rows: %d", rows);
-
-  if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
-    {
-      NSView *view = FRAME_NS_VIEW (emacsframe);
-
-      change_frame_size (emacsframe,
-                         FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
-                         FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
-                         0, delay, 0, 1);
-      SET_FRAME_GARBAGED (emacsframe);
-      cancel_mouse_face (emacsframe);
-
-      /* The next two lines set the frame to the same size as we've
-         already set above.  We need to do this when we switch back
-         from non-native fullscreen, in other circumstances it appears
-         to be a noop.  (bug#28872) */
-      wr = NSMakeRect (0, 0, neww, newh);
-      [view setFrame: wr];
-#ifdef NS_DRAW_TO_BUFFER
-      [self createDrawingBuffer];
-#endif
-
-      // To do: consider using [NSNotificationCenter postNotificationName:].
-      [self windowDidMove: // Update top/left.
-	      [NSNotification notificationWithName:NSWindowDidMoveNotification
-					    object:[view window]]];
-    }
-  else
-    {
-      NSTRACE_MSG ("No change");
-    }
-}
 
 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
 /* Normalize frame to gridded text size.  */
 {
   int extra = 0;
+  int cols, rows;
 
   NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
            NSTRACE_ARG_SIZE (frameSize));
@@ -7277,11 +7214,6 @@ - (void)windowDidResize: (NSNotification *)notification
   sz = [self windowWillResize: theWindow toSize: sz];
 #endif /* NS_IMPL_GNUSTEP */
 
-  if (cols > 0 && rows > 0)
-    {
-      [self updateFrameSize: YES];
-    }
-
   ns_send_appdefined (-1);
 }
 
@@ -7302,6 +7234,51 @@ - (void)viewDidEndLiveResize
 #endif /* NS_IMPL_COCOA */
 
 
+- (void)viewDidResize:(NSNotification *)notification
+{
+  NSRect frame = [self frame];
+  int oldw, oldh, neww, newh;
+
+  if (! FRAME_LIVE_P (emacsframe))
+    return;
+
+#ifdef NS_DRAW_TO_BUFFER
+  CGFloat scale = [[self window] backingScaleFactor];
+  oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
+  oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
+#else
+  oldw = FRAME_PIXEL_WIDTH (emacsframe);
+  oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+#endif
+  neww = (int)NSWidth (frame);
+  newh = (int)NSHeight (frame);
+
+  NSTRACE ("[EmacsView viewDidResize]");
+
+  /* Don't want to do anything when the view size hasn't changed. */
+  if ((oldh == newh && oldw == neww))
+    {
+      NSTRACE_MSG ("No change");
+      return;
+    }
+
+  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+
+  change_frame_size (emacsframe,
+                     FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
+                     FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
+                     0, YES, 0, 1);
+
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+  ns_clear_frame (emacsframe);
+  SET_FRAME_GARBAGED (emacsframe);
+  cancel_mouse_face (emacsframe);
+}
+
+
 - (void)windowDidBecomeKey: (NSNotification *)notification
 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
 {
@@ -7463,10 +7440,6 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   maximizing_resize = NO;
 #endif
 
-#ifdef NS_DRAW_TO_BUFFER
-  [self createDrawingBuffer];
-#endif
-
   win = [[EmacsWindow alloc]
             initWithContentRect: r
                       styleMask: (FRAME_UNDECORATED (f)
@@ -7572,6 +7545,17 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   [NSApp registerServicesMenuSendTypes: ns_send_types
                            returnTypes: [NSArray array]];
 
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+
+  /* Set up view resize notifications.  */
+  [self setPostsFrameChangedNotifications:YES];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector (viewDidResize:)
+             name:NSViewFrameDidChangeNotification object:nil];
+
   /* macOS Sierra automatically enables tabbed windows.  We can't
      allow this to be enabled until it's available on a Free system.
      Currently it only happens by accident and is buggy anyway.  */
@@ -7601,9 +7585,8 @@ - (void)windowDidMove: sender
     return;
   if (screen != nil)
     {
-      emacsframe->left_pos = r.origin.x - NS_PARENT_WINDOW_LEFT_POS (emacsframe);
-      emacsframe->top_pos =
-        NS_PARENT_WINDOW_TOP_POS (emacsframe) - (r.origin.y + r.size.height);
+      emacsframe->left_pos = NSMinX (r) - NS_PARENT_WINDOW_LEFT_POS (emacsframe);
+      emacsframe->top_pos = NS_PARENT_WINDOW_TOP_POS (emacsframe) - NSMaxY (r);
 
       // FIXME: after event part below didExitFullScreen is not received
       // if (emacs_event)
@@ -7902,7 +7885,6 @@ - (void)windowDidExitFullScreen /* provided for direct calls */
     {
       [toolbar setVisible:YES];
       update_frame_tool_bar (emacsframe);
-      [self updateFrameSize:YES];
       [[self window] display];
     }
   else
@@ -8115,11 +8097,11 @@ - (void)toggleFullScreen: (id)sender
       // send notifications.
 
       [self windowWillExitFullScreen];
-      [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
+      [fw setFrame:[[w contentView] frame]
+                    display:YES animate:ns_use_fullscreen_animation];
       [fw close];
       [w makeKeyAndOrderFront:NSApp];
       [self windowDidExitFullScreen];
-      [self updateFrameSize:YES];
     }
 }
 
@@ -8628,13 +8610,6 @@ - (instancetype)setMiniwindowImage: (BOOL) setMini
 }
 
 
-- (void) setRows: (int) r andColumns: (int) c
-{
-  NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
-  rows = r;
-  cols = c;
-}
-
 - (int) fullscreenState
 {
   return fs_state;
-- 
2.24.0


-- 
Alan Third





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* bug#40200: [PATCH v3] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-04 14:17             ` bug#40200: [PATCH v3] " Alan Third
@ 2020-04-06  6:57               ` Andrii Kolomoiets
  2020-04-06 18:44                 ` bug#28872: [PATCH v4] " Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-04-06  6:57 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, 28872, aaronjensen

Alan Third <alan@idiocy.org> writes:

> Once again, I think this is right. Please test and let me know how you
> get on.

This code works differently in the patched version:

(progn
  (tool-bar-mode -1)
  (let ((child-frame (make-frame `((parent-frame . ,(selected-frame))
                                   (top . 0)
                                   (left . 0)
                                   (width . 1.0)
                                   (height . 1))))
        (new-frame (make-frame)))
    (set-frame-width new-frame (+ 20 (frame-parameter new-frame 'width)))
    (modify-frame-parameters child-frame `((parent-frame . ,new-frame)))
    (modify-frame-parameters child-frame '((top . 0)
                                           (left . 0)
                                           (width . 1.0)
                                           (height . 1)))))

Child frame doesn't occupy full width of the parent frame.

> +  ns_clear_frame (emacsframe);

Can this line be removed from the patch? I've described reasons to
remove it in another letter:
https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg01060.html

Thanks!





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-06  6:57               ` Andrii Kolomoiets
@ 2020-04-06 18:44                 ` Alan Third
  2020-04-07  8:14                   ` bug#40200: " Andrii Kolomoiets
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-04-06 18:44 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200, 28872, aaronjensen

* src/nsmenu.m (update_frame_tool_bar): Remove reference to
updateFrameSize.
* src/nsterm.h: ([EmacsView updateFrameSize]):
([EmacsView setRows:andColumns:]): Remove unused
method definitions.
(NS_PARENT_WINDOW_LEFT_POS):
(NS_PARENT_WINDOW_TOP_POS): Move to nsterm.m.
* src/nsterm.m (ns_parent_window_rect): New function.
(NS_PARENT_WINDOW_LEFT_POS):
(NS_PARENT_WINDOW_TOP_POS): Move to nsterm.m and simplify.
(ns_set_offset): Fix strange behaviours when using negative values.
(ns_set_window_size):
(ns_set_undecorated):
([EmacsView windowDidResize:]):
([EmacsView windowDidExitFullScreen]):
(ns_judge_scroll_bars): Remove references to updateFrameSize.
([EmacsView dealloc]): Unset resize notification and release buffer.
([EmacsView updateFrameSize:]): Remove function.
([EmacsView windowWillResize:toSize:]): Move some code to
viewDidResize.
([EmacsView viewDidResize]): New function.
([EmacsView initFrameFromEmacs:]): Set up resize notification and move
buffer creation until after the prerequisite objects are created.
([EmacsView toggleFullScreen:]): Set frame to the size of the
contentview, not the whole window, and remove reference to
updateFrameSize.
([EmacsView setRows:andColumns:]): Remove unused method.
([EmacsView windowDidMove:]): Tidy up.
---
Out of interest, do you have a test suite, or are you just coming up
with these tests on the fly?

 src/nsmenu.m |   2 -
 src/nsterm.h |  15 ---
 src/nsterm.m | 318 ++++++++++++++++++++++++---------------------------
 3 files changed, 150 insertions(+), 185 deletions(-)

diff --git a/src/nsmenu.m b/src/nsmenu.m
index 67f9a45a40..b7e4cbd565 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -1141,8 +1141,6 @@ - (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
     }
 #endif
 
-  if (oldh != FRAME_TOOLBAR_HEIGHT (f))
-    [view updateFrameSize:YES];
   if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
     {
       view->wait_for_tool_bar = NO;
diff --git a/src/nsterm.h b/src/nsterm.h
index 8396a542f7..e142dbd4f0 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -439,7 +439,6 @@ #define NS_DRAW_TO_BUFFER 1
 #endif
 @public
    struct frame *emacsframe;
-   int rows, cols;
    int scrollbarsNeedingUpdate;
    EmacsToolbar *toolbar;
    NSRect ns_userRect;
@@ -458,11 +457,9 @@ #define NS_DRAW_TO_BUFFER 1
 /* Emacs-side interface */
 - (instancetype) initFrameFromEmacs: (struct frame *) f;
 - (void) createToolbar: (struct frame *)f;
-- (void) setRows: (int) r andColumns: (int) c;
 - (void) setWindowClosing: (BOOL)closing;
 - (EmacsToolbar *) toolbar;
 - (void) deleteWorkingText;
-- (void) updateFrameSize: (BOOL) delay;
 - (void) handleFS;
 - (void) setFSValue: (int)value;
 - (void) toggleFullScreen: (id) sender;
@@ -1084,18 +1081,6 @@ #define NS_SCROLL_BAR_ADJUST_HORIZONTALLY(w, f)		\
    (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)	\
     - NS_SCROLL_BAR_HEIGHT (f)) : 0)
 
-/* 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 (FRAME_PARENT_FRAME (f)) window].frame.origin.x : 0)
-#define NS_PARENT_WINDOW_TOP_POS(f)                                     \
-  (FRAME_PARENT_FRAME (f) != NULL                                       \
-   ? ([FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window].frame.origin.y    \
-      + [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window].frame.size.height \
-      - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f)))              \
-   : [[[NSScreen screens] objectAtIndex: 0] frame].size.height)
-
 #define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table)
 
 #define FRAME_FONTSET(f) ((f)->output_data.ns->fontset)
diff --git a/src/nsterm.m b/src/nsterm.m
index 04fc051223..4318622377 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -843,6 +843,32 @@ Free a pool and temporary objects it refers to (callable from C)
 }
 
 
+/* Get the frame rect, in system coordinates, of the parent window or,
+   if there is no parent window, the main screen.  */
+static inline NSRect
+ns_parent_window_rect (struct frame *f)
+{
+  NSRect parentRect;
+
+  if (FRAME_PARENT_FRAME (f) != NULL)
+    {
+      EmacsView *parentView = FRAME_NS_VIEW (FRAME_PARENT_FRAME (f));
+      parentRect = [parentView convertRect:[parentView frame]
+                                    toView:nil];
+      parentRect = [[parentView window] convertRectToScreen:parentRect];
+    }
+  else
+    parentRect = [[[NSScreen screens] objectAtIndex:0] frame];
+
+  return parentRect;
+}
+
+/* Calculate system coordinates of the left and top of the parent
+   window or, if there is no parent window, the main screen.  */
+#define NS_PARENT_WINDOW_LEFT_POS(f) NSMinX (ns_parent_window_rect (f))
+#define NS_PARENT_WINDOW_TOP_POS(f) NSMaxY (ns_parent_window_rect (f))
+
+
 static NSRect
 ns_row_rect (struct window *w, struct glyph_row *row,
                enum glyph_row_area area)
@@ -1741,61 +1767,64 @@ Hide the window (X11 semantics)
    -------------------------------------------------------------------------- */
 {
   NSView *view = FRAME_NS_VIEW (f);
-  NSScreen *screen = [[view window] screen];
+  NSRect windowFrame = [[view window] frame];
+  NSPoint topLeft;
 
   NSTRACE ("ns_set_offset");
 
   block_input ();
 
-  f->left_pos = xoff;
-  f->top_pos = yoff;
+  if (FRAME_PARENT_FRAME (f))
+    {
+      /* Convert the parent frame's view rectangle into screen
+         coords.  */
+      EmacsView *parentView = FRAME_NS_VIEW (FRAME_PARENT_FRAME (f));
+      NSRect parentRect = [parentView convertRect:[parentView frame]
+                                           toView:nil];
+      parentRect = [[parentView window] convertRectToScreen:parentRect];
+
+      if (f->size_hint_flags & XNegative)
+        topLeft.x = NSMaxX (parentRect) - NSWidth (windowFrame) + xoff;
+      else
+        topLeft.x = NSMinX (parentRect) + xoff;
 
-  if (view != nil)
+      if (f->size_hint_flags & YNegative)
+        topLeft.y = NSMinY (parentRect) + NSHeight (windowFrame) - yoff;
+      else
+        topLeft.y = NSMaxY (parentRect) - yoff;
+    }
+  else
     {
-      if (FRAME_PARENT_FRAME (f) == NULL && screen)
-        {
-          f->left_pos = f->size_hint_flags & XNegative
-            ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
-            : f->left_pos;
-          /* We use visibleFrame here to take menu bar into account.
-             Ideally we should also adjust left/top with visibleFrame.origin.  */
-
-          f->top_pos = f->size_hint_flags & YNegative
-            ? ([screen visibleFrame].size.height + f->top_pos
-               - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
-               - FRAME_TOOLBAR_HEIGHT (f))
-            : f->top_pos;
-#ifdef NS_IMPL_GNUSTEP
-	  if (f->left_pos < 100)
-	    f->left_pos = 100;  /* don't overlap menu */
-#endif
-        }
-      else if (FRAME_PARENT_FRAME (f) != NULL)
-        {
-          struct frame *parent = FRAME_PARENT_FRAME (f);
+      /* 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 screenFrame = [[[view window] screen] frame];
 
-          /* On X negative values for child frames always result in
-             positioning relative to the bottom right corner of the
-             parent frame.  */
-          if (f->left_pos < 0)
-            f->left_pos = FRAME_PIXEL_WIDTH (parent) - FRAME_PIXEL_WIDTH (f) + f->left_pos;
+      if (f->size_hint_flags & XNegative)
+        topLeft.x = NSMaxX (screenFrame) - NSWidth (windowFrame) + xoff;
+      else
+        topLeft.x = xoff;
 
-          if (f->top_pos < 0)
-            f->top_pos = FRAME_PIXEL_HEIGHT (parent) + FRAME_TOOLBAR_HEIGHT (parent)
-              - FRAME_PIXEL_HEIGHT (f) + f->top_pos;
-        }
+      if (f->size_hint_flags & YNegative)
+        topLeft.y = NSMinY (screenFrame) + NSHeight (windowFrame) - yoff;
+      else
+        topLeft.y = NSMaxY ([[[NSScreen screens] objectAtIndex:0] frame]) - yoff;
+
+#ifdef NS_IMPL_GNUSTEP
+      /* Don't overlap the menu.
 
-      /* Constrain the setFrameTopLeftPoint so we don't move behind the
-         menu bar.  */
-      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);
+         FIXME: Surely there's a better way than just hardcoding 100
+         in here?  */
+      boundsRect.origin.x = 100;
+#endif
     }
 
+  NSTRACE_POINT ("setFrameTopLeftPoint", topLeft);
+  [[view window] setFrameTopLeftPoint:topLeft];
+  f->size_hint_flags &= ~(XNegative|YNegative);
+
   unblock_input ();
 }
 
@@ -1862,9 +1891,16 @@ Hide the window (X11 semantics)
 	   make_fixnum (FRAME_NS_TITLEBAR_HEIGHT (f)),
 	   make_fixnum (FRAME_TOOLBAR_HEIGHT (f))));
 
-  [window setFrame: wr display: YES];
+ /* 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,
+                    FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth),
+                    FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight),
+                    0, NO, 0, 1);
+
+  [window setFrame:wr display:NO];
 
-  [view updateFrameSize: NO];
   unblock_input ();
 }
 
@@ -1913,7 +1949,6 @@ Hide the window (X11 semantics)
          so some key presses (TAB) are swallowed by the system.  */
       [window makeFirstResponder: view];
 
-      [view updateFrameSize: NO];
       unblock_input ();
     }
 }
@@ -5024,9 +5059,6 @@ in certain situations (rapid incoming events).
       if ([view judge])
         removed = YES;
     }
-
-  if (removed)
-    [eview updateFrameSize: NO];
 }
 
 /* ==========================================================================
@@ -6198,6 +6230,15 @@ - (void) setWindowClosing: (BOOL)closing
 - (void)dealloc
 {
   NSTRACE ("[EmacsView dealloc]");
+
+  /* Clear the view resize notification.  */
+  [[NSNotificationCenter defaultCenter]
+    removeObserver:self
+              name:NSViewFrameDidChangeNotification
+            object:nil];
+
+  CGContextRelease (drawingBuffer);
+
   [toolbar release];
   if (fs_state == FULLSCREEN_BOTH)
     [nonfs_window release];
@@ -7039,108 +7080,12 @@ - (BOOL)windowShouldClose: (id)sender
   return NO;
 }
 
-- (void) updateFrameSize: (BOOL) delay
-{
-  NSWindow *window = [self window];
-  NSRect wr = [window frame];
-  int extra = 0;
-  int oldc = cols, oldr = rows;
-  int oldw = FRAME_PIXEL_WIDTH (emacsframe);
-  int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
-  int neww, newh;
-
-  NSTRACE ("[EmacsView updateFrameSize:]");
-  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
-  NSTRACE_RECT ("Original frame", wr);
-  NSTRACE_MSG  ("Original columns: %d", cols);
-  NSTRACE_MSG  ("Original rows: %d", rows);
-
-  if (! [self isFullscreen])
-    {
-      int toolbar_height;
-#ifdef NS_IMPL_GNUSTEP
-      // GNUstep does not always update the tool bar height.  Force it.
-      if (toolbar && [toolbar isVisible])
-          update_frame_tool_bar (emacsframe);
-#endif
-
-      toolbar_height = FRAME_TOOLBAR_HEIGHT (emacsframe);
-      if (toolbar_height < 0)
-        toolbar_height = 35;
-
-      extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
-        + toolbar_height;
-    }
-
-  if (wait_for_tool_bar)
-    {
-      /* The toolbar height is always 0 in fullscreen and undecorated
-         frames, so don't wait for it to become available.  */
-      if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0
-          && FRAME_UNDECORATED (emacsframe) == false
-          && ! [self isFullscreen])
-        {
-          NSTRACE_MSG ("Waiting for toolbar");
-          return;
-        }
-      wait_for_tool_bar = NO;
-    }
-
-  neww = (int)wr.size.width - emacsframe->border_width;
-  newh = (int)wr.size.height - extra;
-
-  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
-  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);
-
-  if (cols < MINWIDTH)
-    cols = MINWIDTH;
-
-  if (rows < MINHEIGHT)
-    rows = MINHEIGHT;
-
-  NSTRACE_MSG ("New columns: %d", cols);
-  NSTRACE_MSG ("New rows: %d", rows);
-
-  if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
-    {
-      NSView *view = FRAME_NS_VIEW (emacsframe);
-
-      change_frame_size (emacsframe,
-                         FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
-                         FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
-                         0, delay, 0, 1);
-      SET_FRAME_GARBAGED (emacsframe);
-      cancel_mouse_face (emacsframe);
-
-      /* The next two lines set the frame to the same size as we've
-         already set above.  We need to do this when we switch back
-         from non-native fullscreen, in other circumstances it appears
-         to be a noop.  (bug#28872) */
-      wr = NSMakeRect (0, 0, neww, newh);
-      [view setFrame: wr];
-#ifdef NS_DRAW_TO_BUFFER
-      [self createDrawingBuffer];
-#endif
-
-      // To do: consider using [NSNotificationCenter postNotificationName:].
-      [self windowDidMove: // Update top/left.
-	      [NSNotification notificationWithName:NSWindowDidMoveNotification
-					    object:[view window]]];
-    }
-  else
-    {
-      NSTRACE_MSG ("No change");
-    }
-}
 
 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
 /* Normalize frame to gridded text size.  */
 {
   int extra = 0;
+  int cols, rows;
 
   NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
            NSTRACE_ARG_SIZE (frameSize));
@@ -7277,11 +7222,6 @@ - (void)windowDidResize: (NSNotification *)notification
   sz = [self windowWillResize: theWindow toSize: sz];
 #endif /* NS_IMPL_GNUSTEP */
 
-  if (cols > 0 && rows > 0)
-    {
-      [self updateFrameSize: YES];
-    }
-
   ns_send_appdefined (-1);
 }
 
@@ -7302,6 +7242,50 @@ - (void)viewDidEndLiveResize
 #endif /* NS_IMPL_COCOA */
 
 
+- (void)viewDidResize:(NSNotification *)notification
+{
+  NSRect frame = [self frame];
+  int oldw, oldh, neww, newh;
+
+  if (! FRAME_LIVE_P (emacsframe))
+    return;
+
+#ifdef NS_DRAW_TO_BUFFER
+  CGFloat scale = [[self window] backingScaleFactor];
+  oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
+  oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
+#else
+  oldw = FRAME_PIXEL_WIDTH (emacsframe);
+  oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+#endif
+  neww = (int)NSWidth (frame);
+  newh = (int)NSHeight (frame);
+
+  NSTRACE ("[EmacsView viewDidResize]");
+
+  /* Don't want to do anything when the view size hasn't changed. */
+  if ((oldh == newh && oldw == neww))
+    {
+      NSTRACE_MSG ("No change");
+      return;
+    }
+
+  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+
+  change_frame_size (emacsframe,
+                     FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
+                     FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
+                     0, YES, 0, 1);
+
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+  SET_FRAME_GARBAGED (emacsframe);
+  cancel_mouse_face (emacsframe);
+}
+
+
 - (void)windowDidBecomeKey: (NSNotification *)notification
 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
 {
@@ -7463,10 +7447,6 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   maximizing_resize = NO;
 #endif
 
-#ifdef NS_DRAW_TO_BUFFER
-  [self createDrawingBuffer];
-#endif
-
   win = [[EmacsWindow alloc]
             initWithContentRect: r
                       styleMask: (FRAME_UNDECORATED (f)
@@ -7572,6 +7552,17 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   [NSApp registerServicesMenuSendTypes: ns_send_types
                            returnTypes: [NSArray array]];
 
+#ifdef NS_DRAW_TO_BUFFER
+  [self createDrawingBuffer];
+#endif
+
+  /* Set up view resize notifications.  */
+  [self setPostsFrameChangedNotifications:YES];
+  [[NSNotificationCenter defaultCenter]
+      addObserver:self
+         selector:@selector (viewDidResize:)
+             name:NSViewFrameDidChangeNotification object:nil];
+
   /* macOS Sierra automatically enables tabbed windows.  We can't
      allow this to be enabled until it's available on a Free system.
      Currently it only happens by accident and is buggy anyway.  */
@@ -7601,9 +7592,8 @@ - (void)windowDidMove: sender
     return;
   if (screen != nil)
     {
-      emacsframe->left_pos = r.origin.x - NS_PARENT_WINDOW_LEFT_POS (emacsframe);
-      emacsframe->top_pos =
-        NS_PARENT_WINDOW_TOP_POS (emacsframe) - (r.origin.y + r.size.height);
+      emacsframe->left_pos = NSMinX (r) - NS_PARENT_WINDOW_LEFT_POS (emacsframe);
+      emacsframe->top_pos = NS_PARENT_WINDOW_TOP_POS (emacsframe) - NSMaxY (r);
 
       // FIXME: after event part below didExitFullScreen is not received
       // if (emacs_event)
@@ -7902,7 +7892,6 @@ - (void)windowDidExitFullScreen /* provided for direct calls */
     {
       [toolbar setVisible:YES];
       update_frame_tool_bar (emacsframe);
-      [self updateFrameSize:YES];
       [[self window] display];
     }
   else
@@ -8115,11 +8104,11 @@ - (void)toggleFullScreen: (id)sender
       // send notifications.
 
       [self windowWillExitFullScreen];
-      [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
+      [fw setFrame:[[w contentView] frame]
+                    display:YES animate:ns_use_fullscreen_animation];
       [fw close];
       [w makeKeyAndOrderFront:NSApp];
       [self windowDidExitFullScreen];
-      [self updateFrameSize:YES];
     }
 }
 
@@ -8628,13 +8617,6 @@ - (instancetype)setMiniwindowImage: (BOOL) setMini
 }
 
 
-- (void) setRows: (int) r andColumns: (int) c
-{
-  NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
-  rows = r;
-  cols = c;
-}
-
 - (int) fullscreenState
 {
   return fs_state;
-- 
2.26.0


-- 
Alan Third





^ permalink raw reply related	[flat|nested] 24+ messages in thread

* bug#40200: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-06 18:44                 ` bug#28872: [PATCH v4] " Alan Third
@ 2020-04-07  8:14                   ` Andrii Kolomoiets
  2020-04-16 18:24                     ` bug#28872: " Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: Andrii Kolomoiets @ 2020-04-07  8:14 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, 28872, aaronjensen

Alan Third <alan@idiocy.org> writes:

> Out of interest, do you have a test suite, or are you just coming up
> with these tests on the fly?

I'm using these minor modes which utilize child frame to display
minibuffer and completions buffer:
https://github.com/muffinmad/emacs-mini-frame
https://github.com/muffinmad/emacs-completions-frame

Single child frame moves across all frames so child frame positioning
issues are quickly comes in sight for me.  And then the fun part: narrow
down the code so the issue can be reproduced in `emacs -Q`.

The patch v4 works good so far, thank you!





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-07  8:14                   ` bug#40200: " Andrii Kolomoiets
@ 2020-04-16 18:24                     ` Alan Third
  2020-04-18  1:52                       ` bug#40200: " HaiJun Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-04-16 18:24 UTC (permalink / raw)
  To: Andrii Kolomoiets; +Cc: 40200-done, 28872-done, aaronjensen

On Tue, Apr 07, 2020 at 11:14:00AM +0300, Andrii Kolomoiets wrote:
> The patch v4 works good so far, thank you!

Since I’ve not heard anything bad for over a week now I’ve pushed the
change to the master branch.

Thanks for your help.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-16 18:24                     ` bug#28872: " Alan Third
@ 2020-04-18  1:52                       ` HaiJun Zhang
  2020-04-18 12:07                         ` Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: HaiJun Zhang @ 2020-04-18  1:52 UTC (permalink / raw)
  To: Andrii Kolomoiets, Alan Third; +Cc: 40200-done, 28872-done, aaronjensen


[-- Attachment #1.1: Type: text/plain, Size: 609 bytes --]

There is problem here. After emacs startups, there is no mini buffer window and there is a blank rectangle at the right edge of the frame.

It is with my profile and it can’t be reproduced with emacs -Q.

No problem before the commit.

在 2020年4月17日 +0800 AM2:25,Alan Third <alan@idiocy.org>,写道:
> On Tue, Apr 07, 2020 at 11:14:00AM +0300, Andrii Kolomoiets wrote:
> > The patch v4 works good so far, thank you!
>
> Since I’ve not heard anything bad for over a week now I’ve pushed the
> change to the master branch.
>
> Thanks for your help.
> --
> Alan Third
>
>
>

[-- Attachment #1.2: Type: text/html, Size: 1321 bytes --]

[-- Attachment #2: WX20200417-153341@2x.png --]
[-- Type: image/png, Size: 177034 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-18  1:52                       ` bug#40200: " HaiJun Zhang
@ 2020-04-18 12:07                         ` Alan Third
  2020-04-18 14:12                           ` HaiJun Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-04-18 12:07 UTC (permalink / raw)
  To: HaiJun Zhang; +Cc: 40200, Andrii Kolomoiets

On Sat, Apr 18, 2020 at 09:52:47AM +0800, HaiJun Zhang wrote:
> There is problem here. After emacs startups, there is no mini buffer
> window and there is a blank rectangle at the right edge of the
> frame.
> 
> It is with my profile and it can’t be reproduced with emacs -Q.
> 
> No problem before the commit.

Can you try working out what part of your configuration is causing
this?

Probably there’s a place in the code where I need to either force
Emacs to update the frame size, which is unlikely, or Emacs updates
the frame size and I need to force macOS to do the actual resize.

-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-18 12:07                         ` Alan Third
@ 2020-04-18 14:12                           ` HaiJun Zhang
  2020-04-18 15:26                             ` Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: HaiJun Zhang @ 2020-04-18 14:12 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, Andrii Kolomoiets

[-- Attachment #1: Type: text/plain, Size: 1089 bytes --]

I can reproduce it with the following lines in ~/.emacs:

(setq inhibit-startup-message t
   inhibit-startup-buffer-menu t)

(setq default-frame-alist ‘(
       (width . 85)
       (height . 35)
       (vertical-scroll-bars . nil)
       (horizontal-scroll-bars . nil)
       ))

(set-frame-font “Monospace 16”)


在 2020年4月18日 +0800 PM8:07,Alan Third <alan@idiocy.org>,写道:
> On Sat, Apr 18, 2020 at 09:52:47AM +0800, HaiJun Zhang wrote:
> > There is problem here. After emacs startups, there is no mini buffer
> > window and there is a blank rectangle at the right edge of the
> > frame.
> >
> > It is with my profile and it can’t be reproduced with emacs -Q.
> >
> > No problem before the commit.
>
> Can you try working out what part of your configuration is causing
> this?
>
> Probably there’s a place in the code where I need to either force
> Emacs to update the frame size, which is unlikely, or Emacs updates
> the frame size and I need to force macOS to do the actual resize.
>
> --
> Alan Third

[-- Attachment #2: Type: text/html, Size: 2095 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-18 14:12                           ` HaiJun Zhang
@ 2020-04-18 15:26                             ` Alan Third
  2020-04-19  1:49                               ` HaiJun Zhang
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-04-18 15:26 UTC (permalink / raw)
  To: HaiJun Zhang; +Cc: 40200, Andrii Kolomoiets

[-- Attachment #1: Type: text/plain, Size: 483 bytes --]

On Sat, Apr 18, 2020 at 10:12:27PM +0800, HaiJun Zhang wrote:
> I can reproduce it with the following lines in ~/.emacs:
> 
> (setq inhibit-startup-message t
>    inhibit-startup-buffer-menu t)
> 
> (setq default-frame-alist ‘(
>        (width . 85)
>        (height . 35)
>        (vertical-scroll-bars . nil)
>        (horizontal-scroll-bars . nil)
>        ))
> 
> (set-frame-font “Monospace 16”)

Can you please try the attached patch.
-- 
Alan Third

[-- Attachment #2: 0001-Fix-initial-frame-resizing-issue-on-NS-bug-40200.patch --]
[-- Type: text/plain, Size: 2937 bytes --]

From 836c19eae4802a3aedee887669425f949971eb4a Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Sat, 18 Apr 2020 16:22:06 +0100
Subject: [PATCH] Fix initial frame resizing issue on NS (bug#40200)

* src/nsterm.m ([EmacsView viewDidResize:]): Don't try to determine
the old size when not drawing to the buffer.
---
 src/nsterm.m | 51 +++++++++++++++++++++------------------------------
 1 file changed, 21 insertions(+), 30 deletions(-)

diff --git a/src/nsterm.m b/src/nsterm.m
index 9cd1c9d860..d85a579e38 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7322,48 +7322,39 @@ - (void)viewDidEndLiveResize
 - (void)viewDidResize:(NSNotification *)notification
 {
   NSRect frame = [self frame];
-  int oldw, oldh, neww, newh;
+  int neww, newh;
 
   if (! FRAME_LIVE_P (emacsframe))
     return;
 
+  NSTRACE ("[EmacsView viewDidResize]");
+
+  neww = (int)NSWidth (frame);
+  newh = (int)NSHeight (frame);
+  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+
 #ifdef NS_DRAW_TO_BUFFER
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
   if ([self wantsUpdateLayer])
     {
-#endif
       CGFloat scale = [[self window] backingScaleFactor];
-      oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
-      oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 101400
-    }
-  else
-    {
-#endif
-#endif /* NS_DRAW_TO_BUFFER */
-#if !defined (NS_DRAW_TO_BUFFER) || MAC_OS_X_VERSION_MIN_REQUIRED < 101400
-      oldw = FRAME_PIXEL_WIDTH (emacsframe);
-      oldh = FRAME_PIXEL_HEIGHT (emacsframe);
-#endif
-#if defined (NS_DRAW_TO_BUFFER) && MAC_OS_X_VERSION_MIN_REQUIRED < 101400
-    }
-#endif
-
-  neww = (int)NSWidth (frame);
-  newh = (int)NSHeight (frame);
+      int oldw = (CGFloat)CGBitmapContextGetWidth (drawingBuffer) / scale;
+      int oldh = (CGFloat)CGBitmapContextGetHeight (drawingBuffer) / scale;
 
-  NSTRACE ("[EmacsView viewDidResize]");
+      NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
 
-  /* Don't want to do anything when the view size hasn't changed. */
-  if ((oldh == newh && oldw == neww))
-    {
-      NSTRACE_MSG ("No change");
-      return;
+      /* Don't want to do anything when the view size hasn't changed. */
+      if ((oldh == newh && oldw == neww))
+        {
+          NSTRACE_MSG ("No change");
+          return;
+        }
     }
+#endif
 
-  NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
-  NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
-
+  /* I'm not sure if it's safe to call this every time the view
+     changes size, as Emacs may already know about the change.
+     Unfortunately there doesn't seem to be a bullet-proof method of
+     determining whether we need to call it or not.  */
   change_frame_size (emacsframe,
                      FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
                      FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
-- 
2.26.1


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-18 15:26                             ` Alan Third
@ 2020-04-19  1:49                               ` HaiJun Zhang
  2020-05-03 16:26                                 ` Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: HaiJun Zhang @ 2020-04-19  1:49 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, Andrii Kolomoiets

[-- Attachment #1: Type: text/plain, Size: 697 bytes --]

The patch fixes the bug. Thanks.

Can you please look at another bug? bug#40541

在 2020年4月18日 +0800 PM11:26,Alan Third <alan@idiocy.org>,写道:
> On Sat, Apr 18, 2020 at 10:12:27PM +0800, HaiJun Zhang wrote:
> > I can reproduce it with the following lines in ~/.emacs:
> >
> > (setq inhibit-startup-message t
> >    inhibit-startup-buffer-menu t)
> >
> > (setq default-frame-alist ‘(
> >        (width . 85)
> >        (height . 35)
> >        (vertical-scroll-bars . nil)
> >        (horizontal-scroll-bars . nil)
> >        ))
> >
> > (set-frame-font “Monospace 16”)
>
> Can you please try the attached patch.
> --
> Alan Third

[-- Attachment #2: Type: text/html, Size: 1730 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-04-19  1:49                               ` HaiJun Zhang
@ 2020-05-03 16:26                                 ` Alan Third
  2020-05-03 17:13                                   ` Filipp Gunbin
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-05-03 16:26 UTC (permalink / raw)
  To: HaiJun Zhang; +Cc: 40200-done, Andrii Kolomoiets

On Sun, Apr 19, 2020 at 09:49:58AM +0800, HaiJun Zhang wrote:
> The patch fixes the bug. Thanks.

I’ve pushed it to master. Thanks!

-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-05-03 16:26                                 ` Alan Third
@ 2020-05-03 17:13                                   ` Filipp Gunbin
  2020-05-03 18:41                                     ` Alan Third
  0 siblings, 1 reply; 24+ messages in thread
From: Filipp Gunbin @ 2020-05-03 17:13 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, HaiJun Zhang, Andrii Kolomoiets

Hi, I've just filed bug#41055 which is also about NS frame resizing, it
may have something to do with this...

Filipp





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-05-03 17:13                                   ` Filipp Gunbin
@ 2020-05-03 18:41                                     ` Alan Third
  2020-05-03 19:49                                       ` Filipp Gunbin
  0 siblings, 1 reply; 24+ messages in thread
From: Alan Third @ 2020-05-03 18:41 UTC (permalink / raw)
  To: Filipp Gunbin; +Cc: 40200, HaiJun Zhang, Andrii Kolomoiets

On Sun, May 03, 2020 at 08:13:35PM +0300, Filipp Gunbin wrote:
> Hi, I've just filed bug#41055 which is also about NS frame resizing, it
> may have something to do with this...

Does this patch make any difference to your issue? Or is it the cause?

Most likely the commit that’s broken it is
24cb6908d70c14792c686679cb08091447b9c3b1

-- 
Alan Third





^ permalink raw reply	[flat|nested] 24+ messages in thread

* bug#40200: bug#28872: [PATCH v4] Fix NS frame resizing issues (bug#40200, bug#28872)
  2020-05-03 18:41                                     ` Alan Third
@ 2020-05-03 19:49                                       ` Filipp Gunbin
  0 siblings, 0 replies; 24+ messages in thread
From: Filipp Gunbin @ 2020-05-03 19:49 UTC (permalink / raw)
  To: Alan Third; +Cc: 40200, HaiJun Zhang, Andrii Kolomoiets

On 03/05/2020 19:41 +0100, Alan Third wrote:

> On Sun, May 03, 2020 at 08:13:35PM +0300, Filipp Gunbin wrote:
>> Hi, I've just filed bug#41055 which is also about NS frame resizing, it
>> may have something to do with this...
>
> Does this patch make any difference to your issue? Or is it the cause?

No, not really.

> Most likely the commit that’s broken it is
> 24cb6908d70c14792c686679cb08091447b9c3b1

Yes, I think so too.





^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2020-05-03 19:49 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-23 18:13 bug#40200: 28.0.50; NS: text drawing glitches in maximized frame with frame-inhibit-implied-resize Andrii Kolomoiets
2020-03-23 19:22 ` Eli Zaretskii
2020-03-23 19:47   ` Andrii Kolomoiets
2020-03-23 23:54 ` Alan Third
2020-03-25 22:28   ` bug#40200: [PATCH] Fix NS frame resizing issues (bug#40200, bug#28872) Alan Third
2020-03-26 17:35     ` bug#28872: " Andrii Kolomoiets
2020-03-26 21:21       ` bug#28872: [PATCH v2] " Alan Third
2020-03-27  9:45         ` Andrii Kolomoiets
2020-03-27 13:22         ` Andrii Kolomoiets
2020-03-28  1:56           ` Alan Third
2020-04-04 14:17             ` bug#40200: [PATCH v3] " Alan Third
2020-04-06  6:57               ` Andrii Kolomoiets
2020-04-06 18:44                 ` bug#28872: [PATCH v4] " Alan Third
2020-04-07  8:14                   ` bug#40200: " Andrii Kolomoiets
2020-04-16 18:24                     ` bug#28872: " Alan Third
2020-04-18  1:52                       ` bug#40200: " HaiJun Zhang
2020-04-18 12:07                         ` Alan Third
2020-04-18 14:12                           ` HaiJun Zhang
2020-04-18 15:26                             ` Alan Third
2020-04-19  1:49                               ` HaiJun Zhang
2020-05-03 16:26                                 ` Alan Third
2020-05-03 17:13                                   ` Filipp Gunbin
2020-05-03 18:41                                     ` Alan Third
2020-05-03 19:49                                       ` Filipp Gunbin

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).