changeset 61574:d3c53b9d1828

(x_autoselect_window_p): Remove variable. (last_window): New variable. (XTreassert_line_highlight, x_change_line_highlight): Remove declarations. (mac_focus_changed, x_detect_focus_change): New functions and declarations. (XTextExtents16, front_emacs_window): Remove function. (mac_focus_frame): New function. (XTmouse_position, do_menu_choice, do_zoom_window, XTread_socket) (mac_check_for_quit_char): Use it instead of front_emacs_window. (x_scroll_bar_report_motion): Obtain window from control owner. (x_make_frame_invisible): Set window manager size hint. (do_mouse_moved): Remove function. (XTread_socket): Move its contents here. Generate select-window event on mouse movement if needed. Use x_detect_focus_change on activate/deactivate events. Don't deiconify frame or invalidate window rectangle when dnd items are dropped. Don't activate/deactivate root control. (frame_highlight, frame_unhighlight): Activate/deactivate root control here. (syms_of_macterm): Delete DEFVAR_BOOL for x_autoselect_window_p.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Sat, 16 Apr 2005 03:05:15 +0000
parents 5b0b486b7f71
children 999aacd9ac84
files src/macterm.c
diffstat 1 files changed, 211 insertions(+), 162 deletions(-) [+]
line wrap: on
line diff
--- a/src/macterm.c	Sat Apr 16 03:04:13 2005 +0000
+++ b/src/macterm.c	Sat Apr 16 03:05:15 2005 +0000
@@ -95,6 +95,7 @@
 			: controlKey)
 #define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
 
+#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
 
 
 /* Non-nil means Emacs uses toolkit scroll bars.  */
@@ -110,9 +111,8 @@
 
 static int any_help_event_p;
 
-/* Non-zero means autoselect window with the mouse cursor.  */
-
-int x_autoselect_window_p;
+/* Last window where we saw the mouse.  Used by mouse-autoselect-window.  */
+static Lisp_Object last_window;
 
 /* Non-zero means make use of UNDERLINE_POSITION font properties.  */
 
@@ -273,14 +273,16 @@
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void XTframe_up_to_date P_ ((struct frame *));
-static void XTreassert_line_highlight P_ ((int, int));
-static void x_change_line_highlight P_ ((int, int, int, int));
 static void XTset_terminal_modes P_ ((void));
 static void XTreset_terminal_modes P_ ((void));
 static void x_clear_frame P_ ((void));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
+static void mac_focus_changed P_ ((int, struct mac_display_info *,
+				   struct frame *, struct input_event *));
+static void x_detect_focus_change P_ ((struct mac_display_info *,
+				       EventRecord *, struct input_event *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
@@ -1198,15 +1200,6 @@
 }
 
 
-static void
-XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
-                     int *direction,int *font_ascent,
-                     int *font_descent, XCharStruct *cs)
-{
-  /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
-}
-
-
 /* x_sync is a no-op on Mac.  */
 void
 x_sync (f)
@@ -3494,6 +3487,14 @@
 frame_highlight (f)
      struct frame *f;
 {
+  OSErr err;
+  ControlRef root_control;
+
+  BLOCK_INPUT;
+  err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
+  if (err == noErr)
+    ActivateControl (root_control);
+  UNBLOCK_INPUT;
   x_update_cursor (f, 1);
 }
 
@@ -3501,6 +3502,14 @@
 frame_unhighlight (f)
      struct frame *f;
 {
+  OSErr err;
+  ControlRef root_control;
+
+  BLOCK_INPUT;
+  err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control);
+  if (err == noErr)
+    DeactivateControl (root_control);
+  UNBLOCK_INPUT;
   x_update_cursor (f, 1);
 }
 
@@ -3543,6 +3552,68 @@
   x_frame_rehighlight (dpyinfo);
 }
 
