> I finally got that working.  I have attached a patch (relative to the
> current SVN tree after `make patch`).  This only touches macterm.c
> (one line) and macfns.c.
>
> I kept the functionality that returns to the original frame size when
> leaving full-screen mode even though the X port does not do that, as
> it is a very useful thing.

There was a bug in the code that restores the original frame size and
position when leaving full-screen mode.  The attached patch should be
better.

Here's an elisp function to retain the old interface, if that's
desirable:

(defun mac-toggle-max-window ()
  (interactive)
  (set-frame-parameter nil 'fullscreen (if (frame-parameter nil 'fullscreen)
                                           nil
                                           'fullboth)))

Vebjorn

--~--~---------~--~----~------------~-------~--~----~
Carbon Emacs User Group
http://groups.google.com/group/carbon-emacs?hl=en
-~----------~----~----~----~------~----~------~--~---

--- ../../emacs.orig/src/macterm.c	2008-05-16 13:43:47.000000000 -0400
+++ macterm.c	2008-05-21 12:28:28.000000000 -0400
@@ -9540,6 +9540,8 @@
   mac_shift_glyphs_for_insert
 };
 
+extern void mac_fullscreen_hook (FRAME_PTR);
+
 void
 mac_initialize ()
 {
@@ -9564,6 +9566,7 @@
   condemn_scroll_bars_hook = XTcondemn_scroll_bars;
   redeem_scroll_bar_hook = XTredeem_scroll_bar;
   judge_scroll_bars_hook = XTjudge_scroll_bars;
+  fullscreen_hook = mac_fullscreen_hook;
 
   scroll_region_ok = 1;         /* we'll scroll partial frames */
   char_ins_del_ok = 1;
--- ../../emacs.orig/src/macfns.c	2008-05-16 13:43:47.000000000 -0400
+++ macfns.c	2008-05-21 13:13:35.000000000 -0400
@@ -4392,10 +4392,11 @@
 
 typedef struct 
 {
-    Rect bounds;
+     int left, top, pixel_width, pixel_height;
 } MacWindowCustomState, **MacWindowCustomStateH;
 
-#define MAC_WINSTATE_HANDLE_FIELD_PTR(handle, fld) (&((**handle).fld))
+#define MAC_WINSTATE_FIELD_PTR(handle, fld) (&((**handle).fld))
+#define MAC_WINSTATE_FIELD(handle, fld) ((**handle).fld)
 
 void MacReleaseWindowCustomState(
     MacWindowCustomStateH h)
@@ -4404,23 +4405,34 @@
     free(h);
 }
 
-void MacToggleFullFrame(WindowRef frame);
+static
+mac_set_frame_bounds(f, left, top, pixel_width, pixel_height)
+     FRAME_PTR f;
+     int left, top, pixel_width, pixel_height;
+{
+  int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixel_height);
+  int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixel_width);
+  Lisp_Object frame;
+  XSETFRAME (frame, f);
+  Fset_frame_size (frame, make_number (columns), make_number (rows));
+  Fset_frame_position (frame, make_number (left), make_number (top));
+}
+
+extern Lisp_Object Qfullscreen;
+
 static pascal void MacOnReconfigMaximizedWindow(
     CGDirectDisplayID           dispID,
     CGDisplayChangeSummaryFlags flags,
     void*                       userInfo)
 {
-    if (flags & kCGDisplayRemoveFlag)
-    {
-        /*
-          NB: We choose to un-maximize any full-screen frame during a
-          display reconfiguration involving the removal of a display.
-        */
-
-        CGDirectDisplayID inDispID;
-        WindowRef         frame = (WindowRef) userInfo;
-        MacToggleFullFrame(frame);
-    }
+  /* Leave full-screen mode when the display is reconfigured (e.g., a
+     display is added or removed, or the resolution is changed)
+     because it is not obvious whether resizing the window is always *
+     the right thing to do. */
+  FRAME_PTR f = (FRAME_PTR) userInfo;
+  Lisp_Object frame;
+  XSETFRAME (frame, f);
+  Fmodify_frame_parameters (frame, Fcons (Fcons (Qfullscreen, Qnil), Qnil));
 }
 
 Boolean MacGetWindowCustomState(
@@ -4551,8 +4563,7 @@
     }
 }
 
