changeset 81560:3ce0ebdd2017

(mac_dialog_modal_filter, Fx_popup_dialog) [MAC_OSX]: Put special treatment for Fmessage_box, Fyes_or_no_p, and Fy_or_n_p in #if 0 as it is not compatible with y-or-n-p-with-timeout. (timer_check) [TARGET_API_MAC_CARBON]: Add extern. [TARGET_API_MAC_CARBON] (mac_handle_dialog_event): Use QuitEventLoop instead of QuitAppModalLoopForWindow. Consolidate QuitEventLoop calls. (pop_down_dialog) [TARGET_API_MAC_CARBON]: New function. [TARGET_API_MAC_CARBON] (create_and_show_dialog): Use it for unwind. Run timers during dialog popup. (Fmenu_or_popup_active_p) [TARGET_API_MAC_CARBON]: Use popup_activated.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Fri, 22 Jun 2007 09:05:35 +0000
parents 0e17f76d05e4
children 1ff1ce0627d8
files src/macmenu.c
diffstat 1 files changed, 92 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/macmenu.c	Fri Jun 22 09:05:25 2007 +0000
+++ b/src/macmenu.c	Fri Jun 22 09:05:35 2007 +0000
@@ -882,7 +882,7 @@
 
 /* Regard ESC and C-g as Cancel even without the Cancel button.  */
 
-#ifdef MAC_OSX
+#if 0 /* defined (MAC_OSX) */
 static Boolean
 mac_dialog_modal_filter (dialog, event, item_hit)
      DialogRef dialog;
@@ -991,7 +991,7 @@
        but I don't want to make one now.  */
     CHECK_WINDOW (window);
 
-#ifdef MAC_OSX
+#if 0 /* defined (MAC_OSX) */
   /* Special treatment for Fmessage_box, Fyes_or_no_p, and Fy_or_n_p.  */
   if (EQ (position, Qt)
       && STRINGP (Fcar (contents))
@@ -2330,14 +2330,17 @@
 #define DIALOG_BUTTON_MAKE_COMMAND_ID(value)	\
   ((value) + DIALOG_BUTTON_COMMAND_ID_OFFSET)
 
+extern EMACS_TIME timer_check P_ ((int));
+
 static pascal OSStatus
 mac_handle_dialog_event (next_handler, event, data)
      EventHandlerCallRef next_handler;
      EventRef event;
      void *data;
 {
-  OSStatus err;
+  OSStatus err, result = eventNotHandledErr;
   WindowRef window = (WindowRef) data;
+  int quit_event_loop_p = 0;
 
   switch (GetEventClass (event))
     {
@@ -2352,12 +2355,11 @@
 	  if (DIALOG_BUTTON_COMMAND_ID_P (command.commandID))
 	    {
 	      SetWRefCon (window, command.commandID);
-	      err = QuitAppModalLoopForWindow (window);
-
-	      return err == noErr ? noErr : eventNotHandledErr;
+	      quit_event_loop_p = 1;
+	      break;
 	    }
 
-	return CallNextEventHandler (next_handler, event);
+	result = CallNextEventHandler (next_handler, event);
       }
       break;
 
@@ -2367,8 +2369,8 @@
 	char char_code;
 
 	result = CallNextEventHandler (next_handler, event);
-	if (result == noErr)
-	  return noErr;
+	if (result != eventNotHandledErr)
+	  break;
 
 	err = GetEventParameter (event, kEventParamKeyMacCharCodes,
 				 typeChar, NULL, sizeof (char),
@@ -2377,7 +2379,7 @@
 	  switch (char_code)
 	    {
 	    case kEscapeCharCode:
-	      err = QuitAppModalLoopForWindow (window);
+	      quit_event_loop_p = 1;
 	      break;
 
 	    default:
@@ -2392,26 +2394,26 @@
 					   typeUInt32, NULL, sizeof (UInt32),
 					   NULL, &key_code);
 		if (err == noErr)
-		  {
-		    if (mac_quit_char_key_p (modifiers, key_code))
-		      err = QuitAppModalLoopForWindow (window);
-		    else
-		      err = eventNotHandledErr;
-		  }
+		  if (mac_quit_char_key_p (modifiers, key_code))
+		    quit_event_loop_p = 1;
 	      }
 	      break;
 	    }
-
-	if (err == noErr)
-	  result = noErr;
-
-	return result;
       }
       break;
 
     default:
       abort ();
     }