+/* Handle FocusIn and FocusOut state changes for FRAME.
+   If FRAME has focus and there exists more than one frame, puts
+   a FOCUS_IN_EVENT into *BUFP.  */
+
+static void
+mac_focus_changed (type, dpyinfo, frame, bufp)
+     int type;
+     struct mac_display_info *dpyinfo;
+     struct frame *frame;
+     struct input_event *bufp;
+{
+  if (type == activeFlag)
+    {
+      if (dpyinfo->x_focus_event_frame != frame)
+        {
+          x_new_focus_frame (dpyinfo, frame);
+          dpyinfo->x_focus_event_frame = frame;
+
+          /* Don't stop displaying the initial startup message
+             for a switch-frame event we don't need.  */
+          if (GC_NILP (Vterminal_frame)
+              && GC_CONSP (Vframe_list)
+              && !GC_NILP (XCDR (Vframe_list)))
+            {
+              bufp->kind = FOCUS_IN_EVENT;
+              XSETFRAME (bufp->frame_or_window, frame);
+            }
+        }
+    }
+  else
+    {
+      if (dpyinfo->x_focus_event_frame == frame)
+        {
+          dpyinfo->x_focus_event_frame = 0;
+          x_new_focus_frame (dpyinfo, 0);
+        }
+    }
+}
+
+/* The focus may have changed.  Figure out if it is a real focus change,
+   by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+   Returns FOCUS_IN_EVENT event in *BUFP. */
+
+static void
+x_detect_focus_change (dpyinfo, event, bufp)
+     struct mac_display_info *dpyinfo;
+     EventRecord *event;
+     struct input_event *bufp;
+{
+  struct frame *frame;
+
+  frame = mac_window_to_frame ((WindowPtr) event->message);
+  if (! frame)
+    return;
+
+  /* On Mac, this is only called from focus events, so no switch needed.  */
+  mac_focus_changed ((event->modifiers & activeFlag),
+		     dpyinfo, frame, bufp);
+}
+
+
 /* Handle an event saying the mouse has moved out of an Emacs frame.  */
 
 void
@@ -3980,25 +4051,19 @@
 }
 
 
-static WindowPtr
-front_emacs_window ()
-{
-#if TARGET_API_MAC_CARBON
-  WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
-
-  while (wp && !is_emacs_window (wp))
-    wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
-#else
-  WindowPtr wp = FrontWindow ();
-
-  while (wp && (wp == tip_window || !is_emacs_window (wp)))
-    wp = GetNextWindow (wp);
-#endif
-
-  return wp;
-}
-
-#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
+static struct frame *
+mac_focus_frame (dpyinfo)
+     struct mac_display_info *dpyinfo;
+{
+  if (dpyinfo->x_focus_frame)
+    return dpyinfo->x_focus_frame;
+  else
+    /* Mac version may get events, such as a menu bar click, even when
+       all the frames are invisible.  In this case, we regard the
+       event came to the selected frame.  */
+    return SELECTED_FRAME ();
+}
+
 
 /* Return the current position of the mouse.
    *fp should be a frame which indicates which display to ask about.
@@ -4031,13 +4096,10 @@
 {
   Point mouse_pos;
   int ignore1, ignore2;
-  WindowPtr wp = front_emacs_window ();
-  struct frame *f;
+  struct frame *f = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
+  WindowPtr wp = FRAME_MAC_WINDOW (f);
   Lisp_Object frame, tail;
 
-  if (is_emacs_window(wp))
-    f = mac_window_to_frame (wp);
-
   BLOCK_INPUT;
 
   if (! NILP (last_mouse_scroll_bar) && insist == 0)
@@ -4604,7 +4666,12 @@
      unsigned long *time;
 {
   struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
-  WindowPtr wp = front_emacs_window ();
+  ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
+#if TARGET_API_MAC_CARBON
+  WindowPtr wp = GetControlOwner (ch);
+#else
+  WindowPtr wp = (*ch)->contrlOwner;
+#endif
   Point mouse_pos;
   struct frame *f = mac_window_to_frame (wp);
   int win_y, top_range;
@@ -5050,7 +5117,7 @@
     return Qnil;
 
   /* Since x_new_font doesn't update any fontset information, do it now.  */
-  FRAME_FONTSET(f) = fontset;
+  FRAME_FONTSET (f) = fontset;
 
   return build_string (fontsetname);
 }
