]> code.delx.au - gnu-emacs/blobdiff - src/macterm.c
* emacs.c (Fdump_emacs): Only output warning on GNU/Linux.
[gnu-emacs] / src / macterm.c
index a5146dc8ec4db6ff6717a24b0a35f37d85aca956..eae892fb7fc0fc3ae058c965339243937a30c402 100644 (file)
@@ -50,6 +50,7 @@ Boston, MA 02111-1307, USA.  */
 #include <TextUtils.h>
 #include <LowMem.h>
 #include <Controls.h>
 #include <TextUtils.h>
 #include <LowMem.h>
 #include <Controls.h>
+#include <Windows.h>
 #if defined (__MRC__) || (__MSL__ >= 0x6000)
 #include <ControlDefinitions.h>
 #endif
 #if defined (__MRC__) || (__MSL__ >= 0x6000)
 #include <ControlDefinitions.h>
 #endif
@@ -227,6 +228,10 @@ extern int errno;
 
 extern int extra_keyboard_modifiers;
 
 
 extern int extra_keyboard_modifiers;
 
+/* The keysyms to use for the various modifiers.  */
+
+static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
+
 static Lisp_Object Qvendor_specific_keysyms;
 
 #if 0
 static Lisp_Object Qvendor_specific_keysyms;
 
 #if 0
@@ -1290,9 +1295,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
                                output_cursor.vpos,
                                output_cursor.x, output_cursor.y);
 
-      x_draw_vertical_border (w);
-
-      draw_window_fringes (w);
+      if (draw_window_fringes (w, 1))
+       x_draw_vertical_border (w);
 
       UNBLOCK_INPUT;
     }
 
       UNBLOCK_INPUT;
     }
@@ -1325,6 +1329,10 @@ static void
 x_update_end (f)
      struct frame *f;
 {
 x_update_end (f)
      struct frame *f;
 {
+  /* Mouse highlight may be displayed again.  */
+  FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
+
+  BLOCK_INPUT;
   /* Reset the background color of Mac OS Window to that of the frame after
      update so that it is used by Mac Toolbox to clear the update region before
      an update event is generated.  */
   /* Reset the background color of Mac OS Window to that of the frame after
      update so that it is used by Mac Toolbox to clear the update region before
      an update event is generated.  */
@@ -1332,10 +1340,6 @@ x_update_end (f)
 
   mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
 
 
   mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
 
-  /* Mouse highlight may be displayed again.  */
-  FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
-
-  BLOCK_INPUT;
   XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
 }
   XFlush (FRAME_MAC_DISPLAY (f));
   UNBLOCK_INPUT;
 }
@@ -3887,18 +3891,21 @@ remember_mouse_glyph (f1, gx, gy)
 
 
 static WindowPtr
 
 
 static WindowPtr
-mac_front_window ()
+front_emacs_window ()
 {
 #if TARGET_API_MAC_CARBON
 {
 #if TARGET_API_MAC_CARBON
-  return GetFrontWindowOfClass (kDocumentWindowClass, true);
+  WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
+
+  while (wp && !is_emacs_window (wp))
+    wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
 #else
 #else
-  WindowPtr front_window = FrontWindow ();
+  WindowPtr wp = FrontWindow ();
 
 
-  if (tip_window && front_window == tip_window)
-    return GetNextWindow (front_window);
-  else
-    return front_window;
+  while (wp && (wp == tip_window || !is_emacs_window (wp)))
+    wp = GetNextWindow (wp);
 #endif
 #endif
+
+  return wp;
 }
 
 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
 }
 
 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
