changeset 112396:e79e716435f4

Make Nextstep port handle multiple screens for resize and move. * nsterm.h (ns_output): Add dont_constrain and zooming. (EmacsView): Add ns_userRect. * nsterm.m (keyDown): If ns_right_alternate_modifier is Qleft, check if ns_alternate_modifier is none. * nsterm.m (x_set_offset, windowDidMove): When calculating y, use first screen, not the window screen. (x_set_window_size): Remove constraints. Calculate origin.y only if zooming is 0 and without referring to a screen. (windowWillResize): Don't modify frameSize. (windowDidBecomeKey, mouseDown): Set dont_constrain to 1. (initFrameFromEmacs): Initialize ns_userRect. (windowShouldZoom): Set zooming to one. Remove all other code. (windowWillUseStandardFrame): Move static ns_userRect to EmacsView. Zero it after restore. (constrainFrameRect): New method for EmacsWindow. (mouseDragged): Always post NSWindowDidResizeNotification after call to windowWillResize.
author Jan D. <jan.h.d@swipnet.se>
date Fri, 21 Jan 2011 15:19:44 +0100
parents f1de024f822c
children a7191495c39c
files src/ChangeLog src/nsterm.h src/nsterm.m
diffstat 3 files changed, 66 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Jan 21 09:35:30 2011 +0100
+++ b/src/ChangeLog	Fri Jan 21 15:19:44 2011 +0100
@@ -1,5 +1,23 @@
 2011-01-21  Jan Djärv  <jan.h.d@swipnet.se>
 
+	* nsterm.m (x_set_offset, windowDidMove): When calculating y, use first
+	screen, not the window screen.
+	(x_set_window_size): Remove constraints.
+	Calculate origin.y only if zooming is 0 and without referring to a
+	screen.
+	(windowWillResize): Don't modify frameSize.
+	(windowDidBecomeKey, mouseDown): Set dont_constrain to 1.
+	(initFrameFromEmacs): Initialize ns_userRect.
+	(windowShouldZoom): Set zooming to one.  Remove all other code.
+	(windowWillUseStandardFrame): Move static ns_userRect to EmacsView.
+	Zero it after restore.
+	(constrainFrameRect): New method for EmacsWindow.
+	(mouseDragged): Always post NSWindowDidResizeNotification after call to
+	windowWillResize.
+
+	* nsterm.h (ns_output): Add dont_constrain and zooming.
+	(EmacsView): Add ns_userRect.
+
 	* nsterm.m (keyDown): If ns_right_alternate_modifier is Qleft, check
 	if ns_alternate_modifier is none.
 
--- a/src/nsterm.h	Fri Jan 21 09:35:30 2011 +0100
+++ b/src/nsterm.h	Fri Jan 21 15:19:44 2011 +0100
@@ -66,6 +66,7 @@
    int rows, cols;
    int scrollbarsNeedingUpdate;
    EmacsToolbar *toolbar;
+   NSRect ns_userRect;
    }
 
 /* AppKit-side interface */
@@ -565,6 +566,12 @@
 
   /* This is the Emacs structure for the NS display this frame is on.  */
   struct ns_display_info *display_info;
+
+  /* Non-zero if we want to constrain the frame to the screen.  */
+  int dont_constrain;
+
+  /* Non-zero if we are zooming (maximizing) the frame.  */
+  int zooming;
 };
 
 /* this dummy decl needed to support TTYs */