@@ -5498,6 +5565,13 @@
 
   BLOCK_INPUT;
 
+  /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
+     that the current position of the window is user-specified, rather than
+     program-specified, so that when the window is mapped again, it will be
+     placed at the same location, without forcing the user to position it
+     by hand again (they have already done that once for this window.)  */
+  x_wm_set_size_hint (f, (long) 0, 1);
+
   HideWindow (FRAME_MAC_WINDOW (f));
 
   /* We can't distinguish this from iconification
@@ -7454,21 +7528,6 @@
 {
   /* Window-activate events will do the job. */
 #if 0
-  WindowPtr wp;
-  struct frame *f;
-
-  wp = front_emacs_window ();
-  if (wp)
-    {
-      f = mac_window_to_frame (wp);
-
-      if (f)
-	{
-	  x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
-	  activate_scroll_bars (f);
-	}
-    }
-
   app_is_suspended = false;
   app_sleep_time = WNE_SLEEP_AT_RESUME;
 #endif
@@ -7479,21 +7538,6 @@
 {
   /* Window-deactivate events will do the job. */
 #if 0
-  WindowPtr wp;
-  struct frame *f;
-
-  wp = front_emacs_window ();
-  if (wp)
-    {
-      f = mac_window_to_frame (wp);
-
-      if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
-	{
-	  x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
-	  deactivate_scroll_bars (f);
-	}
-    }
-
   app_is_suspended = true;
   app_sleep_time = WNE_SLEEP_AT_SUSPEND;
 #endif
@@ -7501,40 +7545,6 @@
 
 
 static void
-do_mouse_moved (mouse_pos, f)
-     Point mouse_pos;
-     FRAME_PTR *f;
-{
-  WindowPtr wp = front_emacs_window ();
-  struct x_display_info *dpyinfo;
-
-  if (wp)
-    {
-      *f = mac_window_to_frame (wp);
-      dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
-
-      if (dpyinfo->mouse_face_hidden)
-	{
-	  dpyinfo->mouse_face_hidden = 0;
-	  clear_mouse_face (dpyinfo);
-	}
-
-      SetPortWindowPort (wp);
-
-      GlobalToLocal (&mouse_pos);
-
-      if (dpyinfo->grabbed && tracked_scroll_bar)
-	x_scroll_bar_note_movement (tracked_scroll_bar,
-				    mouse_pos.v
-				    - XINT (tracked_scroll_bar->top),
-				    TickCount() * (1000 / 60));
-      else
-	note_mouse_movement (*f, &mouse_pos);
-    }
-}
-
-
-static void
 do_apple_menu (SInt16 menu_item)
 {
 #if !TARGET_API_MAC_CARBON
@@ -7570,7 +7580,7 @@
 
     default:
       {
-        struct frame *f = mac_window_to_frame (front_emacs_window ());
+        struct frame *f = mac_focus_frame (&one_mac_display_info);
         MenuHandle menu = GetMenuHandle (menu_id);
         if (menu)
           {
@@ -7648,13 +7658,14 @@
   Point top_left;
   int w_title_height, columns, rows, width, height;
   struct frame *f = mac_window_to_frame (w);
+  struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
 
 #if TARGET_API_MAC_CARBON
   {
     Point standard_size;
 
     standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
-    standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
+    standard_size.v = dpyinfo->height;
 
     if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
       zoom_in_or_out = inZoomIn;
@@ -7710,7 +7721,7 @@
 	= zoom_rect;
     }
 
-  ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
+  ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo));
 
   SetPort (save_port);
 #endif /* not TARGET_API_MAC_CARBON */
@@ -8576,10 +8587,13 @@
 	      {
 		SInt32 delta;
 		Point point;
-		WindowPtr window_ptr = front_emacs_window ();
-
-		if (!IsValidWindowPtr (window_ptr))
+		struct frame *f = mac_focus_frame (dpyinfo);
+		WindowPtr window_ptr;
+
+		if (!f)
 		  {
+		    /* Beep if wheel move occurs when all the frames
+		       are invisible.  */
 		    SysBeep(1);
 		    break;
 		  }
@@ -8595,6 +8609,7 @@
 		inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
 				  | ((delta < 0) ? down_modifier
 				     : up_modifier));
+		window_ptr = FRAME_MAC_WINDOW (f);
 		SetPortWindowPort (window_ptr);
 		GlobalToLocal (&point);
 		XSETINT (inev.x, point.h);
@@ -8653,14 +8668,14 @@
 	    switch (part_code)
 	      {
 	      case inMenuBar:
-		f = mac_window_to_frame (front_emacs_window ());
+		f = mac_focus_frame (dpyinfo);
 		saved_menu_event_location = er.where;
 		inev.kind = MENU_BAR_ACTIVATE_EVENT;
 		XSETFRAME (inev.frame_or_window, f);
 		break;
 
 	      case inContent:
-		if (window_ptr != front_emacs_window ())
+		if (window_ptr != FRAME_MAC_WINDOW (mac_focus_frame (dpyinfo)))
 		  SelectWindow (window_ptr);
 		else
 		  {
@@ -8851,7 +8866,61 @@
 	      help_echo_string = help_echo_object = help_echo_window = Qnil;
 	      help_echo_pos = -1;
 
-	      do_mouse_moved (er.where, &f);
+	      if (dpyinfo->grabbed && last_mouse_frame
+		  && FRAME_LIVE_P (last_mouse_frame))
+		f = last_mouse_frame;
+	      else
+		f = dpyinfo->x_focus_frame;
+
+	      if (dpyinfo->mouse_face_hidden)
+		{
+		  dpyinfo->mouse_face_hidden = 0;
+		  clear_mouse_face (dpyinfo);
+		}
+
+	      if (f)
+		{
+		  WindowPtr wp = FRAME_MAC_WINDOW (f);
+		  Point mouse_pos = er.where;
+
+		  SetPortWindowPort (wp);
+
+		  GlobalToLocal (&mouse_pos);
+
+		  if (dpyinfo->grabbed && tracked_scroll_bar)
+		    x_scroll_bar_note_movement (tracked_scroll_bar,
+						mouse_pos.v
+						- XINT (tracked_scroll_bar->top),
+						TickCount() * (1000 / 60));
+		  else
+		    {
+		      /* Generate SELECT_WINDOW_EVENTs when needed.  */
+		      if (mouse_autoselect_window)
+			{
+			  Lisp_Object window;
+
+			  window = window_from_coordinates (f,
+							    mouse_pos.h,
+							    mouse_pos.v,
+							    0, 0, 0, 0);
+
+			  /* Window will be selected only when it is
+			     not selected now and last mouse movement
+			     event was not in it.  Minibuffer window
+			     will be selected iff it is active.  */
+			  if (WINDOWP (window)
+			      && !EQ (window, last_window)
+			      && !EQ (window, selected_window))
+			    {
+			      inev.kind = SELECT_WINDOW_EVENT;
+			      inev.frame_or_window = window;
+			    }
+
+			  last_window=window;
+			}
+		      note_mouse_movement (f, &mouse_pos);
+		    }
+		}
 
 	      /* If the contents of the global variable
 		 help_echo_string has changed, generate a
@@ -8865,7 +8934,6 @@
 	case activateEvt:
 	  {
 	    WindowPtr window_ptr = (WindowPtr) er.message;
-	    ControlRef root_control;
 
 #if USE_CARBON_EVENTS
 	    if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
@@ -8881,16 +8949,12 @@
 	    if (!is_emacs_window (window_ptr))
 	      break;
 
-	    f = mac_window_to_frame (window_ptr);
-	    GetRootControl (window_ptr, &root_control);
-
 	    if ((er.modifiers & activeFlag) != 0)
 	      {
 		/* A window has been activated */
 		Point mouse_loc = er.where;
 
-		x_new_focus_frame (dpyinfo, f);
-		ActivateControl (root_control);
+		x_detect_focus_change (dpyinfo, &er, &inev);
 
 		SetPortWindowPort (window_ptr);
 		GlobalToLocal (&mouse_loc);
@@ -8904,13 +8968,9 @@
 		/* A window has been deactivated */
 		dpyinfo->grabbed = 0;
 
-		if (f == dpyinfo->x_focus_frame)
-		  {
-		    x_new_focus_frame (dpyinfo, 0);
-		    DeactivateControl (root_control);
-		  }
-
-
+		x_detect_focus_change (dpyinfo, &er, &inev);
+
+		f = mac_window_to_frame (window_ptr);
 		if (f == dpyinfo->mouse_face_mouse_frame)
 		  {
 		    /* If we move outside the frame, then we're
@@ -8951,13 +9011,14 @@
 		break;
 #endif
 
-#if TARGET_API_MAC_CARBON
-	    if (!IsValidWindowPtr (front_emacs_window ()))
+	    if (dpyinfo->x_focus_frame == NULL)
 	      {
+		/* Beep if keyboard input occurs when all the frames
+		   are invisible.  */
 		SysBeep (1);
 		break;
 	      }
-#endif
+
 	    {
 	      static SInt16 last_key_script = -1;
 	      SInt16 current_key_script = GetScriptManagerVariable (smKeyScript);
@@ -8965,7 +9026,7 @@
 	      if (last_key_script != current_key_script)
 		{
 		  struct input_event event;
-		  
+
 		  EVENT_INIT (event);
 		  event.kind = LANGUAGE_CHANGE_EVENT;
 		  event.arg = Qnil;
@@ -9009,18 +9070,20 @@
 		    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 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;
@@ -9032,8 +9095,7 @@
 #else
 	  inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
-	  XSETFRAME (inev.frame_or_window,
-		     mac_window_to_frame (front_emacs_window ()));
+	  XSETFRAME (inev.frame_or_window, mac_focus_frame (dpyinfo));
 	  inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
 	  break;
 
@@ -9046,22 +9108,10 @@
 	     constuct_drag_n_drop in w32term.c.  */
 	  if (!NILP (drag_and_drop_file_list))
 	    {
-	      struct frame *f = NULL;
+	      struct frame *f = mac_focus_frame (dpyinfo);
 	      WindowPtr wp;
 	      Lisp_Object frame;
 
-	      wp = front_emacs_window ();
-
-	      if (!wp)
-		{
-		  struct frame *f = XFRAME (XCAR (Vframe_list));
-		  CollapseWindow (FRAME_MAC_WINDOW (f), false);
-		  wp = front_emacs_window ();
-		}
-
-	      if (wp)
-		f = mac_window_to_frame (wp);
-
 	      inev.kind = DRAG_N_DROP_EVENT;
 	      inev.code = 0;
 	      inev.timestamp = er.when * (1000 / 60);
@@ -9078,10 +9128,12 @@
 	      XSETFRAME (frame, f);
 	      inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
 
+#if 0
 	      /* Regardless of whether Emacs was suspended or in the
 		 foreground, ask it to redraw its entire screen.
 		 Otherwise parts of the screen can be left in an
 		 inconsistent state.  */
+	      wp = FRAME_MAC_WINDOW (f);
 	      if (wp)
 #if TARGET_API_MAC_CARBON
 		{
@@ -9093,6 +9145,7 @@
 #else /* not TARGET_API_MAC_CARBON */
                 InvalRect (&(wp->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
+#endif
 	    }
 	default:
 	  break;
@@ -9572,7 +9625,7 @@
       e.arg = Qnil;
       e.modifiers = NULL;
       e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
-      XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
+      XSETFRAME (e.frame_or_window, mac_focus_frame (&one_mac_display_info));
       /* Remove event from queue to prevent looping. */
       RemoveEventFromQueue (GetMainEventQueue (), event);
       ReleaseEvent (event);
@@ -9765,10 +9818,6 @@
   Qeuc_kr = intern ("euc-kr");
   staticpro (&Qeuc_kr);
 
-  DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
-    doc: /* *Non-nil means autoselect window with mouse pointer.  */);
-  x_autoselect_window_p = 0;
-
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
 	       doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
   Vx_toolkit_scroll_bars = Qt;