-MacWindowCustomStateH MacSaveWindowCustomState(
-    WindowRef wnd)
+MacWindowCustomStateH MacSaveWindowCustomState(WindowRef wnd)
 {
     OSStatus              s;
     MacWindowCustomState* state = malloc(sizeof(MacWindowCustomState));
@@ -4561,206 +4572,191 @@
 
     MacRegisterMaxWinCloseHandler(wnd);
 
-    if (noErr != GetWindowBounds(wnd, kWindowStructureRgn, &state->bounds))
-    {
+    Rect outer_bounds, inner_bounds;
+    if (noErr != GetWindowBounds(wnd, kWindowStructureRgn, &outer_bounds) ||
+        noErr != GetWindowBounds(wnd, kWindowContentRgn, &inner_bounds))
+      {
         error("Error while obtaining window bounds.");
         MacReleaseWindowCustomState(h);
         return NULL;
-    }
-    else {
-        s = SetWindowProperty(
-            wnd,
-            MAC_EMACS_CREATOR_CODE,
-            MAC_EMACS_WINDOW_PROPTAG_MAXWIN,
-            sizeof(MacWindowCustomStateH),
-            &h);
-
-        if (s != noErr)
-        {
-            error("Error while saving window bounds.");
-            MacReleaseWindowCustomState(h);
-            return NULL;
-        }
-    }
+      }
+    state->left = outer_bounds.left;
+    state->top = outer_bounds.top;
+    state->pixel_width = inner_bounds.right - inner_bounds.left + 1;
+    state->pixel_height = inner_bounds.bottom - inner_bounds.top + 1;
+    s = SetWindowProperty(wnd, MAC_EMACS_CREATOR_CODE,
+                          MAC_EMACS_WINDOW_PROPTAG_MAXWIN,
+                          sizeof(MacWindowCustomStateH), &h);
+    if (s != noErr)
+      {
+        error("Error while saving window bounds.");
+        MacReleaseWindowCustomState(h);
+        return NULL;
+      }
     return h;
 }
 
-/* This function is the workhorse routine for the toggle max-size frame
+/* This function is the workhorse routine for the fullscreen
    behavior. */
 
-/* workaround for compiling on pre-10.4 systems */ 
+/* Workaround for compiling on pre-10.4 systems. */ 
 #define FNS_kWindowNoTitleBarAttribute 512
 
-void MacToggleFullFrame(
-    WindowRef frame)
+static void
+enter_fullscreen (f)
+     FRAME_PTR f;
 {
-    OSStatus              st;
-    CGError               e;
-    CGDirectDisplayID     inDispID;
-    MacWindowCustomStateH savedState_h;
-    
-    if (MacGetWindowCustomState(frame, &savedState_h))
-    {
-        /* We're un-maximizing the current frame. */
-
-        Rect* bounds_p =
-            MAC_WINSTATE_HANDLE_FIELD_PTR(savedState_h, bounds);
-
-        /*
-           Saved window state only exists when frame has already been
-           maximized, so we need to restore the window to its initial,
-           pre-maximized state and then remove the saved window state
-           from the window.
-        */
-
-        /* Enable title bar and resizability */
-        st = ChangeWindowAttributes(
-            frame,
-            kWindowResizableAttribute,
-            FNS_kWindowNoTitleBarAttribute);
-        if (st != noErr)
-        {
-            error ("Error during unmaximize: couldn't change window attributes.");
-            goto unmax_cleanup;
-        }
-
-        /* Reset window size */
-        st = SetWindowBounds(frame, kWindowStructureRgn, bounds_p);
-        if (st != noErr)
-        {
-            error ("Error during unmaximize: couldn't reset window bounds.");
-            goto unmax_cleanup;
-        }
+  OSStatus st;
 
-        MacHandleMenuBarBehavior(false,frame);
+  WindowRef mac_window = FRAME_MAC_WINDOW (f);
 
-        /* Resize and/or move the frame as needed in case the saved
-           bounds aren't acceptable for the current display */
+  MacWindowCustomStateH savedState_h = MacSaveWindowCustomState (mac_window);
+  if (savedState_h == NULL)
+    {
+      UNBLOCK_INPUT;
+      error ("Error during maximize: couldn't save window custom state.");
+    }
 
-        st = ConstrainWindowToScreen(
-            frame,
-            kWindowStructureRgn,
-            kWindowConstrainStandardOptions,
-            NULL,
-            NULL);
+  /* Remove title bar & resizability from the window */
+  st = ChangeWindowAttributes (mac_window, FNS_kWindowNoTitleBarAttribute,
+                               kWindowResizableAttribute);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      MacReleaseWindowCustomState (savedState_h);
+      error ("Error during maximize: couldn't set window attributes.");
+    }
 
-        if (st != noErr)
-        {
-            error("Error during unmaximize: couldn't constrain window.");
-            goto unmax_cleanup;
-        }
+  short mbarHeight = MacHandleMenuBarBehavior (true, mac_window);
 
-        /* Toss the saved data */
-        st = RemoveWindowProperty(
-            frame,
-            MAC_EMACS_CREATOR_CODE,
-            MAC_EMACS_WINDOW_PROPTAG_MAXWIN);
-        if (st != noErr)
-        {
-            error ("Error during unmaximize: couldn't remove window state.");
-            goto unmax_cleanup;
-        }
-        
-    unmax_cleanup:
-        MacReleaseWindowCustomState(savedState_h);
-        
-        /* Unregister the display reconfiguration cb */
-        e = CGDisplayRemoveReconfigurationCallback(
-            MacOnReconfigMaximizedWindow,
-            frame);
-        if (e != noErr)
-            error ("Error during unmaximize: couldn't unregister cb");
+  /* Enlarge the window to the screen bounds (unless the user
+     chose to only maximize width or height), leaving room for the
+     menubar to if it is visible (this can be controlled by the
+     user via mac-autohide-menubar-on-maximize */
+  CGDirectDisplayID inDispID;
+  st = MacGetDisplayIdForWindow (mac_window, &inDispID);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      MacReleaseWindowCustomState (savedState_h);
+      error ("Error during maximize: couldn't get display id");
     }