@@ -3934,7 +3941,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 {
   Point mouse_pos;
   int ignore1, ignore2;
 {
   Point mouse_pos;
   int ignore1, ignore2;
-  WindowPtr wp = mac_front_window ();
+  WindowPtr wp = front_emacs_window ();
   struct frame *f;
   Lisp_Object frame, tail;
 
   struct frame *f;
   Lisp_Object frame, tail;
 
@@ -4551,7 +4558,7 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
-  WindowPtr wp = mac_front_window ();
+  WindowPtr wp = front_emacs_window ();
   Point mouse_pos;
   struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
   Point mouse_pos;
   struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
@@ -5036,6 +5043,26 @@ xim_close_dpy (dpyinfo)
  */
 
 \f
  */
 
 \f
+void
+mac_get_window_bounds (f, inner, outer)
+     struct frame *f;
+     Rect *inner, *outer;
+{
+#if TARGET_API_MAC_CARBON
+  GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
+  GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
+#else /* not TARGET_API_MAC_CARBON */
+  RgnHandle region = NewRgn ();
+
+  GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
+  *inner = (*region)->rgnBBox;
+  GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
+  *outer = (*region)->rgnBBox;
+  DisposeRgn (region);
+#endif /* not TARGET_API_MAC_CARBON */
+}
+
+
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
 /* Calculate the absolute position in frame F
    from its current recorded position values and gravity.  */
 
@@ -5043,47 +5070,36 @@ void
 x_calc_absolute_position (f)
      struct frame *f;
 {
 x_calc_absolute_position (f)
      struct frame *f;
 {
-  Point pt;
+  int width_diff = 0, height_diff = 0;
   int flags = f->size_hint_flags;
   int flags = f->size_hint_flags;
+  Rect inner, outer;
 
 
-  pt.h = pt.v = 0;
+  /* We have nothing to do if the current position
+     is already for the top-left corner.  */
+  if (! ((flags & XNegative) || (flags & YNegative)))
+    return;
 
 
-  /* Find the position of the outside upper-left corner of
+  /* Find the offsets of the outside upper-left corner of
      the inner window, with respect to the outer window.  */
      the inner window, with respect to the outer window.  */
-  if (f->output_data.mac->parent_desc != FRAME_MAC_DISPLAY_INFO (f)->root_window)
-    {
-      GrafPtr savePort;
-      GetPort (&savePort);
-
-      SetPortWindowPort (FRAME_MAC_WINDOW (f));
+  mac_get_window_bounds (f, &inner, &outer);
 
 
-#if TARGET_API_MAC_CARBON
-      {
-        Rect r;
-
-        GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r);
-        SetPt(&pt, r.left,  r.top);
-      }
-#else /* not TARGET_API_MAC_CARBON */
-      SetPt(&pt, FRAME_MAC_WINDOW (f)->portRect.left,  FRAME_MAC_WINDOW (f)->portRect.top);
-#endif /* not TARGET_API_MAC_CARBON */
-      LocalToGlobal (&pt);
-      SetPort (savePort);
-    }
+  width_diff = (outer.right - outer.left) - (inner.right - inner.left);
+  height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
 
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
 
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
     f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
-                  - 2 * f->border_width - pt.h
+                   - width_diff
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos);
                   - FRAME_PIXEL_WIDTH (f)
                   + f->left_pos);
-  /* NTEMACS_TODO: Subtract menubar height?  */
+
   if (flags & YNegative)
     f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
   if (flags & YNegative)
     f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
-                 - 2 * f->border_width - pt.v
+                 - height_diff
                  - FRAME_PIXEL_HEIGHT (f)
                  + f->top_pos);
                  - FRAME_PIXEL_HEIGHT (f)
                  + f->top_pos);
+
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
   /* The left_pos and top_pos
      are now relative to the top and left screen edges,
      so the flags should correspond.  */
