Mercurial > emacs
diff src/mac.c @ 59146:9bde7721ad0f
* dispextern.h: Change HAVE_CARBON to MAC_OS.
(struct glyph_string): Likewise.
* emacs.c (main) [MAC_OS8]: Call mac_term_init instead of
mac_initialize.
* fileio.c (Fnext_read_file_uses_dialog_p, Fread_file_name):
Change TARGET_API_MAC_CARBON to HAVE_CARBON.
* fns.c (vector): Change MAC_OSX to MAC_OS.
* frame.c (x_set_frame_parameters, x_report_frame_params)
(x_set_fullscreen): Remove #ifndef HAVE_CARBON.
(x_set_border_width, Vdefault_frame_scroll_bars): Change
HAVE_CARBON to MAC_OS.
* image.c [MAC_OS]: Include sys/stat.h.
[MAC_OS && !MAC_OSX]: Include sys/param.h, ImageCompression.h, and
QuickTimeComponents.h.
* mac.c [!MAC_OSX] (mac_wait_next_event): Add extern.
[!MAC_OSX] (select): Use mac_wait_next_event.
[!MAC_OSX] (run_mac_command): Change EXEC_SUFFIXES to
Vexec_suffixes.
[!MAC_OSX] (select, run_mac_command): Change `#ifdef
TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
(mac_clear_font_name_table): Add extern.
(Fmac_clear_font_name_table): New defun.
(syms_of_mac): Defsubr it.
[MAC_OSX] (SELECT_POLLING_PERIOD_USEC): New define.
[MAC_OSX] (select_and_poll_event): New function.
[MAC_OSX] (sys_select): Use it.
[MAC_OSX && SELECT_USE_CFSOCKET] (socket_callback): New function.
[MAC_OSX && SELECT_USE_CFSOCKET]
(SELECT_TIMEOUT_THRESHOLD_RUNLOOP, EVENT_CLASS_SOCK): New defines.
[MAC_OSX] (sys_select) [SELECT_USE_CFSOCKET]: Use CFSocket and
RunLoop for simultaneously monitoring two kinds of inputs, window
events and process outputs, without periodically polling.
* macfns.c (mac_initialized): Remove extern.
(stricmp): Put in #if 0. All callers changed to use xstricmp in
xfaces.c.
(strnicmp): Decrement `n' at the end of each loop, not the
beginning.
(check_mac): Use the term "Mac native windows" instead of "Mac
OS".
(check_x_display_info, x_display_info_for_name): Sync with xfns.c.
(mac_get_rdb_resource): New function (from w32reg.c).
(x_get_string_resource): Use it.
(install_window_handler): Add extern.
(mac_window): New function.
(Fx_create_frame): Use it instead of make_mac_frame. Set
parameter for Qfullscreen. Call x_wm_set_size_hint.
(Fx_open_connection, Fx_close_connection): New defuns.
(syms_of_macfns): Defsubr them.
(x_create_tip_frame) [TARGET_API_MAC_CARBON]: Add
kWindowNoUpdatesAttribute to the window attribute.
(x_create_tip_frame) [!TARGET_API_MAC_CARBON]: Use NewCWindow.
(x_create_tip_frame): Don't call ShowWindow.
(Fx_show_tip): Call ShowWindow.
(Fx_file_dialog): Change `#ifdef TARGET_API_MAC_CARBON' to `#if
TARGET_API_MAC_CARBON'.
(mac_frame_parm_handlers): Set handlers for Qfullscreen.
(syms_of_macfns) [MAC_OSX]: Initialize mac_in_use to 0.
* macgui.h [!MAC_OSX]: Don't include Controls.h. Include
Windows.h.
(Window): Typedef to WindowPtr and move outside `#if
TARGET_API_MAC_CARBON'.
(XSizeHints): New struct.
* macterm.c (x_update_begin, x_update_end)
[TARGET_API_MAC_CARBON]: Disable screen updates during update of a
frame.
(x_draw_glyph_string_background, x_draw_glyph_string_foreground)
[MAC_OS8]: Use XDrawImageString/XDrawImageString16.
(construct_mouse_click): Put in #if 0.
(x_check_fullscreen, x_check_fullscreen_move): Remove decls.
(x_scroll_bar_create, x_scroll_bar_handle_click): Change `#ifdef
TARGET_API_MAC_CARBON' to `#if TARGET_API_MAC_CARBON'.
(activate_scroll_bars, deactivate_scroll_bars)
[!TARGET_API_MAC_CARBON]: Use ActivateControl/DeactivateControl.
(x_make_frame_visible) [TARGET_API_MAC_CARBON]: Reposition window
if the position is neither user-specified nor program-specified.
(x_free_frame_resources): Free size_hints.
(x_wm_set_size_hint): Allocate size_hints if needed. Set
size_hints.
(mac_clear_font_name_table): New function.
(mac_do_list_fonts): Initialize font_name_table if needed.
(x_list_fonts): Don't initialize font_name_table. Add BLOCK_INPUT
around mac_do_list_fonts.
(mac_unload_font): New function.
(x_load_font): Add BLOCK_INPUT around XLoadQueryFont.
(init_mac_drag_n_drop, mac_do_receive_drag): Enclose declarations
and definitions with #if TARGET_API_MAC_CARBON.
[USE_CARBON_EVENTS] (mac_handle_window_event): Add decl.
(install_window_handler): Add decl.
(do_window_update): Add BeginUpdate/EndUpdate for the tooltip
window. Use UpdateControls. Get the rectangle that should be
updated and restrict the target of expose_frame to it.
(do_grow_window): Set minimum height/width according to
size_hints.
(do_grow_window) [TARGET_API_MAC_CARBON]: Use ResizeWindow.
(do_zoom_window): Don't use x_set_window_size.
[USE_CARBON_EVENTS] (mac_handle_window_event): New function.
(install_window_handler): New function.
[!USE_CARBON_EVENTS] (mouse_region): New variable.
[!USE_CARBON_EVENTS] (mac_wait_next_event): New function.
(XTread_socket) [USE_CARBON_EVENTS]: Move call to
GetEventDispatcherTarget inside BLOCK_INPUT.
(XTread_socket) [!USE_CARBON_EVENTS]: Use mac_wait_next_event.
Update mouse_region when mouse is moved.
(make_mac_frame): Remove.
(make_mac_terminal_frame): Put in #ifdef MAC_OS8. Initialize
mouse pointer shapes. Change values of f->left_pos and
f->top_pos. Don't use make_mac_frame. Use NewCWindow. Don't
call ShowWindow.
(mac_initialize_display_info) [MAC_OSX]: Create mac_id_name from
Vinvocation_name and Vsystem_name.
(mac_make_rdb): New function (from w32term.c).
(mac_term_init): Use it. Add BLOCK_INPUT. Error if display has
already been opened. Don't pass argument to
mac_initialize_display_info. Don't set dpyinfo->height/width.
Add entries to x_display_list and x_display_name_list.
(x_delete_display): New function.
(mac_initialize): Don't call mac_initialize_display_info.
(syms_of_macterm) [!MAC_OSX]: Don't call Fprovide.
* macterm.h (check_mac): Add extern.
(struct mac_output): New member size_hints.
(FRAME_SIZE_HINTS): New macro.
(mac_unload_font): Add extern.
* xdisp.c (expose_window, expose_frame): Remove kludges for Mac.
* xfaces.c (clear_font_table) [MAC_OS]: call mac_unload_font.
| author | Steven Tamm <steventamm@mac.com> |
|---|---|
| date | Mon, 27 Dec 2004 17:27:30 +0000 |
| parents | 4ad0594e1ac4 |
| children | 5ae033db673f 95879cc1ed20 |
line wrap: on
line diff
--- a/src/mac.c Mon Dec 27 17:23:53 2004 +0000 +++ b/src/mac.c Mon Dec 27 17:27:30 2004 +0000 @@ -845,6 +845,8 @@ } +extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean); + int select (n, rfds, wfds, efds, timeout) int n; @@ -853,49 +855,24 @@ SELECT_TYPE *efds; struct timeval *timeout; { -#ifdef TARGET_API_MAC_CARBON +#if TARGET_API_MAC_CARBON return 1; #else /* not TARGET_API_MAC_CARBON */ - EMACS_TIME end_time, now; EventRecord e; + UInt32 sleep_time = EMACS_SECS (*timeout) * 60 + + ((EMACS_USECS (*timeout) * 60) / 1000000); /* Can only handle wait for keyboard input. */ if (n > 1 || wfds || efds) return -1; - EMACS_GET_TIME (end_time); - EMACS_ADD_TIME (end_time, end_time, *timeout); - - do - { - /* Also return true if an event other than a keyDown has - occurred. This causes kbd_buffer_get_event in keyboard.c to - call read_avail_input which in turn calls XTread_socket to - poll for these events. Otherwise these never get processed - except but a very slow poll timer. */ - if (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e)) - return 1; - - /* Also check movement of the mouse. */ - { - Point mouse_pos; - static Point old_mouse_pos = {-1, -1}; - - GetMouse (&mouse_pos); - if (!EqualPt (mouse_pos, old_mouse_pos)) - { - old_mouse_pos = mouse_pos; - return 1; - } - } - - WaitNextEvent (0, &e, 1UL, NULL); /* Accept no event; wait 1 - tic. by T.I. */ - - EMACS_GET_TIME (now); - EMACS_SUB_TIME (now, end_time, now); - } - while (!EMACS_TIME_NEG_P (now)); + /* Also return true if an event other than a keyDown has occurred. + This causes kbd_buffer_get_event in keyboard.c to call + read_avail_input which in turn calls XTread_socket to poll for + these events. Otherwise these never get processed except but a + very slow poll timer. */ + if (FD_ISSET (0, rfds) && mac_wait_next_event (&e, sleep_time, false)) + return 1; return 0; #endif /* not TARGET_API_MAC_CARBON */ @@ -1996,7 +1973,7 @@ const char *workdir; const char *infn, *outfn, *errfn; { -#ifdef TARGET_API_MAC_CARBON +#if TARGET_API_MAC_CARBON return -1; #else /* not TARGET_API_MAC_CARBON */ char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1]; @@ -2081,7 +2058,7 @@ strcat (t, newargv[0]); #endif /* 0 */ Lisp_Object path; - openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path, + openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path, make_number (X_OK)); if (NILP (path)) @@ -2793,17 +2770,98 @@ return Qnil; } +extern void mac_clear_font_name_table P_ ((void)); + +DEFUN ("mac-clear-font-name-table", Fmac_clear_font_name_table, Smac_clear_font_name_table, 0, 0, 0, + doc: /* Clear the font name table. */) + () +{ + check_mac (); + mac_clear_font_name_table (); + return Qnil; +} + #ifdef MAC_OSX #undef select extern int inhibit_window_system; extern int noninteractive; -/* When Emacs is started from the Finder, SELECT always immediately - returns as if input is present when file descriptor 0 is polled for - input. Strangely, when Emacs is run as a GUI application from the - command line, it blocks in the same situation. This `wrapper' of - the system call SELECT corrects this discrepancy. */ +/* Unlike in X11, window events in Carbon do not come from sockets. + So we cannot simply use `select' to monitor two kinds of inputs: + window events and process outputs. We emulate such functionality + by regarding fd 0 as the window event channel and simultaneously + monitoring both kinds of input channels. It is implemented by + dividing into some cases: + 1. The window event channel is not involved. + -> Use `select'. + 2. Sockets are not involved. + -> Use ReceiveNextEvent. + 3. [If SELECT_USE_CFSOCKET is defined] + Only the window event channel and socket read channels are + involved, and timeout is not too short (greater than + SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds). + -> Create CFSocket for each socket and add it into the current + event RunLoop so that an `ready-to-read' event can be posted + to the event queue that is also used for window events. Then + ReceiveNextEvent can wait for both kinds of inputs. + 4. Otherwise. + -> Periodically poll the window input channel while repeatedly + executing `select' with a short timeout + (SELECT_POLLING_PERIOD_USEC microseconds). */ + +#define SELECT_POLLING_PERIOD_USEC 20000 +#ifdef SELECT_USE_CFSOCKET +#define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2 +#define EVENT_CLASS_SOCK 'Sock' + +static void +socket_callback (s, type, address, data, info) + CFSocketRef s; + CFSocketCallBackType type; + CFDataRef address; + const void *data; + void *info; +{ + EventRef event; + + CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event); + PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard); + ReleaseEvent (event); +} +#endif /* SELECT_USE_CFSOCKET */ + +static int +select_and_poll_event (n, rfds, wfds, efds, timeout) + int n; + SELECT_TYPE *rfds; + SELECT_TYPE *wfds; + SELECT_TYPE *efds; + struct timeval *timeout; +{ + int r; + OSErr err; + + r = select (n, rfds, wfds, efds, timeout); + if (r != -1) + { + BLOCK_INPUT; + err = ReceiveNextEvent (0, NULL, kEventDurationNoWait, + kEventLeaveInQueue, NULL); + UNBLOCK_INPUT; + if (err == noErr) + { + FD_SET (0, rfds); + r++; + } + } + return r; +} + +#ifndef MAC_OS_X_VERSION_10_2 +#undef SELECT_INVALIDATE_CFSOCKET +#endif + int sys_select (n, rfds, wfds, efds, timeout) int n; @@ -2813,91 +2871,182 @@ struct timeval *timeout; { OSErr err; - EMACS_TIME end_time, now, remaining_time; - + int i, r; + EMACS_TIME select_timeout; + if (inhibit_window_system || noninteractive || rfds == NULL || !FD_ISSET (0, rfds)) return select (n, rfds, wfds, efds, timeout); - + + FD_CLR (0, rfds); + if (wfds == NULL && efds == NULL) { - int i; + int nsocks = 0; + SELECT_TYPE orfds = *rfds; + + EventTimeout timeout_sec = + (timeout + ? (EMACS_SECS (*timeout) * kEventDurationSecond + + EMACS_USECS (*timeout) * kEventDurationMicrosecond) + : kEventDurationForever); for (i = 1; i < n; i++) if (FD_ISSET (i, rfds)) - break; - if (i == n) - { - EventTimeout timeout_sec = - (timeout - ? (EMACS_SECS (*timeout) * kEventDurationSecond - + EMACS_USECS (*timeout) * kEventDurationMicrosecond) - : kEventDurationForever); - + nsocks++; + + if (nsocks == 0) + { BLOCK_INPUT; err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL); UNBLOCK_INPUT; if (err == noErr) { - FD_ZERO (rfds); FD_SET (0, rfds); return 1; } else return 0; } - } - - if (timeout) - { - remaining_time = *timeout; - EMACS_GET_TIME (now); - EMACS_ADD_TIME (end_time, now, remaining_time); + + /* Avoid initial overhead of RunLoop setup for the case that + some input is already available. */ + EMACS_SET_SECS_USECS (select_timeout, 0, 0); + r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); + if (r != 0 || timeout_sec == 0.0) + return r; + + *rfds = orfds; + +#ifdef SELECT_USE_CFSOCKET + if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) + goto poll_periodically; + + { + CFRunLoopRef runloop = + (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); + EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}}; +#ifdef SELECT_INVALIDATE_CFSOCKET + CFSocketRef *shead, *s; +#else + CFRunLoopSourceRef *shead, *s; +#endif + + BLOCK_INPUT; + +#ifdef SELECT_INVALIDATE_CFSOCKET + shead = xmalloc (sizeof (CFSocketRef) * nsocks); +#else + shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks); +#endif + s = shead; + for (i = 1; i < n; i++) + if (FD_ISSET (i, rfds)) + { + CFSocketRef socket = + CFSocketCreateWithNative (NULL, i, kCFSocketReadCallBack, + socket_callback, NULL); + CFRunLoopSourceRef source = + CFSocketCreateRunLoopSource (NULL, socket, 0); + +#ifdef SELECT_INVALIDATE_CFSOCKET + CFSocketSetSocketFlags (socket, 0); +#endif + CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); +#ifdef SELECT_INVALIDATE_CFSOCKET + CFRelease (source); + *s = socket; +#else + CFRelease (socket); + *s = source; +#endif + s++; + } + + err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL); + + do + { + --s; +#ifdef SELECT_INVALIDATE_CFSOCKET + CFSocketInvalidate (*s); +#else + CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode); +#endif + CFRelease (*s); + } + while (s != shead); + + xfree (shead); + + if (err) + { + FD_ZERO (rfds); + r = 0; + } + else + { + FlushEventsMatchingListFromQueue (GetCurrentEventQueue (), + GetEventTypeCount (specs), + specs); + EMACS_SET_SECS_USECS (select_timeout, 0, 0); + r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); + } + + UNBLOCK_INPUT; + + return r; + } +#endif /* SELECT_USE_CFSOCKET */ } - FD_CLR (0, rfds); - do - { - EMACS_TIME select_timeout; - SELECT_TYPE orfds = *rfds; - int r; - - EMACS_SET_SECS_USECS (select_timeout, 0, 20000); - - if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) - select_timeout = remaining_time; - - r = select (n, &orfds, wfds, efds, &select_timeout); - BLOCK_INPUT; - err = ReceiveNextEvent (0, NULL, kEventDurationNoWait, - kEventLeaveInQueue, NULL); - UNBLOCK_INPUT; - if (r > 0) - { - *rfds = orfds; - if (err == noErr) - { - FD_SET (0, rfds); - r++; - } + + poll_periodically: + { + EMACS_TIME end_time, now, remaining_time; + SELECT_TYPE orfds = *rfds, owfds, oefds; + + if (wfds) + owfds = *wfds; + if (efds) + oefds = *efds; + if (timeout) + { + remaining_time = *timeout; + EMACS_GET_TIME (now); + EMACS_ADD_TIME (end_time, now, remaining_time); + } + + do + { + EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC); + if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) + select_timeout = remaining_time; + r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); + if (r != 0) return r; - } - else if (err == noErr) - { - FD_ZERO (rfds); - FD_SET (0, rfds); - return 1; - } - - if (timeout) - { - EMACS_GET_TIME (now); - EMACS_SUB_TIME (remaining_time, end_time, now); - } - } - while (!timeout || EMACS_TIME_LT (now, end_time)); - - return 0; + + *rfds = orfds; + if (wfds) + *wfds = owfds; + if (efds) + *efds = oefds; + + if (timeout) + { + EMACS_GET_TIME (now); + EMACS_SUB_TIME (remaining_time, end_time, now); + } + } + while (!timeout || EMACS_TIME_LT (now, end_time)); + + FD_ZERO (rfds); + if (wfds) + FD_ZERO (wfds); + if (efds) + FD_ZERO (efds); + return 0; + } } /* Set up environment variables so that Emacs can correctly find its @@ -3043,6 +3192,7 @@ defsubr (&Smac_paste_function); defsubr (&Smac_cut_function); defsubr (&Sx_selection_exists_p); + defsubr (&Smac_clear_font_name_table); defsubr (&Sdo_applescript); defsubr (&Smac_file_name_to_posix);