-    else
+  int left = MAC_WINSTATE_FIELD (savedState_h, left);
+  int top = MAC_WINSTATE_FIELD (savedState_h, top);
+  int pixel_width = MAC_WINSTATE_FIELD (savedState_h, pixel_width);
+  int pixel_height = MAC_WINSTATE_FIELD (savedState_h, pixel_height);
+  Rect screen_bounds = MacConvertCGRectToRect (CGDisplayBounds(inDispID));
+  screen_bounds.top += mbarHeight;
+  if (f->want_fullscreen & FULLSCREEN_HEIGHT)
     {
-        /* We're maximizing the current frame. */
-
-        Rect                  screenBnds;
-        CGDirectDisplayID     inDispID;
-        short                 mbarHeight;
+      top = screen_bounds.top;
+      pixel_height = screen_bounds.bottom - top + 1;
+    }
+  if (f->want_fullscreen & FULLSCREEN_WIDTH)
+    {
+      left = screen_bounds.left;
+      pixel_width = screen_bounds.right - left + 1;
+    }
+  mac_set_frame_bounds (f, left, top, pixel_width, pixel_height);
+        
+  /* Register a callback to restore the window to its old size when
+     the displays are reconfigured; if we don't do this, we can end
+     up with a maximized window that is larger than the current
+     display.  The cb is unregistered on un-maximize. */
+  CGError e = CGDisplayRegisterReconfigurationCallback
+    (MacOnReconfigMaximizedWindow, f);
+  if (e != noErr)
+    {
+      UNBLOCK_INPUT;
+      MacReleaseWindowCustomState (savedState_h);
+      error ("Error during maximize: couldn't register reconfig cb");
+    }
+  f->want_fullscreen = FULLSCREEN_NONE;
+}
 
-        savedState_h = MacSaveWindowCustomState(frame);
-        if (savedState_h == NULL)
-            return;
+static void
+leave_fullscreen (f)
+     FRAME_PTR f;
+{
+  OSStatus st;
 
-        mbarHeight = MacHandleMenuBarBehavior(true, frame);
-        
-        /* Remove title bar & resizability from the window */
-        st = ChangeWindowAttributes(
-            frame,
-            FNS_kWindowNoTitleBarAttribute,
-            kWindowResizableAttribute);
-        if (st != noErr)
-        {
-            error("Error during maximize: couldn't set window attributes.");
-            goto max_cleanup;
-        }
+  WindowRef mac_window = FRAME_MAC_WINDOW (f);
 
-        st = MacGetDisplayIdForWindow(frame, &inDispID);
-        if (st != noErr)
-        {
-            error ("Error during maximize: couldn't get display id");
-            goto max_cleanup;
-        }
+  /* Enable title bar and resizability */
+  st = ChangeWindowAttributes (mac_window, kWindowResizableAttribute,
+                               FNS_kWindowNoTitleBarAttribute);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      error ("Error during unmaximize: couldn't change window attributes.");
+    }
 