@@ -5102,8 +5118,6 @@ x_set_offset (f, xoff, yoff, change_gravity)
      register int xoff, yoff;
      int change_gravity;
 {
      register int xoff, yoff;
      int change_gravity;
 {
-  int modified_top, modified_left;
-
   if (change_gravity > 0)
     {
       f->top_pos = yoff;
   if (change_gravity > 0)
     {
       f->top_pos = yoff;
@@ -5120,11 +5134,55 @@ x_set_offset (f, xoff, yoff, change_gravity)
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
   BLOCK_INPUT;
   x_wm_set_size_hint (f, (long) 0, 0);
 
-  modified_left = f->left_pos;
-  modified_top = f->top_pos;
-
-  MoveWindow (f->output_data.mac->mWP, modified_left + 6,
-             modified_top + 42, false);
+#if TARGET_API_MAC_CARBON
+  MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
+  /* If the title bar is completely outside the screen, adjust the
+     position. */
+  ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
+                          kWindowConstrainMoveRegardlessOfFit
+                          | kWindowConstrainAllowPartial, NULL, NULL);
+  x_real_positions (f, &f->left_pos, &f->top_pos);
+#else
+  {
+    Rect inner, outer, screen_rect, dummy;
+    RgnHandle region = NewRgn ();
+
+    mac_get_window_bounds (f, &inner, &outer);
+    f->x_pixels_diff = inner.left - outer.left;
+    f->y_pixels_diff = inner.top - outer.top;
+    MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
+               f->top_pos + f->y_pixels_diff, false);
+
+    /* If the title bar is completely outside the screen, adjust the
+       position.  The variable `outer' holds the title bar rectangle.
+       The variable `inner' holds slightly smaller one than `outer',
+       so that the calculation of overlapping may not become too
+       strict.  */
+    GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
+    outer = (*region)->rgnBBox;
+    DisposeRgn (region);
+    inner = outer;
+    InsetRect (&inner, 8, 8);
+    screen_rect = qd.screenBits.bounds;
+    screen_rect.top += GetMBarHeight ();
+
+    if (!SectRect (&inner, &screen_rect, &dummy))
+      {
+       if (inner.right <= screen_rect.left)
+         f->left_pos = screen_rect.left;
+       else if (inner.left >= screen_rect.right)
+         f->left_pos = screen_rect.right - (outer.right - outer.left);
+
+       if (inner.bottom <= screen_rect.top)
+         f->top_pos = screen_rect.top;
+       else if (inner.top >= screen_rect.bottom)
+         f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
+
+       MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
+                   f->top_pos + f->y_pixels_diff, false);
+      }
+  }
+#endif
 
   UNBLOCK_INPUT;
 }
 
   UNBLOCK_INPUT;
 }
@@ -5263,7 +5321,11 @@ x_raise_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
      struct frame *f;
 {
   if (f->async_visible)
-    SelectWindow (FRAME_MAC_WINDOW (f));
+    {
+      BLOCK_INPUT;
+      SelectWindow (FRAME_MAC_WINDOW (f));
+      UNBLOCK_INPUT;
+    }
 }
 
 /* Lower frame F.  */
 }
 
 /* Lower frame F.  */
@@ -5272,7 +5334,11 @@ x_lower_frame (f)
      struct frame *f;
 {
   if (f->async_visible)
      struct frame *f;
 {
   if (f->async_visible)
-    SendBehind (FRAME_MAC_WINDOW (f), nil);
+    {
+      BLOCK_INPUT;
+      SendBehind (FRAME_MAC_WINDOW (f), nil);
+      UNBLOCK_INPUT;
+    }
 }
 
 static void
 }
 
 static void
@@ -5321,7 +5387,6 @@ x_make_frame_visible (f)
 
   XFlush (FRAME_MAC_DISPLAY (f));
 
 
   XFlush (FRAME_MAC_DISPLAY (f));
 
-#if 0 /* MAC_TODO */
   /* Synchronize to ensure Emacs knows the frame is visible
      before we do anything else.  We do this loop with input not blocked
      so that incoming events are handled.  */
   /* Synchronize to ensure Emacs knows the frame is visible
      before we do anything else.  We do this loop with input not blocked
      so that incoming events are handled.  */
@@ -5365,9 +5430,6 @@ x_make_frame_visible (f)
        FRAME_SAMPLE_VISIBILITY (f);
       }
   }
        FRAME_SAMPLE_VISIBILITY (f);
       }
   }
-#else
-  UNBLOCK_INPUT;
-#endif /* MAC_TODO */
 }
 
 /* Change from mapped state to withdrawn state.  */
 }
 
 /* Change from mapped state to withdrawn state.  */
@@ -6904,6 +6966,7 @@ x_find_ccl_program (fontp)
 /* true when cannot handle any Mac OS events */
 static int handling_window_update = 0;
 
 /* true when cannot handle any Mac OS events */
 static int handling_window_update = 0;
 
+#if 0
 /* the flag appl_is_suspended is used both for determining the sleep
    time to be passed to WaitNextEvent and whether the cursor should be
    drawn when updating the display.  The cursor is turned off when
 /* the flag appl_is_suspended is used both for determining the sleep
    time to be passed to WaitNextEvent and whether the cursor should be
    drawn when updating the display.  The cursor is turned off when
@@ -6913,6 +6976,7 @@ static int handling_window_update = 0;
    suspended.  */
 static Boolean app_is_suspended = false;
 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
    suspended.  */
 static Boolean app_is_suspended = false;
 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
+#endif
 
 #define EXTRA_STACK_ALLOC (256 * 1024)
 
 
 #define EXTRA_STACK_ALLOC (256 * 1024)
 
