]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix child frame restacking on NS (bug#41422)
authorAlan Third <alan@idiocy.org>
Sun, 3 Jan 2021 16:15:18 +0000 (16:15 +0000)
committerAlan Third <alan@idiocy.org>
Sun, 3 Jan 2021 16:23:06 +0000 (16:23 +0000)
* src/nsfns.m (Fns_frame_restack): Use new restackWindow method.
* src/nsterm.m ([EmacsWindow orderFront:]):
([EmacsWindow makeKeyAndOrderFront:]):
(nswindow_orderedIndex_sort):
([EmacsWindow orderBack:]):
([EmacsWindow restackWindow:above:]): Override superclass methods to
handle child windows the way we want.

src/nsfns.m
src/nsterm.h
src/nsterm.m

index ee2daea07231a670b1dc1eb6c1b272ce1170cfff..ae114f83e4db3c7c0d6f9e079cccbf5828a7b18e 100644 (file)
@@ -1485,14 +1485,14 @@ Some window managers may refuse to restack windows.  */)
 
   if (FRAME_NS_VIEW (f1) && FRAME_NS_VIEW (f2))
     {
-      NSWindow *window = [FRAME_NS_VIEW (f1) window];
-      NSInteger window2 = [[FRAME_NS_VIEW (f2) window] windowNumber];
-      NSWindowOrderingMode flag = NILP (above) ? NSWindowBelow : NSWindowAbove;
+      EmacsWindow *window = (EmacsWindow *)[FRAME_NS_VIEW (f1) window];
+      NSWindow *window2 = [FRAME_NS_VIEW (f2) window];
+      BOOL flag = !NILP (above);
 
-      [window orderWindow: flag
-               relativeTo: window2];
-
-      return Qt;
+      if ([window restackWindow:window2 above:!NILP (above)])
+        return Qt;
+      else
+        return Qnil;
     }
   else
     {
index 3fb64494f76415b796af6f0ab8ae4bd0be29ebb6..2c9d8e85ba9b48d482abb3c3bbac4ec8f47ec9e7 100644 (file)
@@ -498,6 +498,7 @@ typedef id instancetype;
   NSPoint grabOffset;
 }
 
+- (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above;
 - (void)setAppearance;
 @end
 
index 27310639508832ff9c66c4802384e1517743a4dc..2defb9e2eec1001cd98f4452d6a30ffae1274185 100644 (file)
@@ -8693,6 +8693,112 @@ not_in_argv (NSString *arg)
 
 @implementation EmacsWindow
 
+/* It seems the only way to reorder child frames is by removing them
+   from the parent and then reattaching them in the correct order.  */
+
+- (void)orderFront:(id)sender
+{
+  NSTRACE ("[EmacsWindow orderFront:]");
+
+  NSWindow *parent = [self parentWindow];
+  if (parent)
+    {
+      [parent removeChildWindow:self];
+      [parent addChildWindow:self ordered:NSWindowAbove];
+    }
+  else
+    [super orderFront:sender];
+}
+
+- (void)makeKeyAndOrderFront:(id)sender
+{
+  NSTRACE ("[EmacsWindow makeKeyAndOrderFront:]");
+
+  if ([self parentWindow])
+    {
+      [self orderFront:sender];
+      [self makeKeyWindow];
+    }
+  else
+    [super makeKeyAndOrderFront:sender];
+}
+
+
+/* The array returned by [NSWindow parentWindow] may already be
+   sorted, but the documentation doesn't tell us whether or not it is,
+   so to be safe we'll sort it.  */
+NSInteger nswindow_orderedIndex_sort (id w1, id w2, void *c)
+{
+  NSInteger i1 = [w1 orderedIndex];
+  NSInteger i2 = [w2 orderedIndex];
+
+  if (i1 > i2)
+    return NSOrderedAscending;
+  if (i1 < i2)
+    return NSOrderedDescending;
+
+  return NSOrderedSame;
+}
+
+- (void)orderBack:(id)sender
+{
+  NSTRACE ("[EmacsWindow orderBack:]");
+
+  NSWindow *parent = [self parentWindow];
+  if (parent)
+    {
+      NSArray *children = [[parent childWindows]
+                            sortedArrayUsingFunction:nswindow_orderedIndex_sort
+                                              context:nil];
+      [parent removeChildWindow:self];
+      [parent addChildWindow:self ordered:NSWindowAbove];
+
+      for (NSWindow *win in children)
+        {
+          if (win != self)
+            {
+              [parent removeChildWindow:win];
+              [parent addChildWindow:win ordered:NSWindowAbove];
+            }
+        }
+    }
+  else
+    [super orderBack:sender];
+}
+
+- (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above
+{
+  NSTRACE ("[EmacsWindow restackWindow:above:]");
+
+  /* If parent windows don't match we can't restack these frames
+     without changing the parents.  */
+  if ([self parentWindow] != [win parentWindow])
+    return NO;
+  else if (![self parentWindow])
+    [self orderWindow:(above ? NSWindowAbove : NSWindowBelow)
+           relativeTo:[win windowNumber]];
+  else
+    {
+      NSInteger index;
+      NSWindow *parent = [self parentWindow];
+      NSMutableArray *children = [[[parent childWindows]
+                                   sortedArrayUsingFunction:nswindow_orderedIndex_sort
+                                                    context:nil]
+                                   mutableCopy];
+      [children removeObject:self];
+      index = [children indexOfObject:win];
+      [children insertObject:self atIndex:(above ? index+1 : index)];
+
+      for (NSWindow *w in children)
+        {
+          [parent removeChildWindow:w];
+          [parent addChildWindow:w ordered:NSWindowAbove];
+        }
+    }
+
+  return YES;
+}
+
 #ifdef NS_IMPL_COCOA
 - (id)accessibilityAttributeValue:(NSString *)attribute
 {