-        /* Maximize the window to the screen bounds, , leaving room
-           for the menubar to if it is visible (this can be
-           controlled by the user via mac-autohide-menubar-on-maximize */
+  /* Reset window size */
+  MacWindowCustomStateH savedState_h;
+  if (!MacGetWindowCustomState (mac_window, &savedState_h)) 
+    {
+      UNBLOCK_INPUT;
+      error ("Error during unmaximize: couldn't get window custom state.");
+    }
+  int left = MAC_WINSTATE_FIELD (savedState_h, left);
+  int top = MAC_WINSTATE_FIELD (savedState_h, top);
+  int pixel_width = MAC_WINSTATE_FIELD (savedState_h, pixel_width);
+  int pixel_height = MAC_WINSTATE_FIELD (savedState_h, pixel_height);
+  mac_set_frame_bounds (f, left, top, pixel_width, pixel_height);
 
-        screenBnds      = MacConvertCGRectToRect(CGDisplayBounds(inDispID));
-        screenBnds.top += mbarHeight;
+  MacReleaseWindowCustomState (savedState_h);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      error ("Error during unmaximize: couldn't reset window bounds.");
+    }
 
-        st = SetWindowBounds(frame, kWindowStructureRgn, &screenBnds);
-        if (st != noErr)
-        {
-            error ("Error during maximize: couldn't set window bounds.");
-            goto max_cleanup;
-        }
-        
-        /*
-          Register a callback to restore the window to its old size when
-          the displays are reconfigured; if we don't do this, we can end
-          up with a maximized window that is larger than the current
-          display.  The cb is unregistered on un-maximize.
-        */
-
-        e = CGDisplayRegisterReconfigurationCallback(
-            MacOnReconfigMaximizedWindow,
-            frame);
-        if (e != noErr)
-        {
-            error ("Error during maximize: couldn't register reconfig cb");
-            goto max_cleanup;
-        }
+  MacHandleMenuBarBehavior (false, mac_window);
 
-        goto max_done;
-        
-    max_cleanup:
-        MacReleaseWindowCustomState(savedState_h);
+  /* Resize and/or move the mac_window as needed in case the saved
+     bounds aren't acceptable for the current display */
+  st = ConstrainWindowToScreen (mac_window, kWindowStructureRgn,
+                                kWindowConstrainStandardOptions,
+                                NULL, NULL);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      error("Error during unmaximize: couldn't constrain window.");
+    }
 
-    max_done:
-        return;
+  f->want_fullscreen = FULLSCREEN_NONE;
+  /* Toss the saved data */
+  st = RemoveWindowProperty (mac_window, MAC_EMACS_CREATOR_CODE,
+                             MAC_EMACS_WINDOW_PROPTAG_MAXWIN);
+  if (st != noErr)
+    {
+      UNBLOCK_INPUT;
+      error ("Error during unmaximize: couldn't remove window state.");
     }
+
+  /* Unregister the display reconfiguration cb */
+  CGError e = CGDisplayRemoveReconfigurationCallback 
+    (MacOnReconfigMaximizedWindow, f);
+  if (e != noErr)
+    error ("Error during unmaximize: couldn't unregister callback.");
 }
 
-DEFUN ("mac-toggle-full-frame", Fmac_toggle_full_frame, Smac_toggle_full_frame, 0, 0, "",
-       doc: /* Makes the current frame use as much of the display as
-possible, or reverts it to its previous size and position if already
-maximized.  If mac-autohide-menubar-on-maximize is non-nil, maximized
-frames auto-hide the menubar.*/)
-    ()
+void
+mac_fullscreen_hook (f)
+     FRAME_PTR f;
 {
-    if (!EQ (Vwindow_system, intern ("mac")))
-        return Qnil;
 
-    BLOCK_INPUT;
-    
-    WindowRef frame = GetUserFocusWindow();
-    MacToggleFullFrame(frame);
+  if (!f->async_visible)
+    return;
 
-    UNBLOCK_INPUT;
-    return Qnil;
+  BLOCK_INPUT;
+  if (f->want_fullscreen == FULLSCREEN_NONE)
+    leave_fullscreen(f);
+  else
+    enter_fullscreen(f);
+  UNBLOCK_INPUT;
 }
+
 /* === End support for maximizing frames to the full display. === */
 
 #endif /* MAC_OSX && TARGET_API_MAC_CARBON */
@@ -5163,7 +5159,6 @@
 #if TARGET_API_MAC_CARBON
   defsubr (&Sx_file_dialog);
 #if MAC_OSX
-  defsubr (&Smac_toggle_full_frame);
   defsubr (&Smac_show_menu_bar);
   defsubr (&Smac_hide_menu_bar);
   defsubr (&Smac_dialog);

Reply via email to