@@ -6928,6 +6992,9 @@ Lisp_Object Qreverse;
 /* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
 /* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* Modifier associated with the option key, or nil for normal behavior. */
+Lisp_Object Vmac_option_modifier;
+
 /* True if the ctrl and meta keys should be reversed.  */
 Lisp_Object Vmac_reverse_ctrl_meta;
 
 /* True if the ctrl and meta keys should be reversed.  */
 Lisp_Object Vmac_reverse_ctrl_meta;
 
@@ -7009,6 +7076,12 @@ mac_to_emacs_modifiers (EventModifiers mods)
     result |= meta_modifier;
   if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
     result |= alt_modifier;
     result |= meta_modifier;
   if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
     result |= alt_modifier;
+  if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
+      Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
+      if (!NILP(val))
+          result |= XUINT(val);
+  }
+
   return result;
 }
 
   return result;
 }
 
@@ -7239,11 +7312,13 @@ is_emacs_window (WindowPtr win)
 static void
 do_app_resume ()
 {
 static void
 do_app_resume ()
 {
+  /* Window-activate events will do the job. */
+#if 0
   WindowPtr wp;
   struct frame *f;
 
   WindowPtr wp;
   struct frame *f;
 
-  wp = mac_front_window ();
-  if (is_emacs_window (wp))
+  wp = front_emacs_window ();
+  if (wp)
     {
       f = mac_window_to_frame (wp);
 
     {
       f = mac_window_to_frame (wp);
 
@@ -7256,16 +7331,19 @@ do_app_resume ()
 
   app_is_suspended = false;
   app_sleep_time = WNE_SLEEP_AT_RESUME;
 
   app_is_suspended = false;
   app_sleep_time = WNE_SLEEP_AT_RESUME;
+#endif
 }
 
 static void
 do_app_suspend ()
 {
 }
 
 static void
 do_app_suspend ()
 {
+  /* Window-deactivate events will do the job. */
+#if 0
   WindowPtr wp;
   struct frame *f;
 
   WindowPtr wp;
   struct frame *f;
 
-  wp = mac_front_window ();
-  if (is_emacs_window (wp))
+  wp = front_emacs_window ();
+  if (wp)
     {
       f = mac_window_to_frame (wp);
 
     {
       f = mac_window_to_frame (wp);
 
@@ -7278,6 +7356,7 @@ do_app_suspend ()
 
   app_is_suspended = true;
   app_sleep_time = WNE_SLEEP_AT_SUSPEND;
 
   app_is_suspended = true;
   app_sleep_time = WNE_SLEEP_AT_SUSPEND;
+#endif
 }
 
 
 }
 
 
@@ -7286,10 +7365,10 @@ do_mouse_moved (mouse_pos, f)
      Point mouse_pos;
      FRAME_PTR *f;
 {
      Point mouse_pos;
      FRAME_PTR *f;
 {
-  WindowPtr wp = mac_front_window ();
+  WindowPtr wp = front_emacs_window ();
   struct x_display_info *dpyinfo;
 
   struct x_display_info *dpyinfo;
 
-  if (is_emacs_window (wp))
+  if (wp)
     {
       *f = mac_window_to_frame (wp);
       dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
     {
       *f = mac_window_to_frame (wp);
       dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
@@ -7351,7 +7430,7 @@ do_menu_choice (SInt32 menu_choice)
 
     default:
       {
 
     default:
       {
-        struct frame *f = mac_window_to_frame (mac_front_window ());
+        struct frame *f = mac_window_to_frame (front_emacs_window ());
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
@@ -7404,41 +7483,43 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   GrafPtr save_port;
   Rect zoom_rect, port_rect;
   Point top_left;
   GrafPtr save_port;
   Rect zoom_rect, port_rect;
   Point top_left;
-  int w_title_height, columns, rows, width, height, dummy, x, y;
+  int w_title_height, columns, rows;
   struct frame *f = mac_window_to_frame (w);
 
   struct frame *f = mac_window_to_frame (w);
 
-  GetPort (&save_port);
-
-  SetPortWindowPort (w);
-
-  /* Clear window to avoid flicker.  */
 #if TARGET_API_MAC_CARBON
   {
 #if TARGET_API_MAC_CARBON
   {
-    Rect r;
-    BitMap bm;
+    Point standard_size;
 
 
-    GetWindowPortBounds (w, &r);
-    EraseRect (&r);
+    standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
+    standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
 
 
-    if (zoom_in_or_out == inZoomOut)
+    if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
+      zoom_in_or_out = inZoomIn;
+    else
       {
       {
-        /* calculate height of window's title bar (hard card it for now).  */
-        w_title_height = 20 + GetMBarHeight ();
-
-        /* get maximum height of window into zoom_rect.bottom -
-          zoom_rect.top */
-        GetQDGlobalsScreenBits (&bm);
-        zoom_rect = bm.bounds;
-        zoom_rect.top += w_title_height;
-        InsetRect (&zoom_rect, 8, 4);  /* not too tight */
-
-        zoom_rect.right = zoom_rect.left
-         + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-
-        SetWindowStandardState (w, &zoom_rect);
+       /* Adjust the standard size according to character boundaries.  */
+
+       columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
+       rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+       standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
+       standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+       GetWindowBounds (w, kWindowContentRgn, &port_rect);
+       if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
+           && port_rect.left == zoom_rect.left
+           && port_rect.top == zoom_rect.top)
+         zoom_in_or_out = inZoomIn;
+       else
+         zoom_in_or_out = inZoomOut;
       }
       }
+
+    ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
   }
 #else /* not TARGET_API_MAC_CARBON */
   }
 #else /* not TARGET_API_MAC_CARBON */
+  GetPort (&save_port);
+
+  SetPortWindowPort (w);
+
+  /* Clear window to avoid flicker.  */
   EraseRect (&(w->portRect));
   if (zoom_in_or_out == inZoomOut)
     {
   EraseRect (&(w->portRect));
   if (zoom_in_or_out == inZoomOut)
     {
@@ -7457,12 +7538,19 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
       zoom_rect.right = zoom_rect.left
        + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
 
       zoom_rect.right = zoom_rect.left
        + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
 
+      /* Adjust the standard size according to character boundaries.  */
+      rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
+      zoom_rect.bottom =
+       zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+
       (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
        = zoom_rect;
     }
       (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
        = zoom_rect;
     }
-#endif /* not TARGET_API_MAC_CARBON */
 
 
-  ZoomWindow (w, zoom_in_or_out, w == mac_front_window ());
+  ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
+
+  SetPort (save_port);
+#endif /* not TARGET_API_MAC_CARBON */
 
   /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
 
   /* retrieve window size and update application values */
 #if TARGET_API_MAC_CARBON
@@ -7473,8 +7561,7 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
   columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
   x_set_window_size (f, 0, columns, rows);
   rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
   columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
   x_set_window_size (f, 0, columns, rows);
-
-  SetPort (save_port);
+  x_real_positions (f, &f->left_pos, &f->top_pos);
 }
 
 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
 }
 
 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
@@ -8024,19 +8111,15 @@ XTread_socket (sd, expected, hold_quit)
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
-  while (WaitNextEvent (event_mask, &er,
-                       (expected ? app_sleep_time : 0L), NULL))
-#else
-  while (!ReceiveNextEvent (0, NULL,
-                           (expected ? TicksToEventTime (app_sleep_time) : 0),
+  while (WaitNextEvent (event_mask, &er, 0L, NULL))
+#else /* USE_CARBON_EVENTS */
+  while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
                            kEventRemoveFromQueue, &eventRef))
                            kEventRemoveFromQueue, &eventRef))
-#endif /* !USE_CARBON_EVENTS */
+#endif /* USE_CARBON_EVENTS */
     {
       int do_help = 0;
       struct frame *f;
 
     {
       int do_help = 0;
       struct frame *f;
 
-      expected = 0;
-
       /* It is necessary to set this (additional) argument slot of an
         event to nil because keyboard.c protects incompletely
         processed event from being garbage collected by placing them
       /* It is necessary to set this (additional) argument slot of an
         event to nil because keyboard.c protects incompletely
         processed event from being garbage collected by placing them
@@ -8051,7 +8134,7 @@ XTread_socket (sd, expected, hold_quit)
        switch (GetEventClass (eventRef))
          {
          case kEventClassWindow:
        switch (GetEventClass (eventRef))
          {
          case kEventClassWindow:
-           if (GetEventKind (eventRef) == kEventWindowBoundsChanged) 
+           if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
              {
                WindowPtr window_ptr;
                GetEventParameter(eventRef, kEventParamDirectObject,
              {
                WindowPtr window_ptr;
                GetEventParameter(eventRef, kEventParamDirectObject,
@@ -8059,13 +8142,7 @@ XTread_socket (sd, expected, hold_quit)
                                  NULL, &window_ptr);
                f = mac_window_to_frame (window_ptr);
                if (f && !f->async_iconified)
                                  NULL, &window_ptr);
                f = mac_window_to_frame (window_ptr);
                if (f && !f->async_iconified)
-                 {
-                   int x, y;
-                   
-                   x_real_positions (f, &x, &y);
-                   f->left_pos = x;
-                   f->top_pos = y;
-                 }
+                 x_real_positions (f, &f->left_pos, &f->top_pos);
                SendEventToEventTarget (eventRef, toolbox_dispatcher);
              }
            break;
                SendEventToEventTarget (eventRef, toolbox_dispatcher);
              }
            break;
@@ -8074,7 +8151,7 @@ XTread_socket (sd, expected, hold_quit)
              {
                SInt32 delta;
                Point point;
              {
                SInt32 delta;
                Point point;
-               WindowPtr window_ptr = mac_front_window ();
+               WindowPtr window_ptr = front_emacs_window ();
 
                if (!IsValidWindowPtr (window_ptr))
                  {
 
                if (!IsValidWindowPtr (window_ptr))
                  {
@@ -8136,33 +8213,28 @@ XTread_socket (sd, expected, hold_quit)
              }
            else
              {
              }
            else
              {
-               window_ptr = FrontWindow ();
+               part_code = FindWindow (er.where, &window_ptr);
                if (tip_window && window_ptr == tip_window)
                  {
                    HideWindow (tip_window);
                if (tip_window && window_ptr == tip_window)
                  {
                    HideWindow (tip_window);
-                   window_ptr = FrontWindow ();
+                   part_code = FindWindow (er.where, &window_ptr);
                  }
                  }
-
-               if (!is_emacs_window (window_ptr))
-                 break;
-
-               part_code = FindWindow (er.where, &window_ptr);
              }
 
              }
 
+           if (er.what != mouseDown && part_code != inContent)
+             break;
+
            switch (part_code)
              {
              case inMenuBar:
            switch (part_code)
              {
              case inMenuBar:
-               if (er.what == mouseDown)
-                 {
-                   f = mac_window_to_frame (mac_front_window ());
-                   saved_menu_event_location = er.where;
-                   inev.kind = MENU_BAR_ACTIVATE_EVENT;
-                   XSETFRAME (inev.frame_or_window, f);
-                 }
+               f = mac_window_to_frame (front_emacs_window ());
+               saved_menu_event_location = er.where;
+               inev.kind = MENU_BAR_ACTIVATE_EVENT;
+               XSETFRAME (inev.frame_or_window, f);
                break;
 
              case inContent:
                break;
 
              case inContent:
-               if (window_ptr != mac_front_window ())
+               if (window_ptr != front_emacs_window ())
                  SelectWindow (window_ptr);
                else
                  {
                  SelectWindow (window_ptr);
                else
                  {
@@ -8259,7 +8331,7 @@ XTread_socket (sd, expected, hold_quit)
                      }
                    else
                      {
                      }
                    else
                      {
-                       if (dpyinfo->grabbed & (1 << inev.code) == 0)
+                       if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
                          /* If a button is released though it was not
                             previously pressed, that would be because
                             of multi-button emulation.  */
                          /* If a button is released though it was not
                             previously pressed, that would be because
                             of multi-button emulation.  */
@@ -8282,27 +8354,16 @@ XTread_socket (sd, expected, hold_quit)
 
              case inDrag:
 #if TARGET_API_MAC_CARBON
 
              case inDrag:
 #if TARGET_API_MAC_CARBON
-               if (er.what == mouseDown)
-                 {
-                   BitMap bm;
-
-                   GetQDGlobalsScreenBits (&bm);
-                   DragWindow (window_ptr, er.where, &bm.bounds);
-                 }
+               DragWindow (window_ptr, er.where, NULL);
 #else /* not TARGET_API_MAC_CARBON */
                DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
 #endif /* not TARGET_API_MAC_CARBON */
                /* Update the frame parameters.  */
                {
                  struct frame *f = mac_window_to_frame (window_ptr);
 #else /* not TARGET_API_MAC_CARBON */
                DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
 #endif /* not TARGET_API_MAC_CARBON */
                /* Update the frame parameters.  */
                {
                  struct frame *f = mac_window_to_frame (window_ptr);
+
                  if (f && !f->async_iconified)
                  if (f && !f->async_iconified)
-                   {
-                     int x, y;
-                     
-                     x_real_positions (f, &x, &y);
-                     f->left_pos = x;
-                     f->top_pos = y;
-                   }
+                   x_real_positions (f, &f->left_pos, &f->top_pos);
                }
                break;
 
                }
                break;
 
@@ -8317,11 +8378,8 @@ XTread_socket (sd, expected, hold_quit)
 
                /* window resize handling added --ben */
              case inGrow:
 
                /* window resize handling added --ben */
              case inGrow:
-               if (er.what == mouseDown)
-                 {
-                   do_grow_window(window_ptr, &er);
-                   break;
-                 }
+               do_grow_window (window_ptr, &er);
+               break;
 
                /* window zoom handling added --ben */
              case inZoomIn:
 
                /* window zoom handling added --ben */
              case inZoomIn:
@@ -8393,7 +8451,7 @@ XTread_socket (sd, expected, hold_quit)
 
            if (!is_emacs_window (window_ptr))
              break;
 
            if (!is_emacs_window (window_ptr))
              break;
-           
+
            f = mac_window_to_frame (window_ptr);
 
            if ((er.modifiers & activeFlag) != 0)
            f = mac_window_to_frame (window_ptr);
 
            if ((er.modifiers & activeFlag) != 0)
@@ -8464,7 +8522,7 @@ XTread_socket (sd, expected, hold_quit)
 #endif
 
 #if TARGET_API_MAC_CARBON
 #endif
 
 #if TARGET_API_MAC_CARBON
-           if (!IsValidWindowPtr (mac_front_window ()))
+           if (!IsValidWindowPtr (front_emacs_window ()))
              {
                SysBeep (1);
                break;
              {
                SysBeep (1);
                break;
@@ -8504,7 +8562,18 @@ XTread_socket (sd, expected, hold_quit)
                    unsigned long some_state = 0;
                    inev.code = KeyTranslate (kchr_ptr, new_keycode,
                                              &some_state) & 0xff;
                    unsigned long some_state = 0;
                    inev.code = KeyTranslate (kchr_ptr, new_keycode,
                                              &some_state) & 0xff;
-                 }
+                 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
+            {
+                /* When using the option key as an emacs modifier, convert
+                   the pressed key code back to one without the Mac option
+                   modifier applied. */
+                int new_modifiers = er.modifiers & ~optionKey;
+                int new_keycode = keycode | new_modifiers;
+                Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+                unsigned long some_state = 0;
+                inev.code = KeyTranslate (kchr_ptr, new_keycode,
+                                          &some_state) & 0xff;
+            }
                else
                  inev.code = er.message & charCodeMask;
                inev.kind = ASCII_KEYSTROKE_EVENT;
                else
                  inev.code = er.message & charCodeMask;
                inev.kind = ASCII_KEYSTROKE_EVENT;
@@ -8568,7 +8637,7 @@ XTread_socket (sd, expected, hold_quit)
          inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
          XSETFRAME (inev.frame_or_window,
          inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
          XSETFRAME (inev.frame_or_window,
-                    mac_window_to_frame (mac_front_window ()));
+                    mac_window_to_frame (front_emacs_window ()));
          inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
          break;
 
          inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
          break;
 
@@ -8585,16 +8654,16 @@ XTread_socket (sd, expected, hold_quit)
              WindowPtr wp;
              Lisp_Object frame;
 
              WindowPtr wp;
              Lisp_Object frame;
 
-             wp = mac_front_window ();
+             wp = front_emacs_window ();
 
              if (!wp)
                {
                  struct frame *f = XFRAME (XCAR (Vframe_list));
                  CollapseWindow (FRAME_MAC_WINDOW (f), false);
 
              if (!wp)
                {
                  struct frame *f = XFRAME (XCAR (Vframe_list));
                  CollapseWindow (FRAME_MAC_WINDOW (f), false);
-                 wp = mac_front_window ();
+                 wp = front_emacs_window ();
                }
 
                }
 
-             if (wp && is_emacs_window (wp))
+             if (wp)
                f = mac_window_to_frame (wp);
 
              inev.kind = DRAG_N_DROP_EVENT;
                f = mac_window_to_frame (wp);
 
              inev.kind = DRAG_N_DROP_EVENT;
@@ -8720,6 +8789,7 @@ make_mac_frame (FRAME_PTR fp)
 
   mwp = fp->output_data.mac;
 
 
   mwp = fp->output_data.mac;
 
+  BLOCK_INPUT;
   if (making_terminal_window)
     {
       if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
   if (making_terminal_window)
     {
       if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
@@ -8747,9 +8817,8 @@ make_mac_frame (FRAME_PTR fp)
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
 
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
 
-  SetPortWindowPort (mwp->mWP);
-
   SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
   SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
+  UNBLOCK_INPUT;
 }
 
 
 }
 
 
@@ -8854,8 +8923,21 @@ mac_initialize_display_info ()
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
 #ifdef MAC_OSX
   /* HasDepth returns true if it is possible to have a 32 bit display,
   dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
 #ifdef MAC_OSX
   /* HasDepth returns true if it is possible to have a 32 bit display,
-     but this may not be what is actually used.  Mac OSX can do better.  */
-  dpyinfo->n_planes = CGDisplayBitsPerPixel (CGMainDisplayID ());
+     but this may not be what is actually used.  Mac OSX can do better.
+     CGMainDisplayID is only available on OSX 10.2 and higher, but the
+     header for CGGetActiveDisplayList says that the first display returned
+     is the active one, so we use that.  */
+  {
+    CGDirectDisplayID disp_id[1];
+    CGDisplayCount disp_count;
+    CGDisplayErr error_code;
+
+    error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
+    if (error_code != 0)
+      error ("No display found, CGGetActiveDisplayList error %d", error_code);
+
+    dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
+  }
 #else
   for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
     if (HasDepth (main_device_handle, dpyinfo->n_planes,
 #else
   for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
     if (HasDepth (main_device_handle, dpyinfo->n_planes,
@@ -9038,7 +9120,7 @@ mac_check_for_quit_char ()
       e.arg = Qnil;
       e.modifiers = NULL;
       e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
       e.arg = Qnil;
       e.modifiers = NULL;
       e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
-      XSETFRAME (e.frame_or_window, mac_window_to_frame (mac_front_window ()));
+      XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
       /* Remove event from queue to prevent looping. */
       RemoveEventFromQueue (GetMainEventQueue (), event);
       ReleaseEvent (event);
       /* Remove event from queue to prevent looping. */
       RemoveEventFromQueue (GetMainEventQueue (), event);
       ReleaseEvent (event);
@@ -9159,6 +9241,7 @@ mac_initialize ()
   signal (SIGPIPE, x_connection_signal);
 #endif
 
   signal (SIGPIPE, x_connection_signal);
 #endif
 
+  BLOCK_INPUT;
   mac_initialize_display_info ();
 
 #if TARGET_API_MAC_CARBON
   mac_initialize_display_info ();
 
 #if TARGET_API_MAC_CARBON
@@ -9177,6 +9260,7 @@ mac_initialize ()
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
   if (!inhibit_window_system)
     MakeMeTheFrontProcess ();
 #endif
+  UNBLOCK_INPUT;
 }
 
 
 }
 
 
@@ -9188,6 +9272,14 @@ syms_of_macterm ()
   x_error_message_string = Qnil;
 #endif
 
   x_error_message_string = Qnil;
 #endif
 
+  Qmodifier_value = intern ("modifier-value");
+  Qalt = intern ("alt");
+  Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
+  Qhyper = intern ("hyper");
+  Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
+  Qsuper = intern ("super");
+  Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
+
   Fprovide (intern ("mac-carbon"), Qnil);
 
   staticpro (&Qreverse);
   Fprovide (intern ("mac-carbon"), Qnil);
 
   staticpro (&Qreverse);
@@ -9244,6 +9336,12 @@ to 4.1, set this to nil.  */);
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
+    doc: /* Modifier to use for the Mac alt/option key.  The value can
+be alt, hyper, or super for the respective modifier.  If the value is
+nil then the key will act as the normal Mac option modifier.  */);
+  Vmac_option_modifier = Qnil;
+
   DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
     doc: /* Non-nil means that the control and meta keys are reversed.  This is
            useful for non-standard keyboard layouts.  */);
   DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
     doc: /* Non-nil means that the control and meta keys are reversed.  This is
            useful for non-standard keyboard layouts.  */);