]> code.delx.au - gnu-emacs/commitdiff
In src:
authorAndrew Choi <akochoi@shaw.ca>
Sat, 3 Aug 2002 22:21:09 +0000 (22:21 +0000)
committerAndrew Choi <akochoi@shaw.ca>
Sat, 3 Aug 2002 22:21:09 +0000 (22:21 +0000)
2002-08-03  Andrew Choi  <akochoi@shaw.ca>

        * macterm.c (USE_CARBON_EVENTS): New macro.
        (macCtrlKey, macShiftKey, macMetaKey, macAltKey): New macros.
        (x_iconify_frame): Call CollapseWindow.
        (Vmac_reverse_ctrl_meta): New variable.
        (Vmac_wheel_button_is_mouse_2): New variable.
        (init_mac_drag_n_drop): New function.
        (mac_do_receive_drag): New function.
        (mac_handle_service_event): New function.
        (init_service_handler): New function.
        (mac_to_emacs_modifiers): New function.
        (mac_event_to_emacs_modifiers): New function.
        (mac_get_mouse_btn): New function.
        (mac_convert_event_ref): New function.
        (XTread_socket) [USE_CARBON_EVENTS]: Call ReceiveNextEvent,
        SendEventToEventTarget, mac_event_to_emacs_modifiers, and
        mac_get_mouse_btn.
        (mac_initialize): Call init_mac_drag_n_drop and
        init_service_handler.

        * keyboard.c: Define Qmouse_wheel, mouse_wheel_syms, and
        lispy_mouse_wheel_names for MAC_OSX as well as for WINDOWS_NT.
        (kbd_buffer_get_event): Set used_mouse_menu for MENU_BAR_EVENT and
        TOOL_BAR_EVENT for MAC_OS as well.
        (make_lispy_event): Handle MOUSE_WHEEL_EVENT for MAC_OSX as well
        as for WINDOWS_NT.
        (syms_of_keyboard): Initialize Qmouse_wheel for MAC_OSX.

        * termhooks.h (event_kind): Define MOUSE_WHEEL_EVENT also for
        MAC_OSX.

In lisp:

2002-08-03  Andrew Choi  <akochoi@shaw.ca>

        * term/mac-win.el: Set keys to enable mouse wheel support.

lisp/ChangeLog
lisp/term/mac-win.el
src/ChangeLog
src/keyboard.c
src/macterm.c
src/termhooks.h

index 27b596e30d29b9135bedf9a9b41eff02ef75d949..58135b43dfa719f81584cd4e9c54b08c2a144aab 100644 (file)
@@ -1,9 +1,13 @@
-2002-08-03  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Andrew Choi  <akochoi@shaw.ca>
+
+       * term/mac-win.el: Set keys to enable mouse wheel support.
+
+2002-08-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
        * net/tramp.el: Version 2.0.8.
        (tramp-perl-encode, tramp-perl-encode): Double the backslashes.
 
-2002-08-03  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
        * net/tramp.el: Version 2.0.7.
        (tramp-perl-encode-with-module, tramp-perl-decode-with-module) 
