X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/2d97ff8cf6090dcd93722f7a459fc52def6070ee..44fab9c1c6d383dbf846bca886e13bf00446bdc0:/src/macterm.c diff --git a/src/macterm.c b/src/macterm.c index 41dfbc0c0a..e9cb1b07de 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -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 #include @@ -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) + /* Fringe bitmaps. */ @@ -7005,9 +7018,9 @@ note_mode_line_highlight (w, x, mode_line_p) if (glyph < end && STRINGP (glyph->object) - && XSTRING (glyph->object)->intervals + && STRING_INTERVALS (glyph->object) && glyph->charpos >= 0 - && glyph->charpos < XSTRING (glyph->object)->size) + && glyph->charpos < SCHARS (glyph->object)) { /* If we're on a string with `help-echo' text property, arrange for the help to be displayed. This is done by @@ -7328,7 +7341,7 @@ note_mouse_highlight (f, x, y) if (NILP (b)) b = make_number (0); if (NILP (e)) - e = make_number (XSTRING (object)->size - 1); + e = make_number (SCHARS (object) - 1); fast_find_string_pos (w, XINT (b), object, &dpyinfo->mouse_face_beg_col, &dpyinfo->mouse_face_beg_row, @@ -7426,7 +7439,7 @@ note_mouse_highlight (f, x, y) /* Try text properties. */ if (STRINGP (object) && charpos >= 0 - && charpos < XSTRING (object)->size) + && charpos < SCHARS (object)) { help = Fget_text_property (make_number (charpos), Qhelp_echo, object); @@ -9469,7 +9482,7 @@ x_bitmap_icon (f, icon) if (NILP (icon)) hicon = LoadIcon (hinst, EMACS_CLASS); else if (STRINGP (icon)) - hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0, + hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); else if (SYMBOLP (icon)) { @@ -9606,7 +9619,7 @@ x_new_fontset (f, fontsetname) to do. */ return fontset_name (fontset); - result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data)); + result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); if (!STRINGP (result)) /* Can't load ASCII font. */ @@ -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 */ } @@ -10747,8 +10673,14 @@ init_font_name_table () sc)); } else - add_font_name_table_entry (mac_to_x_fontname (name, size, style, - sc)); + { + add_font_name_table_entry (mac_to_x_fontname (name, size, + style, sc)); + if (smJapanese == sc) + add_font_name_table_entry (mac_to_x_fontname (name, size, + style, + -smJapanese)); + } } /* Dispose of the iterators. */ @@ -10833,7 +10765,7 @@ init_font_name_table () = mac_to_x_fontname (name, assc_entry->fontSize, assc_entry->fontStyle, - smRoman); + -smJapanese); } } } @@ -10854,11 +10786,9 @@ init_font_name_table () /* Return a list of at most MAXNAMES font specs matching the one in - PATTERN. Note that each '*' in the PATTERN matches exactly one - field of the font spec, unlike X in which an '*' in a font spec can - match a number of fields. The result is in the Mac implementation - all fonts must be specified by a font spec with all 13 fields - (although many of these can be "*'s"). */ + PATTERN. Cache matching fonts for patterns in + dpyinfo->name_list_element to avoid looking them up again by + calling mac_font_pattern_match (slow). */ Lisp_Object x_list_fonts (struct frame *f, @@ -10867,15 +10797,29 @@ x_list_fonts (struct frame *f, int maxnames) { char *ptnstr; - Lisp_Object newlist = Qnil; + Lisp_Object newlist = Qnil, tem, key; int n_fonts = 0; int i; struct gcpro gcpro1, gcpro2; + struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL; if (font_name_table == NULL) /* Initialize when first used. */ init_font_name_table (); - ptnstr = XSTRING (pattern)->data; + if (dpyinfo) + { + tem = XCDR (dpyinfo->name_list_element); + key = Fcons (pattern, make_number (maxnames)); + + newlist = Fassoc (key, tem); + if (!NILP (newlist)) + { + newlist = Fcdr_safe (newlist); + goto label_cached; + } + } + + ptnstr = SDATA (pattern); GCPRO2 (pattern, newlist); @@ -10896,6 +10840,14 @@ x_list_fonts (struct frame *f, UNGCPRO; + if (dpyinfo) + { + XSETCDR (dpyinfo->name_list_element, + Fcons (Fcons (key, newlist), + XCDR (dpyinfo->name_list_element))); + } + label_cached: + return newlist; } @@ -11105,7 +11057,7 @@ XLoadQueryFont (Display *dpy, char *fontname) if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s", cs) == 1 - && 0 == strcmp (cs, "mac-roman")) + && 0 == strcmp (cs, "jisx0201.1976-0")) font->mac_scriptcode = smRoman; } @@ -11217,9 +11169,9 @@ x_load_font (f, fontname, size) for (tail = font_names; CONSP (tail); tail = XCDR (tail)) if (dpyinfo->font_table[i].name && (!strcmp (dpyinfo->font_table[i].name, - XSTRING (XCAR (tail))->data) + SDATA (XCAR (tail))) || !strcmp (dpyinfo->font_table[i].full_name, - XSTRING (XCAR (tail))->data))) + SDATA (XCAR (tail))))) return (dpyinfo->font_table + i); } @@ -11237,7 +11189,7 @@ x_load_font (f, fontname, size) a bug of not finding a font even if the font surely exists and is loadable by XLoadQueryFont. */ if (size > 0 && !NILP (font_names)) - fontname = (char *) XSTRING (XCAR (font_names))->data; + fontname = (char *) SDATA (XCAR (font_names)); font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname); if (!font) @@ -11431,7 +11383,7 @@ same_x_server (name1, name2) char *name1, *name2; { int seen_colon = 0; - unsigned char *system_name = XSTRING (Vsystem_name)->data; + unsigned char *system_name = SDATA (Vsystem_name); int system_name_length = strlen (system_name); int length_until_period = 0; @@ -11534,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; @@ -11551,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 **); @@ -11566,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) @@ -11993,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 @@ -12066,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, ©Types); + type = CreateTypeStringWithOSType (kScrapFlavorTypeText); + if (type) { + CFArrayAppendValue (copyTypes, type); + //CFArrayAppendValue (pasteTypes, type); + CFRelease (type); + } + } + case kEventServiceCopy: + { + ScrapRef currentScrap, specificScrap; + char * buf = ""; + Size byteCount = 0; + + GetCurrentScrap (¤tScrap); + + 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 @@ -12123,20 +12295,31 @@ do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon) int i; /* AE file list is one based so just use that for indexing here. */ - for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) { - FSSpec fs; - Str255 path_name, unix_path_name; + for (i = 1; (err == noErr) && (i <= num_files_to_open); i++) + { + FSSpec fs; + Str255 path_name, unix_path_name; +#ifdef MAC_OSX + FSRef fref; +#endif - err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type, - (Ptr) &fs, sizeof (fs), &actual_size); - if (err != noErr) break; + err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type, + (Ptr) &fs, sizeof (fs), &actual_size); + if (err != noErr) break; - if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID, - fs.name) && - mac_to_posix_pathname (path_name, unix_path_name, 255)) - drag_and_drop_file_list = Fcons (build_string (unix_path_name), - drag_and_drop_file_list); - } +#ifdef MAC_OSX + err = FSpMakeFSRef (&fs, &fref); + if (err != noErr) break; + + if (FSRefMakePath (&fref, unix_path_name, 255) == noErr) +#else + if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID, + fs.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); + } } } @@ -12150,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) @@ -12297,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; @@ -12343,7 +12608,54 @@ 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: @@ -12352,6 +12664,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) { @@ -12367,11 +12684,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 */ @@ -12424,7 +12750,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); @@ -12464,13 +12795,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; } @@ -12522,6 +12859,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; @@ -12531,6 +12871,13 @@ XTread_socket (int sd, struct input_event *bufp, int numchars, int expected) int keycode = (er.message & keyCodeMask) >> 8; int xkeysym; + if (!IsValidWindowPtr (FrontNonFloatingWindow ())) + { + SysBeep (1); + UNBLOCK_INPUT; + return 0; + } + ObscureCursor (); if (keycode == 0x33) /* delete key (charCode translated to 0x8) */ @@ -12542,11 +12889,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 @@ -12560,6 +12917,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; @@ -12617,24 +12984,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 ()); @@ -12669,7 +13024,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); @@ -12695,10 +13054,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. */ @@ -12810,7 +13172,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 */ @@ -12931,7 +13292,7 @@ same_x_server (name1, name2) char *name1, *name2; { int seen_colon = 0; - unsigned char *system_name = XSTRING (Vsystem_name)->data; + unsigned char *system_name = SDATA (Vsystem_name); int system_name_length = strlen (system_name); int length_until_period = 0; @@ -12989,11 +13350,11 @@ mac_initialize_display_info () #if 0 dpyinfo->mac_id_name - = (char *) xmalloc (XSTRING (Vinvocation_name)->size - + XSTRING (Vsystem_name)->size + = (char *) xmalloc (SCHARS (Vinvocation_name) + + SCHARS (Vsystem_name) + 2); sprintf (dpyinfo->mac_id_name, "%s@%s", - XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data); + SDATA (Vinvocation_name), SDATA (Vsystem_name)); #else dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1); strcpy (dpyinfo->mac_id_name, "Mac Display"); @@ -13142,6 +13503,18 @@ mac_initialize () #endif mac_initialize_display_info (); + +#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 } @@ -13210,6 +13583,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