+
+  if (quit_event_loop_p)
+    {
+      err = QuitEventLoop (GetCurrentEventLoop ());
+      if (err == noErr)
+	result = noErr;
+    }
+
+  return result;
 }
 
 static OSStatus
@@ -2446,6 +2448,25 @@
 #define DIALOG_ICON_LEFT_MARGIN (24)
 #define DIALOG_ICON_TOP_MARGIN (15)
 
+static Lisp_Object
+pop_down_dialog (arg)
+     Lisp_Object arg;
+{
+  struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+  WindowRef window = p->pointer;
+
+  BLOCK_INPUT;
+
+  if (popup_activated_flag)
+    EndAppModalStateForWindow (window);
+  DisposeWindow (window);
+  popup_activated_flag = 0;
+
+  UNBLOCK_INPUT;
+
+  return Qnil;
+}
+
 static int
 create_and_show_dialog (f, first_wv)
      FRAME_PTR f;
@@ -2459,6 +2480,7 @@
   Rect empty_rect, *rects;
   WindowRef window = NULL;
   ControlRef *buttons, default_button = NULL, text;
+  int specpdl_count = SPECPDL_INDEX ();
 
   dialog_name = first_wv->name;
   nb_buttons = dialog_name[1] - '0';
@@ -2475,8 +2497,11 @@
 			 kWindowStandardHandlerAttribute,
 			 &empty_rect, &window);
   if (err == noErr)
-    err = SetThemeWindowBackground (window, kThemeBrushMovableModalBackground,
-				    true);
+    {
+      record_unwind_protect (pop_down_dialog, make_save_value (window, 0));
+      err = SetThemeWindowBackground (window, kThemeBrushMovableModalBackground,
+				      true);
+    }
   if (err == noErr)
     err = SetWindowTitleWithCFString (window, (dialog_name[0] == 'Q'
 					       ? CFSTR ("Question")
@@ -2701,7 +2726,45 @@
       SetWRefCon (window, 0);
       ShowWindow (window);
       BringToFront (window);
-      err = RunAppModalLoopForWindow (window);
+      popup_activated_flag = 1;
+      err = BeginAppModalStateForWindow (window);
+    }
+  if (err == noErr)
+    {
+      EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget ();
+
+      while (1)
+	{
+	  EMACS_TIME next_time = timer_check (1);
+	  long secs = EMACS_SECS (next_time);
+	  long usecs = EMACS_USECS (next_time);
+	  EventTimeout timeout;
+	  EventRef event;
+
+	  if (secs < 0 || (secs == 0 && usecs == 0))
+	    {
+	      /* Sometimes timer_check returns -1 (no timers) even if
+		 there are timers.  So do a timeout anyway.  */
+	      secs = 1;
+	      usecs = 0;
+	    }
+
+	  timeout = (secs * kEventDurationSecond
+		     + usecs * kEventDurationMicrosecond);
+	  err = ReceiveNextEvent (0, NULL, timeout, kEventRemoveFromQueue,
+				  &event);
+	  if (err == noErr)
+	    {
+	      SendEventToEventTarget (event, toolbox_dispatcher);
+	      ReleaseEvent (event);
+	    }
+	  else if (err != eventLoopTimedOutErr)
+	    {
+	      if (err == eventLoopQuitErr)
+		err = noErr;
+	      break;
+	    }
+	}
     }
   if (err == noErr)
     {
@@ -2711,8 +2774,7 @@
 	result = DIALOG_BUTTON_COMMAND_ID_VALUE (command_id);
     }
 
-  if (window)
-    DisposeWindow (window);
+  unbind_to (specpdl_count, Qnil);
 
   return result;
 }
@@ -3282,9 +3344,13 @@
        doc: /* Return t if a menu or popup dialog is active.  */)
      ()
 {
+#if TARGET_API_MAC_CARBON
+  return (popup_activated ()) ? Qt : Qnil;
+#else
   /* Always return Qnil since menu selection functions do not return
      until a selection has been made or cancelled.  */
   return Qnil;
+#endif
 }
 
 void