X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e169f939a59dee9a773116c9a6e40f6fb25b2511..6ab9dd8034fcd76f5d2e92a91243f8d8be3a8f98:/src/macterm.c diff --git a/src/macterm.c b/src/macterm.c index dda0cc8311..5aab6ec536 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -1,5 +1,5 @@ /* Implementation of GUI terminal on the Mac OS. - Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -34,12 +34,12 @@ Boston, MA 02111-1307, USA. */ #include #endif -#ifdef MAC_OSX +#if TARGET_API_MAC_CARBON /* 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 */ +#else /* not TARGET_API_MAC_CARBON */ #include #include #include @@ -58,7 +58,7 @@ Boston, MA 02111-1307, USA. */ #if __profile__ #include #endif -#endif /* not MAC_OSX */ +#endif /* not TARGET_API_MAC_CARBON */ #include "systty.h" #include "systime.h" @@ -69,6 +69,7 @@ Boston, MA 02111-1307, USA. */ #include #include #include +#include #include "keyboard.h" #include "frame.h" @@ -94,20 +95,24 @@ Boston, MA 02111-1307, USA. */ : 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. */ Lisp_Object Vx_toolkit_scroll_bars; +/* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */ +Lisp_Object Vmac_use_core_graphics; + + /* Non-zero means that a HELP_EVENT has been generated since Emacs start. */ 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. */ @@ -124,9 +129,12 @@ int x_use_underline_position_properties; struct x_display_info *x_display_list; /* This is a list of cons cells, each of the form (NAME - . FONT-LIST-CACHE), one for each element of x_display_list and in - the same order. NAME is the name of the frame. FONT-LIST-CACHE - records previous values returned by x-list-fonts. */ + FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of + x_display_list and in the same order. NAME is the name of the + frame. FONT-LIST-CACHE records previous values returned by + x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database + equivalent, which is implemented with a Lisp object, for the + display. */ Lisp_Object x_display_name_list; @@ -240,7 +248,7 @@ extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *)); extern int inhibit_window_system; -#if __MRC__ +#if __MRC__ && !TARGET_API_MAC_CARBON QDGlobals qd; /* QuickDraw global information structure. */ #endif @@ -265,14 +273,16 @@ static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); 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 *)); @@ -285,9 +295,6 @@ static void x_update_begin P_ ((struct frame *)); static void x_update_window_begin P_ ((struct window *)); static void x_after_update_window_line P_ ((struct glyph_row *)); -void activate_scroll_bars (FRAME_PTR); -void deactivate_scroll_bars (FRAME_PTR); - static int is_emacs_window (WindowPtr); int x_bitmap_icon (struct frame *, Lisp_Object); @@ -345,8 +352,12 @@ mac_set_backcolor (unsigned long color) commands. Assume that the graphic port has already been set. */ static void -mac_set_colors (GC gc) +mac_set_colors (gc, bg_save) + GC gc; + RGBColor *bg_save; { + if (bg_save) + GetBackColor (bg_save); mac_set_forecolor (gc->foreground); mac_set_backcolor (gc->background); } @@ -360,12 +371,16 @@ XDrawLine (display, w, gc, x1, y1, x2, y2) GC gc; int x1, y1, x2, y2; { + RGBColor old_bg; + SetPortWindowPort (w); - mac_set_colors (gc); + mac_set_colors (gc, &old_bg); MoveTo (x1, y1); LineTo (x2, y2); + + RGBBackColor (&old_bg); } void @@ -381,7 +396,7 @@ mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2) GetGWorld (&old_port, &old_gdh); SetGWorld (p, NULL); - mac_set_colors (gc); + mac_set_colors (gc, NULL); LockPixels (GetGWorldPixMap (p)); MoveTo (x1, y1); @@ -404,16 +419,19 @@ XClearArea (display, w, x, y, width, height, exposures) struct mac_output *mwp = (mac_output *) GetWRefCon (w); Rect r; XGCValues xgc; + RGBColor old_bg; xgc.foreground = mwp->x_compatible.foreground_pixel; xgc.background = mwp->x_compatible.background_pixel; SetPortWindowPort (w); - mac_set_colors (&xgc); + mac_set_colors (&xgc, &old_bg); SetRect (&r, x, y, x + width, y + height); EraseRect (&r); + + RGBBackColor (&old_bg); } /* Mac version of XClearWindow. */ @@ -431,7 +449,7 @@ XClearWindow (display, w) SetPortWindowPort (w); - mac_set_colors (&xgc); + mac_set_colors (&xgc, NULL); #if TARGET_API_MAC_CARBON { @@ -459,6 +477,7 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p) { BitMap bitmap; Rect r; + RGBColor old_bg; bitmap.rowBytes = sizeof(unsigned short); bitmap.baseAddr = (char *)bits; @@ -466,7 +485,7 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p) SetPortWindowPort (w); - mac_set_colors (gc); + mac_set_colors (gc, &old_bg); SetRect (&r, x, y, x + width, y + height); #if TARGET_API_MAC_CARBON @@ -478,6 +497,8 @@ mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p) CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0); #endif /* not TARGET_API_MAC_CARBON */ + + RGBBackColor (&old_bg); } @@ -626,13 +647,16 @@ XFillRectangle (display, w, gc, x, y, width, height) unsigned int width, height; { Rect r; + RGBColor old_bg; SetPortWindowPort (w); - mac_set_colors (gc); + mac_set_colors (gc, &old_bg); SetRect (&r, x, y, x + width, y + height); PaintRect (&r); /* using foreground color of gc */ + + RGBBackColor (&old_bg); } @@ -651,7 +675,7 @@ mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height) GetGWorld (&old_port, &old_gdh); SetGWorld (p, NULL); - mac_set_colors (gc); + mac_set_colors (gc, NULL); SetRect (&r, x, y, x + width, y + height); LockPixels (GetGWorldPixMap (p)); @@ -674,13 +698,16 @@ mac_draw_rectangle (display, w, gc, x, y, width, height) unsigned int width, height; { Rect r; + RGBColor old_bg; SetPortWindowPort (w); - mac_set_colors (gc); + mac_set_colors (gc, &old_bg); SetRect (&r, x, y, x + width + 1, y + height + 1); FrameRect (&r); /* using foreground color of gc */ + + RGBBackColor (&old_bg); } @@ -701,7 +728,7 @@ mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height) GetGWorld (&old_port, &old_gdh); SetGWorld (p, NULL); - mac_set_colors (gc); + mac_set_colors (gc, NULL); SetRect (&r, x, y, x + width + 1, y + height + 1); LockPixels (GetGWorldPixMap (p)); @@ -723,9 +750,18 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, char *buf; int nchars, mode, bytes_per_char; { + RGBColor old_bg; + SetPortWindowPort (w); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + UInt32 textFlags, savedFlags; + if (!NILP(Vmac_use_core_graphics)) { + textFlags = kQDUseCGTextRendering; + savedFlags = SwapQDTextFlags(textFlags); + } +#endif - mac_set_colors (gc); + mac_set_colors (gc, &old_bg); TextFont (gc->font->mac_fontnum); TextSize (gc->font->mac_fontsize); @@ -734,6 +770,12 @@ mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode, MoveTo (x, y); DrawText (buf, 0, nchars * bytes_per_char); + + RGBBackColor (&old_bg); +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 + if (!NILP(Vmac_use_core_graphics)) + SwapQDTextFlags(savedFlags); +#endif } @@ -917,7 +959,7 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y) SetPort (w); #if 0 - mac_set_colors (gc); + mac_set_colors (gc, NULL); #endif SetRect (&src_r, src_x, src_y, src_x + width, src_y + height); @@ -939,7 +981,7 @@ mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y) BackColor (whiteColor); CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0); - mac_set_colors (gc); + mac_set_colors (gc, NULL); #endif #endif /* not TARGET_API_MAC_CARBON */ } @@ -1090,24 +1132,71 @@ XSetForeground (display, gc, color) } -/* Mac replacement for XSetFont. */ +/* Mac replacement for XSetBackground. */ -static void -XSetFont (display, gc, font) +void +XSetBackground (display, gc, color) Display *display; GC gc; - XFontStruct *font; + unsigned long color; { - gc->font = font; + gc->background = color; +} + + +/* Mac replacement for XSetWindowBackground. */ + +void +XSetWindowBackground (display, w, color) + Display *display; + WindowPtr w; + unsigned long color; +{ +#if !TARGET_API_MAC_CARBON + AuxWinHandle aw_handle; + CTabHandle ctab_handle; + ColorSpecPtr ct_table; + short ct_size; +#endif + RGBColor bg_color; + + bg_color.red = RED16_FROM_ULONG (color); + bg_color.green = GREEN16_FROM_ULONG (color); + bg_color.blue = BLUE16_FROM_ULONG (color); + +#if TARGET_API_MAC_CARBON + SetWindowContentColor (w, &bg_color); +#else + if (GetAuxWin (w, &aw_handle)) + { + ctab_handle = (*aw_handle)->awCTable; + HandToHand ((Handle *) &ctab_handle); + ct_table = (*ctab_handle)->ctTable; + ct_size = (*ctab_handle)->ctSize; + while (ct_size > -1) + { + if (ct_table->value == 0) + { + ct_table->rgb = bg_color; + CTabChanged (ctab_handle); + SetWinColor (w, (WCTabHandle) ctab_handle); + } + ct_size--; + } + } +#endif } +/* Mac replacement for XSetFont. */ + static void -XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars, - int *direction,int *font_ascent, - int *font_descent, XCharStruct *cs) +XSetFont (display, gc, font) + Display *display; + GC gc; + XFontStruct *font; { - /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */ + gc->font = font; } @@ -1323,13 +1412,6 @@ x_update_end (f) FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0; BLOCK_INPUT; - /* Reset the background color of Mac OS Window to that of the frame after - update so that it is used by Mac Toolbox to clear the update region before - an update event is generated. */ - SetPortWindowPort (FRAME_MAC_WINDOW (f)); - - mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f)); - #if TARGET_API_MAC_CARBON EnableScreenUpdates (); #endif @@ -1919,20 +2001,33 @@ static void mac_compute_glyph_string_overhangs (s) struct glyph_string *s; { -#if 0 - /* MAC_TODO: XTextExtents16 does nothing yet... */ + Rect r; + MacFontStruct *font = s->font; - if (s->cmp == NULL - && s->first_glyph->type == CHAR_GLYPH) + TextFont (font->mac_fontnum); + TextSize (font->mac_fontsize); + TextFace (font->mac_fontface); + + if (s->two_byte_p) + QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); + else { - XCharStruct cs; - int direction, font_ascent, font_descent; - XTextExtents16 (s->font, s->char2b, s->nchars, &direction, - &font_ascent, &font_descent, &cs); - s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; - s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; + int i; + char *buf = xmalloc (s->nchars); + + if (buf == NULL) + SetRect (&r, 0, 0, 0, 0); + else + { + for (i = 0; i < s->nchars; ++i) + buf[i] = s->char2b[i].byte2; + QDTextBounds (s->nchars, buf, &r); + xfree (buf); + } } -#endif + + s->right_overhang = r.right > s->width ? r.right - s->width : 0; + s->left_overhang = r.left < 0 ? -r.left : 0; } @@ -2570,15 +2665,9 @@ x_draw_glyph_string_box (s) struct glyph *last_glyph; Rect clip_rect; - last_x = window_box_right (s->w, s->area); - if (s->row->full_width_p - && !s->w->pseudo_window_p) - { - last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w); - if (s->area != RIGHT_MARGIN_AREA - || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w)) - last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w); - } + last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) + ? WINDOW_RIGHT_EDGE_X (s->w) + : window_box_right (s->w, s->area)); /* The glyph that may have a right box line. */ last_glyph = (s->cmp || s->img @@ -3006,10 +3095,12 @@ x_draw_glyph_string (s) { int relief_drawn_p = 0; - /* If S draws into the background of its successor, draw the - background of the successor first so that S can draw into it. - This makes S->next use XDrawString instead of XDrawImageString. */ - if (s->next && s->right_overhang && !s->for_overlaps_p) + /* If S draws into the background of its successor that does not + draw a cursor, draw the background of the successor first so that + S can draw into it. This makes S->next use XDrawString instead + of XDrawImageString. */ + if (s->next && s->right_overhang && !s->for_overlaps_p + && s->next->hl != DRAW_CURSOR) { xassert (s->next->img == NULL); x_set_glyph_string_gc (s->next); @@ -3396,6 +3487,14 @@ static void 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); } @@ -3403,6 +3502,14 @@ static void 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); } @@ -3445,6 +3552,68 @@ x_new_focus_frame (dpyinfo, frame) 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 @@ -3882,25 +4051,19 @@ remember_mouse_glyph (f1, gx, gy) } -static WindowPtr -front_emacs_window () +static struct frame * +mac_focus_frame (dpyinfo) + struct mac_display_info *dpyinfo; { -#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; + 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 (); } -#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP) /* Return the current position of the mouse. *fp should be a frame which indicates which display to ask about. @@ -3933,13 +4096,10 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) { 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) @@ -4390,50 +4550,6 @@ XTjudge_scroll_bars (f) } -void -activate_scroll_bars (frame) - FRAME_PTR frame; -{ - Lisp_Object bar; - ControlHandle ch; - - bar = FRAME_SCROLL_BARS (frame); - while (! NILP (bar)) - { - ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar)); -#if 1 /* TARGET_API_MAC_CARBON */ - ActivateControl (ch); -#else - SetControlMaximum (ch, - VERTICAL_SCROLL_BAR_TOP_RANGE (frame, - XINT (XSCROLL_BAR (bar) - ->height)) - 1); -#endif - bar = XSCROLL_BAR (bar)->next; - } -} - - -void -deactivate_scroll_bars (frame) - FRAME_PTR frame; -{ - Lisp_Object bar; - ControlHandle ch; - - bar = FRAME_SCROLL_BARS (frame); - while (! NILP (bar)) - { - ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar)); -#if 1 /* TARGET_API_MAC_CARBON */ - DeactivateControl (ch); -#else - SetControlMaximum (ch, -1); -#endif - bar = XSCROLL_BAR (bar)->next; - } -} - /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind is set to something other than NO_EVENT, it is enqueued. @@ -4550,7 +4666,12 @@ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) unsigned long *time; { struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar); - 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; @@ -4650,29 +4771,10 @@ x_draw_hollow_cursor (w, row) if (cursor_glyph == NULL) return; - /* Compute the width of the rectangle to draw. If on a stretch - glyph, and `x-stretch-block-cursor' is nil, don't draw a - rectangle as wide as the glyph, but use a canonical character - width instead. */ - wd = cursor_glyph->pixel_width - 1; - if (cursor_glyph->type == STRETCH_GLYPH - && !x_stretch_cursor_p) - wd = min (FRAME_COLUMN_WIDTH (f), wd); - w->phys_cursor_width = wd; - - /* Compute frame-relative coordinates from window-relative - coordinates. */ + /* Compute frame-relative coordinates for phys cursor. */ x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); - - /* Compute the proper height and ascent of the rectangle, based - on the actual glyph. Using the full height of the row looks - bad when there are tall images on that row. */ - h = max (min (FRAME_LINE_HEIGHT (f), row->height), - cursor_glyph->ascent + cursor_glyph->descent); - if (h < row->height) - y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h; - h--; + y = get_phys_cursor_geometry (w, row, cursor_glyph, &h); + wd = w->phys_cursor_width; /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ @@ -4783,11 +4885,7 @@ mac_define_frame_cursor (f, cursor) struct frame *f; Cursor cursor; { -#if TARGET_API_MAC_CARBON SetThemeCursor (cursor); -#else - SetCursor (*cursor); -#endif } @@ -5019,7 +5117,7 @@ x_new_fontset (f, fontsetname) 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); } @@ -5212,6 +5310,11 @@ x_set_window_size (f, change_gravity, cols, rows) x_wm_set_size_hint (f, (long) 0, 0); SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0); +#if TARGET_API_MAC_CARBON + if (f->output_data.mac->hourglass_control) + MoveControl (f->output_data.mac->hourglass_control, + pixelwidth - HOURGLASS_WIDTH, 0); +#endif /* Now, strictly speaking, we can't be sure that this is accurate, but the window manager will get around to dealing with the size @@ -5389,7 +5492,7 @@ x_make_frame_visible (f) else RepositionWindow (FRAME_MAC_WINDOW (f), FRAME_MAC_WINDOW (sf), -#ifdef MAC_OS_X_VERSION_10_2 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 kWindowCascadeStartAtParentWindowScreen #else kWindowCascadeOnParentWindowScreen @@ -5462,6 +5565,13 @@ x_make_frame_invisible (f) 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 @@ -5512,6 +5622,9 @@ x_free_frame_resources (f) BLOCK_INPUT; + if (wp != tip_window) + remove_window_handler (wp); + DisposeWindow (wp); if (wp == tip_window) /* Neither WaitNextEvent nor ReceiveNextEvent receives `window @@ -5858,7 +5971,7 @@ decode_mac_font_name (name, size, scriptcode) static char * -mac_to_x_fontname (name, size, style, scriptcode, encoding_base) +mac_to_x_fontname (name, size, style, scriptcode) char *name; int size; Style style; @@ -6411,7 +6524,7 @@ x_list_fonts (struct frame *f, if (dpyinfo) { - tem = XCDR (dpyinfo->name_list_element); + tem = XCAR (XCDR (dpyinfo->name_list_element)); key = Fcons (pattern, make_number (maxnames)); newlist = Fassoc (key, tem); @@ -6430,9 +6543,9 @@ x_list_fonts (struct frame *f, if (dpyinfo) { - XSETCDR (dpyinfo->name_list_element, + XSETCAR (XCDR (dpyinfo->name_list_element), Fcons (Fcons (key, newlist), - XCDR (dpyinfo->name_list_element))); + XCAR (XCDR (dpyinfo->name_list_element)))); } label_cached: @@ -6690,35 +6803,66 @@ XLoadQueryFont (Display *dpy, char *fontname) returns 15 for 12-point Monaco! */ char_width = CharWidth ('m'); - font->max_bounds.rbearing = char_width; - font->max_bounds.lbearing = 0; - font->max_bounds.width = char_width; - font->max_bounds.ascent = the_fontinfo.ascent; - font->max_bounds.descent = the_fontinfo.descent; + if (is_two_byte_font) + { + font->per_char = NULL; - font->min_bounds = font->max_bounds; + if (fontface & italic) + font->max_bounds.rbearing = char_width + 1; + else + font->max_bounds.rbearing = char_width; + font->max_bounds.lbearing = 0; + font->max_bounds.width = char_width; + font->max_bounds.ascent = the_fontinfo.ascent; + font->max_bounds.descent = the_fontinfo.descent; - if (is_two_byte_font || CharWidth ('m') == CharWidth ('i')) - font->per_char = NULL; + font->min_bounds = font->max_bounds; + } else { font->per_char = (XCharStruct *) xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); { - int c, min_width, max_width; + int c, min_width, max_width; + Rect char_bounds, min_bounds, max_bounds; + char ch; min_width = max_width = char_width; + SetRect (&min_bounds, -32767, -32767, 32767, 32767); + SetRect (&max_bounds, 0, 0, 0, 0); for (c = 0x20; c <= 0xff; c++) { - font->per_char[c - 0x20] = font->max_bounds; - char_width = CharWidth (c); - font->per_char[c - 0x20].width = char_width; - font->per_char[c - 0x20].rbearing = char_width; - min_width = min (min_width, char_width); - max_width = max (max_width, char_width); - } - font->min_bounds.width = min_width; - font->max_bounds.width = max_width; + ch = c; + char_width = CharWidth (ch); + QDTextBounds (1, &ch, &char_bounds); + STORE_XCHARSTRUCT (font->per_char[c - 0x20], + char_width, char_bounds); + /* Some Japanese fonts (in SJIS encoding) return 0 as the + character width of 0x7f. */ + if (char_width > 0) + { + min_width = min (min_width, char_width); + max_width = max (max_width, char_width); + } + if (!EmptyRect (&char_bounds)) + { + SetRect (&min_bounds, + max (min_bounds.left, char_bounds.left), + max (min_bounds.top, char_bounds.top), + min (min_bounds.right, char_bounds.right), + min (min_bounds.bottom, char_bounds.bottom)); + UnionRect (&max_bounds, &char_bounds, &max_bounds); + } + } + STORE_XCHARSTRUCT (font->min_bounds, min_width, min_bounds); + STORE_XCHARSTRUCT (font->max_bounds, max_width, max_bounds); + if (min_width == max_width + && max_bounds.left >= 0 && max_bounds.right <= max_width) + { + /* Fixed width and no overhangs. */ + xfree (font->per_char); + font->per_char = NULL; + } } } @@ -6985,7 +7129,7 @@ x_find_ccl_program (fontp) /* The Mac Event loop code */ -#ifndef MAC_OSX +#if !TARGET_API_MAC_CARBON #include #include #include @@ -7000,13 +7144,12 @@ x_find_ccl_program (fontp) #include #include #include -#include #include #if __MWERKS__ #include #endif -#endif /* ! MAC_OSX */ +#endif /* ! TARGET_API_MAC_CARBON */ #define M_APPLE 128 #define I_ABOUT 1 @@ -7076,11 +7219,6 @@ Lisp_Object Vmac_pass_command_to_system; Lisp_Object Vmac_pass_control_to_system; #endif -/* convert input from Mac keyboard (assumed to be in Mac Roman coding) - to this text encoding */ -int mac_keyboard_text_encoding; -int current_mac_keyboard_text_encoding = kTextEncodingMacRoman; - /* Set in term/mac-win.el to indicate that event loop can now generate drag and drop events. */ Lisp_Object Qmac_ready_for_drag_n_drop; @@ -7089,11 +7227,6 @@ Lisp_Object drag_and_drop_file_list; Point saved_menu_event_location; -#if !TARGET_API_MAC_CARBON -/* Place holder for the default arrow cursor. */ -CursPtr arrow_cursor; -#endif - /* Apple Events */ static void init_required_apple_events (void); static pascal OSErr @@ -7107,12 +7240,16 @@ static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long); /* Drag and Drop */ static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference); static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference); +static DragTrackingHandlerUPP mac_do_track_dragUPP = NULL; +static DragReceiveHandlerUPP mac_do_receive_dragUPP = NULL; #endif #if USE_CARBON_EVENTS +#ifdef MAC_OSX /* Preliminary Support for the OSX Services Menu */ static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*); static void init_service_handler (); +#endif /* Window Event Handler */ static pascal OSStatus mac_handle_window_event (EventHandlerCallRef, EventRef, void *); @@ -7292,8 +7429,6 @@ do_init_managers (void) InitCursor (); #if !TARGET_API_MAC_CARBON - arrow_cursor = &qd.arrow; - /* set up some extra stack space for use by emacs */ SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC)); @@ -7354,15 +7489,16 @@ do_window_update (WindowPtr win) RgnHandle region = NewRgn (); GetPortVisibleRegion (GetWindowPort (win), region); - UpdateControls (win, region); GetRegionBounds (region, &r); + expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top); + UpdateControls (win, region); DisposeRgn (region); } #else - UpdateControls (win, win->visRgn); r = (*win->visRgn)->rgnBBox; -#endif expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top); + UpdateControls (win, win->visRgn); +#endif handling_window_update = 0; } @@ -7392,21 +7528,6 @@ do_app_resume () { /* 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 @@ -7417,61 +7538,12 @@ do_app_suspend () { /* 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 } -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) { @@ -7508,7 +7580,7 @@ do_menu_choice (SInt32 menu_choice) 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) { @@ -7586,13 +7658,14 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out) 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; @@ -7648,7 +7721,7 @@ do_zoom_window (WindowPtr w, int zoom_in_or_out) = 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 */ @@ -7751,7 +7824,7 @@ init_required_apple_events () } #if USE_CARBON_EVENTS - +#ifdef MAC_OSX void init_service_handler () { @@ -7847,7 +7920,7 @@ mac_handle_service_event (EventHandlerCallRef callRef, } return err; } - +#endif static pascal OSStatus mac_handle_window_event (next_handler, event, data) @@ -7855,8 +7928,6 @@ mac_handle_window_event (next_handler, event, data) EventRef event; void *data; { - extern Lisp_Object Qcontrol; - WindowPtr wp; OSStatus result; UInt32 attributes; @@ -7867,6 +7938,14 @@ mac_handle_window_event (next_handler, event, data) switch (GetEventKind (event)) { + case kEventWindowUpdate: + result = CallNextEventHandler (next_handler, event); + if (result != eventNotHandledErr) + return result; + + do_window_update (wp); + break; + case kEventWindowBoundsChanging: result = CallNextEventHandler (next_handler, event); if (result != eventNotHandledErr) @@ -7924,7 +8003,8 @@ install_window_handler (window) { OSErr err = noErr; #if USE_CARBON_EVENTS - EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowBoundsChanging}}; + EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate}, + {kEventClassWindow, kEventWindowBoundsChanging}}; static EventHandlerUPP handle_window_event_UPP = NULL; if (handle_window_event_UPP == NULL) @@ -7935,14 +8015,30 @@ install_window_handler (window) NULL, NULL); #endif #if TARGET_API_MAC_CARBON + if (mac_do_track_dragUPP == NULL) + mac_do_track_dragUPP = NewDragTrackingHandlerUPP (mac_do_track_drag); + if (mac_do_receive_dragUPP == NULL) + mac_do_receive_dragUPP = NewDragReceiveHandlerUPP (mac_do_receive_drag); + if (err == noErr) - err = InstallTrackingHandler (mac_do_track_drag, window, NULL); + err = InstallTrackingHandler (mac_do_track_dragUPP, window, NULL); if (err == noErr) - err = InstallReceiveHandler (mac_do_receive_drag, window, NULL); + err = InstallReceiveHandler (mac_do_receive_dragUPP, window, NULL); #endif return err; } +void +remove_window_handler (window) + WindowPtr window; +{ +#if TARGET_API_MAC_CARBON + if (mac_do_track_dragUPP) + RemoveTrackingHandler (mac_do_track_dragUPP, window); + if (mac_do_receive_dragUPP) + RemoveReceiveHandler (mac_do_receive_dragUPP, window); +#endif +} /* Open Application Apple Event */ static pascal OSErr @@ -8019,27 +8115,29 @@ 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++) + for (i = 1; i <= num_files_to_open; i++) { - FSSpec fs; - Str255 path_name, unix_path_name; + char unix_path_name[MAXPATHLEN]; #ifdef MAC_OSX FSRef fref; -#endif + + err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword, + &actual_type, &fref, sizeof (FSRef), + &actual_size); + if (err != noErr || actual_type != typeFSRef) + continue; + + if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)) + == noErr) +#else + FSSpec fs; err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type, (Ptr) &fs, sizeof (fs), &actual_size); - if (err != noErr) break; - -#ifdef MAC_OSX - err = FSpMakeFSRef (&fs, &fref); - if (err != noErr) break; + if (err != noErr) continue; - 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)) + if (fsspec_to_posix_pathname (&fs, unix_path_name, + sizeof (unix_path_name) - 1) == noErr) #endif /* x-dnd functions expect undecoded filenames. */ drag_and_drop_file_list = @@ -8072,18 +8170,21 @@ mac_do_track_drag (DragTrackingMessage message, WindowPtr window, FlavorFlags theFlags; OSErr result; + if (GetFrontWindowOfClass (kMovableModalWindowClass, false)) + return dragNotAcceptedErr; + switch (message) { case kDragTrackingEnterHandler: CountDragItems (theDrag, &items); - can_accept = 1; + can_accept = 0; for (index = 1; index <= items; index++) { GetDragItemReferenceNumber (theDrag, index, &theItem); result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags); - if (result != noErr) + if (result == noErr) { - can_accept = 0; + can_accept = 1; break; } } @@ -8094,6 +8195,7 @@ mac_do_track_drag (DragTrackingMessage message, WindowPtr window, { RgnHandle hilite_rgn = NewRgn (); Rect r; + struct frame *f = mac_window_to_frame (window); GetWindowPortBounds (window, &r); OffsetRect (&r, -r.left, -r.top); @@ -8110,6 +8212,8 @@ mac_do_track_drag (DragTrackingMessage message, WindowPtr window, case kDragTrackingLeaveWindow: if (can_accept) { + struct frame *f = mac_window_to_frame (window); + HideDragHilite (theDrag); SetThemeCursor (kThemeArrowCursor); } @@ -8133,9 +8237,11 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, OSErr result; ItemReference theItem; HFSFlavor data; - FSRef fref; Size size = sizeof (HFSFlavor); + if (GetFrontWindowOfClass (kMovableModalWindowClass, false)) + return dragNotAcceptedErr; + drag_and_drop_file_list = Qnil; GetDragMouse (theDrag, &mouse, 0L); CountDragItems (theDrag, &items); @@ -8147,11 +8253,10 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, if (result == noErr) { #ifdef MAC_OSX - FSRef frref; -#else - Str255 path_name; + FSRef fref; #endif - Str255 unix_path_name; + char unix_path_name[MAXPATHLEN]; + GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L); #ifdef MAC_OSX /* Use Carbon routines, otherwise it converts the file name @@ -8159,9 +8264,8 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, 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)) + if (fsspec_to_posix_pathname (&data.fileSpec, unix_path_name, + sizeof (unix_path_name) - 1) == noErr) #endif /* x-dnd functions expect undecoded filenames. */ drag_and_drop_file_list = @@ -8169,8 +8273,6 @@ mac_do_receive_drag (WindowPtr window, void *handlerRefCon, strlen (unix_path_name)), drag_and_drop_file_list); } - else - continue; } /* If there are items in the list, construct an event and post it to the queue like an interrupt using kbd_buffer_store_event. */ @@ -8260,7 +8362,7 @@ profiler_exit_proc () hints and prompts in the minibuffer after the user stops typing for a wait, etc. */ -#if !TARGET_API_MAC_CARBON +#ifdef MAC_OS8 #undef main int main (void) @@ -8318,19 +8420,23 @@ main (void) #endif /* Table for translating Mac keycode to X keysym values. Contributed - by Sudhir Shenoy. */ + by Sudhir Shenoy. + Mapping for special keys is now identical to that in Apple X11 + except `clear' (-> ) on the KeyPad, `enter' (-> ) + on the right of the Cmd key on laptops, and fn + `enter' (-> + ). */ static unsigned char keycode_to_xkeysym_table[] = { /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/, - /*0x34*/ 0, 0x1b /*escape*/, 0, 0, + /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0, /*0x38*/ 0, 0, 0, 0, /*0x3C*/ 0, 0, 0, 0, /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/, - /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/, + /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x0b /*clear*/, /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/, /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0, @@ -8342,11 +8448,11 @@ static unsigned char keycode_to_xkeysym_table[] = { /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/, /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/, /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/, - /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/, + /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/, - /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/, - /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/, - /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/, + /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/, + /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/, + /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/, /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0 }; @@ -8481,10 +8587,13 @@ XTread_socket (sd, expected, hold_quit) { SInt32 delta; Point point; - WindowPtr window_ptr = front_emacs_window (); + struct frame *f = mac_focus_frame (dpyinfo); + WindowPtr window_ptr; - if (!IsValidWindowPtr (window_ptr)) + if (!f) { + /* Beep if wheel move occurs when all the frames + are invisible. */ SysBeep(1); break; } @@ -8500,6 +8609,7 @@ XTread_socket (sd, expected, hold_quit) 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); @@ -8558,14 +8668,14 @@ XTread_socket (sd, expected, hold_quit) 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 { @@ -8599,12 +8709,9 @@ XTread_socket (sd, expected, hold_quit) /* ticks to milliseconds */ if (dpyinfo->grabbed && tracked_scroll_bar -#if TARGET_API_MAC_CARBON - || ch != 0 -#else - || control_part_code != 0 -#endif - ) + /* control_part_code becomes kControlNoPart if + a progress indicator is clicked. */ + || ch != 0 && control_part_code != kControlNoPart) { struct scroll_bar *bar; @@ -8730,8 +8837,9 @@ XTread_socket (sd, expected, hold_quit) if (SendEventToEventTarget (eventRef, toolbox_dispatcher) != eventNotHandledErr) break; -#endif +#else do_window_update ((WindowPtr) er.message); +#endif break; case osEvt: @@ -8758,7 +8866,61 @@ XTread_socket (sd, expected, hold_quit) 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 @@ -8787,15 +8949,12 @@ XTread_socket (sd, expected, hold_quit) if (!is_emacs_window (window_ptr)) break; - f = mac_window_to_frame (window_ptr); - if ((er.modifiers & activeFlag) != 0) { /* A window has been activated */ Point mouse_loc = er.where; - x_new_focus_frame (dpyinfo, f); - activate_scroll_bars (f); + x_detect_focus_change (dpyinfo, &er, &inev); SetPortWindowPort (window_ptr); GlobalToLocal (&mouse_loc); @@ -8809,13 +8968,9 @@ XTread_socket (sd, expected, hold_quit) /* A window has been deactivated */ dpyinfo->grabbed = 0; - if (f == dpyinfo->x_focus_frame) - { - x_new_focus_frame (dpyinfo, 0); - deactivate_scroll_bars (f); - } - + 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 @@ -8841,7 +8996,7 @@ XTread_socket (sd, expected, hold_quit) int keycode = (er.message & keyCodeMask) >> 8; int xkeysym; -#if USE_CARBON_EVENTS +#if USE_CARBON_EVENTS && defined (MAC_OSX) /* When using Carbon Events, we need to pass raw keyboard events to the TSM ourselves. If TSM handles it, it will pass back noErr, otherwise it will pass back @@ -8856,13 +9011,31 @@ XTread_socket (sd, expected, hold_quit) 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); + + if (last_key_script != current_key_script) + { + struct input_event event; + + EVENT_INIT (event); + event.kind = LANGUAGE_CHANGE_EVENT; + event.arg = Qnil; + event.code = current_key_script; + kbd_buffer_store_event (&event); + count++; + } + last_key_script = current_key_script; + } ObscureCursor (); @@ -8897,95 +9070,32 @@ XTread_socket (sd, expected, hold_quit) 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; } } - /* If variable mac-convert-keyboard-input-to-latin-1 is - non-nil, convert non-ASCII characters typed at the Mac - keyboard (presumed to be in the Mac Roman encoding) to - iso-latin-1 encoding before they are passed to Emacs. - This enables the Mac keyboard to be used to enter - non-ASCII iso-latin-1 characters directly. */ - if (mac_keyboard_text_encoding != kTextEncodingMacRoman - && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128) - { - static TECObjectRef converter = NULL; - OSStatus the_err = noErr; - OSStatus convert_status = noErr; - - if (converter == NULL) - { - the_err = TECCreateConverter (&converter, - kTextEncodingMacRoman, - mac_keyboard_text_encoding); - current_mac_keyboard_text_encoding - = mac_keyboard_text_encoding; - } - else if (mac_keyboard_text_encoding - != current_mac_keyboard_text_encoding) - { - /* Free the converter for the current encoding - before creating a new one. */ - TECDisposeConverter (converter); - the_err = TECCreateConverter (&converter, - kTextEncodingMacRoman, - mac_keyboard_text_encoding); - current_mac_keyboard_text_encoding - = mac_keyboard_text_encoding; - } - - if (the_err == noErr) - { - unsigned char ch = inev.code; - ByteCount actual_input_length, actual_output_length; - unsigned char outbuf[32]; - - convert_status = TECConvertText (converter, &ch, 1, - &actual_input_length, - outbuf, 1, - &actual_output_length); - if (convert_status == noErr - && actual_input_length == 1 - && actual_output_length == 1) - inev.code = *outbuf; - - /* Reset internal states of the converter object. - If it fails, create another one. */ - convert_status = TECFlushText (converter, outbuf, - sizeof (outbuf), - &actual_output_length); - if (convert_status != noErr) - { - TECDisposeConverter (converter); - TECCreateConverter (&converter, - kTextEncodingMacRoman, - mac_keyboard_text_encoding); - } - } - } - #if USE_CARBON_EVENTS inev.modifiers = mac_event_to_emacs_modifiers (eventRef); #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; @@ -8998,22 +9108,10 @@ XTread_socket (sd, expected, hold_quit) 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); @@ -9030,10 +9128,12 @@ XTread_socket (sd, expected, hold_quit) 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 { @@ -9045,6 +9145,7 @@ XTread_socket (sd, expected, hold_quit) #else /* not TARGET_API_MAC_CARBON */ InvalRect (&(wp->portRect)); #endif /* not TARGET_API_MAC_CARBON */ +#endif } default: break; @@ -9150,12 +9251,12 @@ make_mac_terminal_frame (struct frame *f) f->output_data.mac->mouse_pixel = 0xff00ff; f->output_data.mac->cursor_foreground_pixel = 0x0000ff; - f->output_data.mac->text_cursor = GetCursor (iBeamCursor); - f->output_data.mac->nontext_cursor = &arrow_cursor; - f->output_data.mac->modeline_cursor = &arrow_cursor; - f->output_data.mac->hand_cursor = &arrow_cursor; - f->output_data.mac->hourglass_cursor = GetCursor (watchCursor); - f->output_data.mac->horizontal_drag_cursor = &arrow_cursor; + f->output_data.mac->text_cursor = kThemeIBeamCursor; + f->output_data.mac->nontext_cursor = kThemeArrowCursor; + f->output_data.mac->modeline_cursor = kThemeArrowCursor; + f->output_data.mac->hand_cursor = kThemePointingHandCursor; + f->output_data.mac->hourglass_cursor = kThemeWatchCursor; + f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor; FRAME_FONTSET (f) = -1; f->output_data.mac->explicit_parent = 0; @@ -9273,59 +9374,18 @@ mac_initialize_display_info () dpyinfo->mouse_face_hidden = 0; } -/* Create an xrdb-style database of resources to supercede registry settings. - The database is just a concatenation of C strings, finished by an additional - \0. The string are submitted to some basic normalization, so - [ *]option[ *]:[ *]value... - - becomes - - option:value... - - but any whitespace following value is not removed. */ - -static char * +static XrmDatabase mac_make_rdb (xrm_option) char *xrm_option; { - char *buffer = xmalloc (strlen (xrm_option) + 2); - char *current = buffer; - char ch; - int in_option = 1; - int before_value = 0; - - do { - ch = *xrm_option++; - - if (ch == '\n') - { - *current++ = '\0'; - in_option = 1; - before_value = 0; - } - else if (ch != ' ') - { - *current++ = ch; - if (in_option && (ch == ':')) - { - in_option = 0; - before_value = 1; - } - else if (before_value) - { - before_value = 0; - } - } - else if (!(in_option || before_value)) - { - *current++ = ch; - } - } while (ch); + XrmDatabase database; - *current = '\0'; + database = xrm_get_preference_database (NULL); + if (xrm_option) + xrm_merge_string_database (database, xrm_option); - return buffer; + return database; } struct mac_display_info * @@ -9351,14 +9411,15 @@ mac_term_init (display_name, xrm_option, resource_name) dpyinfo = &one_mac_display_info; - dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL; + dpyinfo->xrdb = mac_make_rdb (xrm_option); /* Put this display on the chain. */ dpyinfo->next = x_display_list; x_display_list = dpyinfo; /* Put it on x_display_name_list. */ - x_display_name_list = Fcons (Fcons (display_name, Qnil), + x_display_name_list = Fcons (Fcons (display_name, + Fcons (Qnil, dpyinfo->xrdb)), x_display_name_list); dpyinfo->name_list_element = XCAR (x_display_name_list); @@ -9564,7 +9625,7 @@ mac_check_for_quit_char () 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); @@ -9600,7 +9661,7 @@ static struct redisplay_interface x_redisplay_interface = 0, /* destroy_fringe_bitmap */ mac_per_char_metric, mac_encode_char, - NULL, /* mac_compute_glyph_string_overhangs */ + mac_compute_glyph_string_overhangs, x_draw_glyph_string, mac_define_frame_cursor, mac_clear_frame_area, @@ -9634,12 +9695,13 @@ mac_initialize () redeem_scroll_bar_hook = XTredeem_scroll_bar; judge_scroll_bars_hook = XTjudge_scroll_bars; - scroll_region_ok = 1; /* we'll scroll partial frames */ - char_ins_del_ok = 1; - line_ins_del_ok = 1; /* we'll just blt 'em */ - fast_clear_end_of_line = 1; /* X does this well */ - memory_below_frame = 0; /* we don't remember what scrolls - off the bottom */ + TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */ + TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1; + TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */ + TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */ + TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what + scrolls off the + bottom */ baud_rate = 19200; x_noop_count = 0; @@ -9690,7 +9752,7 @@ mac_initialize () #if TARGET_API_MAC_CARBON init_required_apple_events (); -#if USE_CARBON_EVENTS +#if USE_CARBON_EVENTS && defined (MAC_OSX) init_service_handler (); init_quit_char_handler (); @@ -9698,8 +9760,10 @@ mac_initialize () DisableMenuCommand (NULL, kHICommandQuit); +#ifdef MAC_OSX if (!inhibit_window_system) MakeMeTheFrontProcess (); +#endif #endif UNBLOCK_INPUT; } @@ -9755,10 +9819,6 @@ syms_of_macterm () 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; @@ -9787,18 +9847,18 @@ nil then the key will act as the normal Mac option modifier. */); 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. */); +useful for non-standard keyboard layouts. */); Vmac_reverse_ctrl_meta = Qnil; DEFVAR_LISP ("mac-emulate-three-button-mouse", &Vmac_emulate_three_button_mouse, doc: /* t means that when the option-key is held down while pressing the - mouse button, the click will register as mouse-2 and while the - command-key is held down, the click will register as mouse-3. - 'reverse means that the the option-key will register for mouse-3 - and the command-key will register for mouse-2. nil means that - not emulation should be done and the modifiers should be placed - on the mouse-1 event. */); +mouse button, the click will register as mouse-2 and while the +command-key is held down, the click will register as mouse-3. +'reverse means that the the option-key will register for mouse-3 +and the command-key will register for mouse-2. nil means that +no emulation should be done and the modifiers should be placed +on the mouse-1 event. */); Vmac_emulate_three_button_mouse = Qnil; #if USE_CARBON_EVENTS @@ -9817,22 +9877,14 @@ Toolbox for processing before Emacs sees it. */); doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac Toolbox for processing before Emacs sees it. */); Vmac_pass_control_to_system = 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 -Conversion Manager. Its value determines the encoding characters -typed at the Mac keyboard (presumed to be in the MacRoman encoding) -will convert into. E.g., if it is set to kTextEncodingMacRoman (0), -its default value, no conversion takes place. If it is set to -kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202), -characters typed on Mac keyboard are first converted into the -ISO Latin-1 or ISO Latin-2 encoding, respectively before being -passed to Emacs. Together with Emacs's set-keyboard-coding-system -command, this enables the Mac keyboard to be used to enter non-ASCII -characters directly. */); - mac_keyboard_text_encoding = kTextEncodingMacRoman; + DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics, + doc: /* If non-nil, allow anti-aliasing. +The text will be rendered using Core Graphics text rendering which +may anti-alias the text. */); + Vmac_use_core_graphics = Qnil; } /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b