@@ -17,7 +21,7 @@
        (f90-font-lock-keywords-2): Fix `implicit type(foo)' case.
        (f90-type-def-re): Fix value.
 
-2002-08-03  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
        * net/tramp.el: Version 2.0.6.
        (tramp-default-method): Change to "ssh" from "sm".
        (update-subdirs-CMD): Generate the right list of subdirectories.  From
        Tak Ota <Takaaki.Ota@am.sony.com>.
 
-2002-07-30  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-07-30  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
        * net/tramp.el: New version 2.0.5.
        (tramp-methods): Remove inline encoding method parameters.  The
        * ps-print.el: Update copyright year.
        (ps-begin-cut-regexp, ps-end-cut-regexp): Fix type.
 
-2002-07-26  Kai Gro\e,b_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-07-26  Kai Gro\e,A_\e(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
        * eshell/eshell.el (eshell): Numeric prefix arg means to switch
        to the session with that number.  Old behavior still available
index a9ac12f085e803dda0eb8d33cde79d334146e07d..ef5ce486cef9bf786ccde22c814e17e5a5d2e754 100644 (file)
@@ -234,6 +234,16 @@ ascii:-*-Monaco-*-*-*-*-12-*-*-*-*-*-mac-roman")
 ;; or bold bitmap versions will not display these variants correctly.
 (setq scalable-fonts-allowed t)
 
+;; Make suspend-emacs [C-z] collapse the current frame
+(substitute-key-definition 'suspend-emacs 'iconify-frame
+                          global-map)
+;; Support mouse-wheel scrolling
+(autoload 'mwheel-scroll "mwheel")
+(global-set-key [mouse-wheel] 'mwheel-scroll)
+(global-set-key [C-mouse-wheel] 'mwheel-scroll)
+(global-set-key [S-mouse-wheel] 'mwheel-scroll)
+
 ;; (prefer-coding-system 'mac-roman)
 
 ;;
index 9169ddc7fe447d453e5d4aa94086952b6c4669a1..c69c37ce50467298c43565273fa96302d75621f5 100644 (file)
@@ -1,3 +1,35 @@
+2002-08-03  Andrew Choi  <akochoi@shaw.ca>
+
+       * macterm.c (USE_CARBON_EVENTS): New macro.
+       (macCtrlKey, macShiftKey, macMetaKey, macAltKey): New macros.
+       (x_iconify_frame): Call CollapseWindow.
+       (Vmac_reverse_ctrl_meta): New variable.
+       (Vmac_wheel_button_is_mouse_2): New variable.
+       (init_mac_drag_n_drop): New function.
+       (mac_do_receive_drag): New function.
+       (mac_handle_service_event): New function.
+       (init_service_handler): New function.
+       (mac_to_emacs_modifiers): New function.
+       (mac_event_to_emacs_modifiers): New function.
+       (mac_get_mouse_btn): New function.
+       (mac_convert_event_ref): New function.
+       (XTread_socket) [USE_CARBON_EVENTS]: Call ReceiveNextEvent,
+       SendEventToEventTarget, mac_event_to_emacs_modifiers, and
+       mac_get_mouse_btn.
+       (mac_initialize): Call init_mac_drag_n_drop and
+       init_service_handler.
+
+       * keyboard.c: Define Qmouse_wheel, mouse_wheel_syms, and
+       lispy_mouse_wheel_names for MAC_OSX as well as for WINDOWS_NT.
+       (kbd_buffer_get_event): Set used_mouse_menu for MENU_BAR_EVENT and
+       TOOL_BAR_EVENT for MAC_OS as well.
+       (make_lispy_event): Handle MOUSE_WHEEL_EVENT for MAC_OSX as well
+       as for WINDOWS_NT.
+       (syms_of_keyboard): Initialize Qmouse_wheel for MAC_OSX.
+
+       * termhooks.h (event_kind): Define MOUSE_WHEEL_EVENT also for
+       MAC_OSX.
+       
 2002-08-03  Gerd Moellmann  <gerd.moellmann@t-online.de>
 
        * xdisp.c (forward_to_next_line_start): Fix a condition that
index ce20d57913da718a079762431deb7399800c0c1e..6c45139d80e094c19c773e08b6dd2478fbebc550 100644 (file)
@@ -550,8 +550,10 @@ Lisp_Object Qhelp_echo;
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 Lisp_Object Qmouse_wheel;
+#endif
+#ifdef WINDOWSNT
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
@@ -644,7 +646,7 @@ int flow_control;
 
 /* If we support a window system, turn on the code to poll periodically
    to detect C-g.  It isn't actually used when doing interrupt input.  */
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined(HAVE_WINDOW_SYSTEM) && !defined(USE_ASYNC_EVENTS)
 #define POLL_FOR_INPUT
 #endif
 
@@ -3881,7 +3883,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu)
            {
              obj = make_lispy_event (event);
              
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS)
              /* If this was a menu selection, then set the flag to inhibit
                 writing to last_nonmenu_event.  Don't do this if the event
                 we're returning is (menu-bar), though; that indicates the
@@ -4260,7 +4262,7 @@ timer_check (do_it_now)
 static Lisp_Object accent_key_syms;
 static Lisp_Object func_key_syms;
 static Lisp_Object mouse_syms;
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 static Lisp_Object mouse_wheel_syms;
 #endif
 static Lisp_Object drag_n_drop_syms;
@@ -4669,7 +4671,7 @@ static char *iso_lispy_function_keys[] =
 
 Lisp_Object Vlispy_mouse_stem;
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 /* mouse-wheel events are generated by the wheel on devices such as
    the MS Intellimouse.  The wheel sits in between the left and right
    mouse buttons, and is typically used to scroll or zoom the window
@@ -5279,6 +5281,8 @@ make_lispy_event (event)
                               Qnil));
        }
       }
+#endif /* WINDOWS_NT */
+#if defined(WINDOWS_NT) || defined(MAC_OSX)
     case MOUSE_WHEEL_EVENT:
       {
        int part;
@@ -5350,7 +5354,7 @@ make_lispy_event (event)
                                             Qnil))));
        }
       }
-#endif /* WINDOWSNT */
+#endif /* WINDOWSNT || MAC_OSX */
 
     case DRAG_N_DROP_EVENT:
       {
@@ -10433,9 +10437,11 @@ syms_of_keyboard ()
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   Qmouse_wheel = intern ("mouse-wheel");
   staticpro (&Qmouse_wheel);
+#endif
+#ifdef WINDOWSNT
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
 #endif
@@ -10583,10 +10589,9 @@ syms_of_keyboard ()
   func_key_syms = Qnil;
   staticpro (&func_key_syms);
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   mouse_wheel_syms = Qnil;
   staticpro (&mouse_wheel_syms);
-  
   drag_n_drop_syms = Qnil;
   staticpro (&drag_n_drop_syms);
 #endif
index c471ba4bf35960bd7a673d3edbe65544ee882de4..c00c288001c4412d64682e9c9f8c5d77b952a09f 100644 (file)
@@ -58,6 +58,10 @@ Boston, MA 02111-1307, USA.  */
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #undef init_process
 #define init_process emacs_init_process
+/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
+   obtain events from the event queue.  If set to 0, WaitNextEvent is
+   used instead.  */
+#define USE_CARBON_EVENTS 1
 #else /* not MAC_OSX */
 #include <Quickdraw.h>
 #include <ToolUtils.h>
@@ -106,6 +110,15 @@ Boston, MA 02111-1307, USA.  */
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 
+/* Set of macros that handle mapping of Mac modifier keys to emacs.  */
+#define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :   \
+                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+#define macShiftKey    (shiftKey)
+#define macMetaKey     (NILP (Vmac_reverse_ctrl_meta) ?                        \
+                       (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
+                       : controlKey)
+#define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
+
 \f
 /* Fringe bitmaps.  */
 
@@ -10092,108 +10105,21 @@ void
 x_iconify_frame (f)
      struct frame *f;
 {
-#if 0 /* MAC_TODO: really no iconify on Mac */
-  int result;
-  Lisp_Object type;
-
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
-    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
+  if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
 
+#if 0
+  /* Review:  Since window is still visible in dock, still allow updates? */
   if (f->async_iconified)
     return;
+#endif
 
   BLOCK_INPUT;
 
-  FRAME_SAMPLE_VISIBILITY (f);
-
-  type = x_icon_type (f);
-  if (!NILP (type))
-    x_bitmap_icon (f, type);
-
-#ifdef USE_X_TOOLKIT
-
-  if (! FRAME_VISIBLE_P (f))
-    {
-      if (! EQ (Vx_no_window_manager, Qt))
-       x_wm_set_window_state (f, IconicState);
-      /* This was XtPopup, but that did nothing for an iconified frame.  */
-      XtMapWidget (f->output_data.x->widget);
-      /* The server won't give us any event to indicate
-        that an invisible frame was changed to an icon,
-        so we have to record it here.  */
-      f->iconified = 1;
-      f->visible = 1;
-      f->async_iconified = 1;
-      f->async_visible = 0;
-      UNBLOCK_INPUT;
-      return;
-    }
-
-  result = XIconifyWindow (FRAME_X_DISPLAY (f),
-                          XtWindow (f->output_data.x->widget),
-                          DefaultScreen (FRAME_X_DISPLAY (f)));
-  UNBLOCK_INPUT;
-
-  if (!result)
-    error ("Can't notify window manager of iconification");
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
-
-  BLOCK_INPUT;
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-#else /* not USE_X_TOOLKIT */
-
-  /* Make sure the X server knows where the window should be positioned,
-     in case the user deiconifies with the window manager.  */
-  if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
-  /* Since we don't know which revision of X we're running, we'll use both
-     the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
-
-  /* X11R4: send a ClientMessage to the window manager using the
-     WM_CHANGE_STATE type.  */
-  {
-    XEvent message;
-
-    message.xclient.window = FRAME_X_WINDOW (f);
-    message.xclient.type = ClientMessage;
-    message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
-    message.xclient.format = 32;
-    message.xclient.data.l[0] = IconicState;
-
-    if (! XSendEvent (FRAME_X_DISPLAY (f),
-                     DefaultRootWindow (FRAME_X_DISPLAY (f)),
-                     False,
-                     SubstructureRedirectMask | SubstructureNotifyMask,
-                     &message))
-      {
-       UNBLOCK_INPUT_RESIGNAL;
-       error ("Can't notify window manager of iconification");
-      }
-  }
-
-  /* X11R3: set the initial_state field of the window manager hints to
-     IconicState.  */
-  x_wm_set_window_state (f, IconicState);
-
-  if (!FRAME_VISIBLE_P (f))
-    {
-      /* If the frame was withdrawn, before, we must map it.  */
-      XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-    }
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
-  XFlush (FRAME_X_DISPLAY (f));
+  CollapseWindow (FRAME_MAC_WINDOW (f), true);
+  
   UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
-#endif /* MAC_TODO */
 }
 
 \f
@@ -11560,9 +11486,18 @@ static long app_sleep_time = WNE_SLEEP_AT_RESUME;
 
 Boolean        terminate_flag = false;
 
-/* true if using command key as meta key */
+/* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* True if the ctrl and meta keys should be reversed.  */
+Lisp_Object Vmac_reverse_ctrl_meta;
+
+#if USE_CARBON_EVENTS
+/* True if the mouse wheel button (i.e. button 4) should map to
+   mouse-2, instead of mouse-3.  */
+Lisp_Object Vmac_wheel_button_is_mouse_2;
+#endif
+
 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
    to this text encoding */
 int mac_keyboard_text_encoding;
@@ -11577,13 +11512,23 @@ Lisp_Object drag_and_drop_file_list;
 Point saved_menu_event_location;
 
 /* Apple Events */
-static void init_required_apple_events(void);
+static void init_required_apple_events (void);
 static pascal OSErr
-do_ae_open_application(const AppleEvent *, AppleEvent *, long);
+do_ae_open_application (const AppleEvent *, AppleEvent *, long);
 static pascal OSErr
-do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
+do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+
+/* Drag and Drop */
+static OSErr init_mac_drag_n_drop ();
+static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference); 
+
+#if USE_CARBON_EVENTS
+/* Preliminary Support for the OSX Services Menu */
+static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
+static void init_service_handler ();
+#endif
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
@@ -11592,6 +11537,104 @@ extern void check_alarm ();
 extern void initialize_applescript();
 extern void terminate_applescript();
 
+static unsigned int 
+#if USE_CARBON_EVENTS
+mac_to_emacs_modifiers (UInt32 mods)
+#else
+mac_to_emacs_modifiers (EventModifiers mods)
+#endif
+{
+  unsigned int result = 0;
+  if (mods & macShiftKey)
+    result |= shift_modifier;
+  if (mods & macCtrlKey)
+    result |= ctrl_modifier;
+  if (mods & macMetaKey)
+    result |= meta_modifier;
+  if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
+    result |= alt_modifier;
+  return result;
+}
+
+#if USE_CARBON_EVENTS
+/* Obtains the event modifiers from the event ref and then calls
+   mac_to_emacs_modifiers.  */
+static int 
+mac_event_to_emacs_modifiers (EventRef eventRef) 
+{
+  UInt32 mods = 0;
+  GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
+                   sizeof (UInt32), NULL, &mods);
+  return mac_to_emacs_modifiers (mods);
+}
+
+/* Given an event ref, return the code to use for the mouse button
+   code in the emacs input_event.  */
+static int
+mac_get_mouse_btn (EventRef ref) 
+{
+  EventMouseButton result = kEventMouseButtonPrimary;
+  GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
+                   sizeof (EventMouseButton), NULL, &result);
+  switch (result) 
+    {
+    case kEventMouseButtonPrimary:
+      return 0;
+    case kEventMouseButtonSecondary:
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1; 
+    case kEventMouseButtonTertiary:
+    case 4:  /* 4 is the number for the mouse wheel button */
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2; 
+    default:
+      return 0;
+    }
+}
+
+/* Normally, ConvertEventRefToEventRecord will correctly handle all
+   events.  However the click of the mouse wheel is not converted to a
+   mouseDown or mouseUp event.  This calls ConvertEventRef, but then
+   checks to see if it is a mouse up or down carbon event that has not
+   been converted, and if so, converts it by hand (to be picked up in
+   the XTread_socket loop).  */
+static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) 
+{
+  Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
+  /* Do special case for mouse wheel button.  */
+  if (!result && GetEventClass (eventRef) == kEventClassMouse) 
+    { 
+      UInt32 kind = GetEventKind (eventRef);
+      if (kind == kEventMouseDown && !(eventRec->what == mouseDown)) 
+       {
+         eventRec->what = mouseDown;
+         result=1;
+       }
+      if (kind == kEventMouseUp && !(eventRec->what == mouseUp)) 
+       {
+         eventRec->what = mouseUp;
+         result=1;
+       }
+      if (result) 
+       {
+         /* Need where and when.  */
+         UInt32 mods;
+         GetEventParameter (eventRef, kEventParamMouseLocation,
+                            typeQDPoint, NULL, sizeof (Point),
+                            NULL, &eventRec->where);
+         /* Use two step process because new event modifiers are
+            32-bit and old are 16-bit.  Currently, only loss is
+            NumLock & Fn. */
+         GetEventParameter (eventRef, kEventParamKeyModifiers,
+                            typeUInt32, NULL, sizeof (UInt32),
+                            NULL, &mods);
+         eventRec->modifiers = mods;
+         
+         eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
+       }
+    }
+  return result;
+}
+
+#endif
 
 static void
 do_get_menus (void)
@@ -12019,6 +12062,13 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out)
   SetPort (save_port);
 }
 
+/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
+static OSErr
+init_mac_drag_n_drop ()
+{
+  OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
+  return result;
+}
 
 /* Intialize AppleEvent dispatcher table for the required events.  */
 void
@@ -12092,6 +12142,102 @@ init_required_apple_events ()
     abort ();
 }
 
+#if USE_CARBON_EVENTS
+
+void init_service_handler()
+{
+  EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
+                          {kEventClassService, kEventServiceCopy},
+                          {kEventClassService, kEventServicePaste}};
+  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
+                                 3, specs, NULL, NULL);
+}
+
+/*
+   MAC_TODO: Check to see if this is called by AEProcessDesc...
+ */
+OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
+                                  EventRef event, void *data)
+{
+  OSStatus err = noErr; 
+  switch (GetEventKind (event))
+    {
+    case kEventServiceGetTypes: 
+      {
+       CFMutableArrayRef copyTypes, pasteTypes;
+       CFStringRef type;
+       Boolean selection = true;
+       /*
+         GetEventParameter(event, kEventParamServicePasteTypes,
+         typeCFMutableArrayRef, NULL,
+         sizeof (CFMutableArrayRef), NULL, &pasteTypes);
+       */
+       GetEventParameter(event, kEventParamServiceCopyTypes,
+                         typeCFMutableArrayRef, NULL,
+                         sizeof (CFMutableArrayRef), NULL, &copyTypes);
+       type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
+       if (type) {
+         CFArrayAppendValue (copyTypes, type);
+         //CFArrayAppendValue (pasteTypes, type);
+         CFRelease (type);
+       }
+      }
+    case kEventServiceCopy:
+      {
+       ScrapRef currentScrap, specificScrap;
+       char * buf = "";
+       Size byteCount = 0;
+
+       GetCurrentScrap (&currentScrap);
+
+       err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
+       if (err == noErr)
+         {
+           void *buffer = xmalloc (byteCount);
+           if (buffer != NULL)
+             {
+               GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
+                                  sizeof (ScrapRef), NULL, &specificScrap);
+             
+               err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
+                                         &byteCount, buffer);
+               if (err == noErr)
+                 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
+                                 kScrapFlavorMaskNone, byteCount, buffer);
+               xfree (buffer);
+             } 
+         }
+       err = noErr;
+      }
+    case kEventServicePaste:
+      {
+       /*
+       // Get the current location
+        Size     byteCount;
+        ScrapRef specificScrap;
+        GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
+                         sizeof(ScrapRef), NULL, &specificScrap);
+        err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
+        if (err == noErr) {
+         void * buffer = xmalloc(byteCount);
+         if (buffer != NULL ) {
+           err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText, 
+                                    &byteCount, buffer);
+           if (err == noErr) {
+             // Actually place in the buffer
+             BLOCK_INPUT;
+             // Get the current "selection" string here
+             UNBLOCK_INPUT;
+           }
+         }
+         xfree(buffer);
+        }
+        */
+      }   
+    }
+  return err;
+}
+#endif
 
 /* Open Application Apple Event */
 static pascal OSErr
@@ -12187,6 +12333,83 @@ descriptor_error_exit:
 }
 
 
+static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
+                                        DragReference theDrag)
+{
+  short items;
+  short index;
+  FlavorFlags theFlags;
+  Point mouse;
+  OSErr result;
+  ItemReference theItem;
+  HFSFlavor data;
+  FSRef fref;
+  Size size = sizeof (HFSFlavor);
+
+  drag_and_drop_file_list = Qnil;
+  GetDragMouse (theDrag, &mouse, 0L);
+  CountDragItems (theDrag, &items);
+  for (index = 1; index <= items; index++) 
+    {
+      /* Only handle file references.  */
+      GetDragItemReferenceNumber (theDrag, index, &theItem);
+      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
+      if (result == noErr)
+       {
+#ifdef MAC_OSX
+         FSRef frref;
+#else
+         Str255 path_name;
+#endif
+         Str255 unix_path_name;
+         GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
+#ifdef MAC_OSX
+         /* Use Carbon routines, otherwise it converts the file name
+            to /Macintosh HD/..., which is not correct. */
+         FSpMakeFSRef (&data.fileSpec, &fref);
+         if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
+#else
+         if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
+                                     data.fileSpec.parID, data.fileSpec.name) &&
+             mac_to_posix_pathname (path_name, unix_path_name, 255))
+#endif
+            drag_and_drop_file_list = Fcons (build_string (unix_path_name),
+                                            drag_and_drop_file_list);
+       }
+      else
+       return;
+    }
+  /* If there are items in the list, construct an event and post it to
+     the queue like an interrupt using kbd_buffer_store_event.  */
+  if (!NILP (drag_and_drop_file_list)) 
+    {
+      struct input_event event;
+      Lisp_Object frame;
+      struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
+      SetPort (GetWindowPort (window));
+      GlobalToLocal (&mouse);
+
+      event.kind = DRAG_N_DROP_EVENT;
+      event.code = 0;
+      event.modifiers = 0;
+      event.timestamp = TickCount () * (1000 / 60);
+      XSETINT (event.x, mouse.h);
+      XSETINT (event.y, mouse.v);
+      XSETFRAME (frame, f);
+      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      event.arg = Qnil;
+      /* Post to the interrupt queue */
+      kbd_buffer_store_event (&event);
+      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
+      {
+       ProcessSerialNumber psn;
+       GetCurrentProcess (&psn);
+       SetFrontProcess (&psn);
+      }
+    }
+}
+
+
 /* Print Document Apple Event */
 static pascal OSErr
 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
@@ -12334,7 +12557,12 @@ keycode_to_xkeysym (int keyCode, int *xKeySym)
 int
 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 {
-  int count = 0;
+  int count = 0; 
+#if USE_CARBON_EVENTS
+  OSStatus rneResult;
+  EventRef eventRef;
+  EventMouseButton mouseBtn;
+#endif
   EventRecord er;
   int the_modifiers;
   EventMask event_mask;
@@ -12380,7 +12608,52 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
+#if USE_CARBON_EVENTS
+  rneResult = ReceiveNextEvent (0, NULL, 
+                               expected ? TicksToEventTime(app_sleep_time) : 0,
+                               true, &eventRef);
+  if (!rneResult)
+    {
+      /* Handle new events */
+      if (!mac_convert_event_ref (eventRef, &er)) 
+       switch (GetEventClass (eventRef)) 
+         {
+         case kEventClassMouse:
+           if (GetEventKind (eventRef) == kEventMouseWheelMoved) 
+             {
+               SInt32 delta;
+               Point point;
+               WindowPtr window_ptr = FrontWindow ();
+               struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
+               GetEventParameter(eventRef, kEventParamMouseWheelDelta,
+                                 typeSInt32, NULL, sizeof (SInt32),
+                                 NULL, &delta);
+               GetEventParameter(eventRef, kEventParamMouseLocation,
+                                 typeQDPoint, NULL, sizeof (Point),
+                                 NULL, &point);
+               bufp->kind = MOUSE_WHEEL_EVENT;
+               bufp->code = delta;
+               bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
+               SetPort (GetWindowPort (window_ptr));
+               GlobalToLocal (&point);
+               XSETINT (bufp->x, point.h);
+               XSETINT (bufp->y, point.v);
+               XSETFRAME (bufp->frame_or_window, mwp->mFP);
+               bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
+               count++;
+             }
+           else
+             SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+
+           break;
+         default:
+           /* Send the event to the appropriate receiver.  */
+           SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+         }
+      else
+#else
   if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
+#endif /* USE_CARBON_EVENTS */
     switch (er.what)
       {
       case mouseDown:
@@ -12389,6 +12662,11 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
          WindowPtr window_ptr = FrontWindow ();
          SInt16 part_code;
 
+#if USE_CARBON_EVENTS
+         /* This is needed to correctly */
+         SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+#endif
+
           if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
              && er.what == mouseUp)
             {
@@ -12404,11 +12682,20 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 
              GlobalToLocal (&mouse_loc);
                  
+#if USE_CARBON_EVENTS
+             bufp->code = mac_get_mouse_btn (eventRef);
+#else
              bufp->code = 0;  /* only one mouse button */
+#endif
               bufp->kind = SCROLL_BAR_CLICK_EVENT;
               bufp->frame_or_window = tracked_scroll_bar->window;
               bufp->part = scroll_bar_handle;
-              bufp->modifiers = up_modifier;
+#if USE_CARBON_EVENTS
+             bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+             bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+              bufp->modifiers |= up_modifier;
              bufp->timestamp = er.when * (1000 / 60);
                /* ticks to milliseconds */
 
@@ -12461,7 +12748,12 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 #else
                  control_part_code = FindControl (mouse_loc, window_ptr, &ch);
 #endif           
+
+#if USE_CARBON_EVENTS
+                 bufp->code = mac_get_mouse_btn (eventRef);
+#else            
                  bufp->code = 0;  /* only one mouse button */
+#endif
                  XSETINT (bufp->x, mouse_loc.h);
                  XSETINT (bufp->y, mouse_loc.v);
                  bufp->timestamp = er.when * (1000 / 60);
@@ -12501,13 +12793,19 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                        mouse_tracking_in_progress = mouse_tracking_none;
                    }
                                
+#if USE_CARBON_EVENTS
+                 bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+                 bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+
                  switch (er.what)
                    {
                    case mouseDown:
-                     bufp->modifiers = down_modifier;
+                     bufp->modifiers |= down_modifier;
                      break;
                    case mouseUp:
-                     bufp->modifiers = up_modifier;
+                     bufp->modifiers |= up_modifier;
                      break;
                    }
                                                                
@@ -12559,6 +12857,9 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
       case updateEvt:
       case osEvt:
       case activateEvt:
+#if USE_CARBON_EVENTS
+       SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+#endif 
        do_events (&er);
        break;
        
@@ -12579,11 +12880,21 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
            {
              bufp->code = 0xff00 | xkeysym;
              bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-           }         
+           }      
+         else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
+           {
+             /* This is a special case to deal with converting from
+                a control character to non-control character */
+             int new_modifiers = er.modifiers & ~controlKey;
+             int new_keycode = keycode | new_modifiers;              
+             Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+             unsigned long some_state = 0;
+             bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
+             bufp->kind = ASCII_KEYSTROKE_EVENT;
+           }
          else
            {
-             if (er.modifiers
-                 & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+             if (er.modifiers & macMetaKey)
                {
                  /* This code comes from Keyboard Resource, Appendix
                     C of IM - Text.  This is necessary since shift is
@@ -12597,6 +12908,16 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
                  bufp->code = KeyTranslate (kchr_ptr, new_keycode,
                                             &some_state) & 0xff;
                }
+#if USE_CARBON_EVENTS
+             else if (er.modifiers & cmdKey &&
+                      (NILP (Vmac_command_key_is_meta)))
+               {
+                 /* If this is a command key (and we are not overriding it),
+                    send back to the operating system  */
+                 SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+                 break;
+               }
+#endif
              else
                bufp->code = er.message & charCodeMask;
              bufp->kind = ASCII_KEYSTROKE_EVENT;
@@ -12654,24 +12975,12 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
               }
          }
 
-       the_modifiers = 0;
-       if (er.modifiers & shiftKey)
-         the_modifiers |= shift_modifier;
-       if (er.modifiers & controlKey)
-         the_modifiers |= ctrl_modifier;
-       /* Use option or command key as meta depending on value of
-          mac-command-key-is-meta.  */
-       if (er.modifiers
-           & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-         the_modifiers |= meta_modifier;
-       /* If the Mac option key is meta, then make Emacs recognize
-          the Mac command key as alt.  */
-       if (NILP (Vmac_command_key_is_meta) && (er.modifiers & cmdKey))
-         the_modifiers |= alt_modifier;
-
-       bufp->modifiers = the_modifiers;
-                               
+#if USE_CARBON_EVENTS
+       bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+       bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+       
        {
          mac_output *mwp
            = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
@@ -12706,7 +13015,11 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
             bufp->code = 0;
             bufp->timestamp = er.when * (1000 / 60);
              /* ticks to milliseconds */
-            bufp->modifiers = 0;
+#if USE_CARBON_EVENTS
+           bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+           bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
 
             XSETINT (bufp->x, 0);
             XSETINT (bufp->y, 0);
@@ -12732,10 +13045,13 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
             
             count++;
           }
-        
       default:
        break;
       }
+#if USE_CARBON_EVENTS
+      ReleaseEvent (eventRef);
+    }
+#endif
 
   /* If the focus was just given to an autoraising frame,
      raise it now.  */
@@ -12847,7 +13163,6 @@ NewMacWindow (FRAME_PTR fp)
     if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
       abort ();
   
-
   SetWRefCon (mwp->mWP, (long) mwp);
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
@@ -13183,6 +13498,12 @@ mac_initialize ()
 #if TARGET_API_MAC_CARBON
   init_required_apple_events ();
 
+  init_mac_drag_n_drop ();
+
+#if USE_CARBON_EVENTS
+  init_service_handler ();
+#endif
+
   DisableMenuCommand (NULL, kHICommandQuit);
 #endif
 }
@@ -13253,6 +13574,19 @@ to 4.1, set this to nil.  */);
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  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.  */);
+  Vmac_reverse_ctrl_meta = Qnil;
+
+#if USE_CARBON_EVENTS
+  DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
+   doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
+the right click will be mouse-3.
+Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
+  Vmac_wheel_button_is_mouse_2 = Qt;
+#endif
+
   DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
     doc: /* One of the Text Encoding Base constant values defined in the
 Basic Text Constants section of Inside Macintosh - Text Encoding
index 63fa1f0ee3b5cc73b8a603b561667746c7d32615..a479b5bdc1a719028b850a24df92ab6cbaa7e68d 100644 (file)
@@ -242,9 +242,9 @@ enum event_kind
                                   the mouse click occurred in.
                                   .timestamp gives a timestamp (in
                                   milliseconds) for the click.  */
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   MOUSE_WHEEL_EVENT,           /* A mouse-wheel event is generated 
-                                  on WINDOWSNT by a 
+                                  on WINDOWSNT or MAC_OSX by a 
                                   wheel on a mouse (e.g., MS Intellimouse).
                                   The event contains a delta that corresponds
                                   to the amount and direction that the wheel
@@ -259,6 +259,8 @@ enum event_kind
                                   the wheel event occurred in.
                                   .timestamp gives a timestamp (in
                                   milliseconds) for the wheel event.  */
+#endif
+#ifdef WINDOWSNT
   LANGUAGE_CHANGE_EVENT,       /* A LANGUAGE_CHANGE_EVENT is generated
                                   on WINDOWSNT when the keyboard layout
                                   or input language is changed by the