--- a/src/nsterm.m	Fri Jan 21 09:35:30 2011 +0100
+++ b/src/nsterm.m	Fri Jan 21 15:19:44 2011 +0100
@@ -1053,8 +1053,10 @@
      External: Position the window
    -------------------------------------------------------------------------- */
 {
-  NSScreen *screen;
   NSView *view = FRAME_NS_VIEW (f);
+  NSArray *screens = [NSScreen screens];
+  NSScreen *fscreen = [screens objectAtIndex: 0];
+  NSScreen *screen = [[view window] screen];
 
   NSTRACE (x_set_offset);
 
@@ -1063,7 +1065,7 @@
   f->left_pos = xoff;
   f->top_pos = yoff;
 
-  if (view != nil && (screen = [[view window] screen]))
+  if (view != nil && screen && fscreen)
     {
       f->left_pos = f->size_hint_flags & XNegative
         ? [screen visibleFrame].size.width + f->left_pos - FRAME_PIXEL_WIDTH (f)
@@ -1082,7 +1084,7 @@
 #endif
       [[view window] setFrameTopLeftPoint:
                        NSMakePoint (SCREENMAXBOUND (f->left_pos),
-                                    SCREENMAXBOUND ([screen frame].size.height
+                                    SCREENMAXBOUND ([fscreen frame].size.height
                                                     - NS_TOP_POS (f)))];
       f->size_hint_flags &= ~(XNegative|YNegative);
     }
@@ -1096,13 +1098,12 @@
 /* --------------------------------------------------------------------------
      Adjust window pixel size based on given character grid size
      Impl is a bit more complex than other terms, need to do some
-     internal clipping and also pay attention to screen constraints.
+     internal clipping.
    -------------------------------------------------------------------------- */
 {
   EmacsView *view = FRAME_NS_VIEW (f);
   EmacsToolbar *toolbar = [view toolbar];
   NSWindow *window = [view window];
-  NSScreen *screen = [window screen];
   NSRect wr = [window frame];
   int tb = FRAME_EXTERNAL_TOOL_BAR (f);
   int pixelwidth, pixelheight;
@@ -1153,31 +1154,13 @@
   wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) 
                   + FRAME_TOOLBAR_HEIGHT (f);
 
-  /* constrain to screen if we can */
-  if (screen)
-    {
-      NSSize sz = [screen visibleFrame].size;
-      NSSize ez = { wr.size.width - sz.width, wr.size.height - sz.height };
-      if (ez.width > 0)
-        {
-          int cr = ez.width / FRAME_COLUMN_WIDTH (f) + 1;
-          cols -= cr;
-          oldCols = cols;
-          wr.size.width -= cr * FRAME_COLUMN_WIDTH (f);
-          pixelwidth -= cr * FRAME_COLUMN_WIDTH (f);
-        }
-      if (ez.height > 0)
-        {
-          int rr = ez.height / FRAME_LINE_HEIGHT (f) + 1;
-          rows -= rr;
-          oldRows = rows;
-          wr.size.height -= rr * FRAME_LINE_HEIGHT (f);
-          pixelheight -= rr * FRAME_LINE_HEIGHT (f);
-        }
-      wr.origin.x = f->left_pos;
-      wr.origin.y = [screen frame].size.height - NS_TOP_POS (f)
-        - wr.size.height;
-    }
+  /* Do not try to constrain to this screen.  We may have multiple
+     screens, and want Emacs to span those.  Constraining to screen
+     prevents that, and that is not nice to the user.  */
+ if (f->output_data.ns->zooming)
+   f->output_data.ns->zooming = 0;
+ else
+   wr.origin.y += FRAME_PIXEL_HEIGHT (f) - pixelheight;
 
   [view setRows: rows andColumns: cols];
   [window setFrame: wr display: YES];
@@ -4987,7 +4970,6 @@
 #endif
   if (cols < MINWIDTH)
     cols = MINWIDTH;
-  frameSize.width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
 
   rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height
 #ifdef NS_IMPL_GNUSTEP
@@ -4999,9 +4981,6 @@
 #endif
   if (rows < MINHEIGHT)
     rows = MINHEIGHT;
-  frameSize.height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows)
-                       + FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
-                       + FRAME_TOOLBAR_HEIGHT (emacsframe);
 #ifdef NS_IMPL_COCOA
   {
     /* this sets window title to have size in it; the wm does this under GS */
@@ -5069,7 +5048,7 @@
      a "windowDidResize" which calls x_set_window_size).  */
 #ifndef NS_IMPL_GNUSTEP
   if (cols > 0 && rows > 0)
-     x_set_window_size (emacsframe, 0, cols, rows);
+    x_set_window_size (emacsframe, 0, cols, rows);
 #endif
 
   ns_send_appdefined (-1);
@@ -5084,6 +5063,7 @@
 
   NSTRACE (windowDidBecomeKey);
 
+  emacsframe->output_data.ns->dont_constrain = 1;
   if (emacsframe != old_focus)
     dpyinfo->x_focus_frame = emacsframe;
 
@@ -5162,6 +5142,7 @@
 
 /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
 
+  ns_userRect = NSMakeRect (0, 0, 0, 0);
   r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
                  FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
   [self initWithFrame: r];
@@ -5248,7 +5229,8 @@
 {
   NSWindow *win = [self window];
   NSRect r = [win frame];
-  NSScreen *screen = [win screen];
+  NSArray *screens = [NSScreen screens];
+  NSScreen *screen = [screens objectAtIndex: 0];
 
   NSTRACE (windowDidMove);
 
@@ -5268,10 +5250,7 @@
    location so set_window_size moves the frame. */
 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
 {
-  NSTRACE (windowShouldZoom);
-  emacsframe->left_pos = (int)newFrame.origin.x;
-  emacsframe->top_pos = [[sender screen] frame].size.height
-                            - (newFrame.origin.y+newFrame.size.height);
+  emacsframe->output_data.ns->zooming = 1;
   return YES;
 }
 
@@ -5283,7 +5262,6 @@
                         defaultFrame:(NSRect)defaultFrame
 {
   NSRect result = [sender frame];
-  static NSRect ns_userRect = { 0, 0, 0, 0 };
 
   NSTRACE (windowWillUseStandardFrame);
 
@@ -5301,7 +5279,11 @@
           > FRAME_COLUMN_WIDTH (emacsframe))
         result = defaultFrame;  /* second click */
       else
-        result = ns_userRect.size.height ? ns_userRect : result;  /* restore */
+        {
+          /* restore */
+          result = ns_userRect.size.height ? ns_userRect : result;
+          ns_userRect = NSMakeRect (0, 0, 0, 0);
+        }
     }
 
   [self windowWillResize: sender toSize: result.size];
@@ -5686,9 +5668,25 @@
 
 @implementation EmacsWindow
 
+/* If we have multiple monitors, one above the other, we don't want to
+   restrict the height to just one monitor.  So we override this.  */
+- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
+{
+  /* When making the frame visible for the first time, we want to
+     constrain.  Other times not.  */
+  struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
+  if (f->output_data.ns->dont_constrain)
+    return frameRect;
+
+  return [super constrainFrameRect:frameRect toScreen:screen];
+}
+
+
 /* called only on resize clicks by special case in EmacsApp-sendEvent */
 - (void)mouseDown: (NSEvent *)theEvent
 {
+  struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
+  f->output_data.ns->dont_constrain = 1;
   if (ns_in_resize)
     {
       NSSize size = [[theEvent window] frame].size;
@@ -5731,12 +5729,9 @@
         return;
 
       vettedSize = [[self delegate] windowWillResize: self toSize: size];
-      if (vettedSize.width != size.width || vettedSize.height != size.height)
-        {
-          [[NSNotificationCenter defaultCenter]
+      [[NSNotificationCenter defaultCenter]
             postNotificationName: NSWindowDidResizeNotification
                           object: self];
-        }
     }
   else
     [super mouseDragged: theEvent];