1 /* Functions for GUI implemented with (HI)Toolbox on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004,
3 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
27 #include "blockinput.h"
31 #if !TARGET_API_MAC_CARBON
32 #include <Quickdraw.h>
33 #include <ToolUtils.h>
37 #include <Resources.h>
39 #include <TextUtils.h>
44 #if defined (__MRC__) || (__MSL__ >= 0x6000)
45 #include <ControlDefinitions.h>
51 #endif /* not TARGET_API_MAC_CARBON */
56 #include "dispextern.h"
58 #include "termhooks.h"
63 #include <sys/param.h>
70 /************************************************************************
72 ************************************************************************/
74 /* The difference in pixels between the top left corner of the
75 Emacs window (including possible window manager decorations)
76 and FRAME_MAC_WINDOW (f). */
77 #define FRAME_OUTER_TO_INNER_DIFF_X(f) ((f)->x_pixels_diff)
78 #define FRAME_OUTER_TO_INNER_DIFF_Y(f) ((f)->y_pixels_diff)
80 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
83 mac_alert_sound_play ()
85 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
93 /************************************************************************
95 ************************************************************************/
97 extern struct frame
*mac_focus_frame
P_ ((struct mac_display_info
*));
98 extern void do_keystroke
P_ ((EventKind
, unsigned char, UInt32
, UInt32
,
99 unsigned long, struct input_event
*));
100 extern UInt32 mac_mapped_modifiers
P_ ((UInt32
, UInt32
));
101 #if TARGET_API_MAC_CARBON
102 extern int mac_to_emacs_modifiers
P_ ((UInt32
, UInt32
));
104 extern int mac_to_emacs_modifiers
P_ ((EventModifiers
, EventModifiers
));
107 #if TARGET_API_MAC_CARBON
108 /* Points to the variable `inev' in the function XTread_socket. It is
109 used for passing an input event to the function back from
110 Carbon/Apple event handlers. */
111 static struct input_event
*read_socket_inev
= NULL
;
113 extern const unsigned char keycode_to_xkeysym_table
[];
114 extern EMACS_INT extra_keyboard_modifiers
;
116 extern Lisp_Object Qhi_command
;
118 static TSMDocumentID tsm_document_id
;
119 extern Lisp_Object Qtext_input
;
120 extern Lisp_Object Qupdate_active_input_area
, Qunicode_for_key_event
;
121 extern Lisp_Object Vmac_ts_active_input_overlay
;
122 extern Lisp_Object Qbefore_string
;
123 extern Lisp_Object Vmac_ts_script_language_on_focus
;
124 extern Lisp_Object saved_ts_script_language_on_focus
;
127 static int mac_event_to_emacs_modifiers
P_ ((EventRef
));
128 static OSStatus install_menu_target_item_handler
P_ ((void));
130 static OSStatus install_service_handler
P_ ((void));
133 extern OSStatus mac_store_event_ref_as_apple_event
P_ ((AEEventClass
, AEEventID
,
137 const EventParamName
*,
138 const EventParamType
*));
141 extern OSStatus mac_restore_keyboard_input_source
P_ ((void));
142 extern void mac_save_keyboard_input_source
P_ ((void));
149 err
= ActivateTSMDocument (tsm_document_id
);
151 err
= mac_restore_keyboard_input_source ();
161 mac_save_keyboard_input_source ();
162 err
= DeactivateTSMDocument (tsm_document_id
);
171 static InterfaceTypeList types
= {kUnicodeDocument
};
173 static InterfaceTypeList types
= {kTextService
};
176 NewTSMDocument (sizeof (types
) / sizeof (types
[0]), types
,
177 &tsm_document_id
, 0);
179 #endif /* USE_MAC_TSM */
181 static pascal OSStatus
182 mac_handle_keyboard_event (next_handler
, event
, data
)
183 EventHandlerCallRef next_handler
;
187 OSStatus err
, result
= eventNotHandledErr
;
188 UInt32 event_kind
, key_code
, modifiers
;
189 unsigned char char_code
;
191 event_kind
= GetEventKind (event
);
194 case kEventRawKeyDown
:
195 case kEventRawKeyRepeat
:
197 /* When using Carbon Events, we need to pass raw keyboard events
198 to the TSM ourselves. If TSM handles it, it will pass back
199 noErr, otherwise it will pass back "eventNotHandledErr" and
200 we can process it normally. */
201 result
= CallNextEventHandler (next_handler
, event
);
202 if (result
!= eventNotHandledErr
)
205 if (read_socket_inev
== NULL
)
209 if (read_socket_inev
->kind
!= NO_EVENT
)
216 if (event_kind
== kEventRawKeyUp
)
219 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
221 sizeof (char), NULL
, &char_code
);
225 err
= GetEventParameter (event
, kEventParamKeyCode
,
227 sizeof (UInt32
), NULL
, &key_code
);
231 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
233 sizeof (UInt32
), NULL
, &modifiers
);
237 do_keystroke ((event_kind
== kEventRawKeyDown
? keyDown
: autoKey
),
238 char_code
, key_code
, modifiers
,
240 (GetEventTime (event
) / kEventDurationMillisecond
)),
252 static pascal OSStatus
253 mac_handle_command_event (next_handler
, event
, data
)
254 EventHandlerCallRef next_handler
;
258 OSStatus err
, result
= eventNotHandledErr
;
260 static const EventParamName names
[] =
261 {kEventParamDirectObject
, kEventParamKeyModifiers
};
262 static const EventParamType types
[] =
263 {typeHICommand
, typeUInt32
};
264 int num_params
= sizeof (names
) / sizeof (names
[0]);
266 err
= GetEventParameter (event
, kEventParamDirectObject
, typeHICommand
,
267 NULL
, sizeof (HICommand
), NULL
, &command
);
269 return eventNotHandledErr
;
271 switch (GetEventKind (event
))
273 case kEventCommandProcess
:
274 result
= CallNextEventHandler (next_handler
, event
);
275 if (result
!= eventNotHandledErr
)
278 err
= GetEventParameter (event
, kEventParamDirectObject
,
280 sizeof (HICommand
), NULL
, &command
);
282 if (err
!= noErr
|| command
.commandID
== 0)
285 /* A HI command event is mapped to an Apple event whose event
286 class symbol is `hi-command' and event ID is its command
288 err
= mac_store_event_ref_as_apple_event (0, command
.commandID
,
303 static pascal OSStatus
304 mac_handle_mouse_event (next_handler
, event
, data
)
305 EventHandlerCallRef next_handler
;
309 OSStatus err
, result
= eventNotHandledErr
;
311 switch (GetEventKind (event
))
313 case kEventMouseWheelMoved
:
317 EventMouseWheelAxis axis
;
321 result
= CallNextEventHandler (next_handler
, event
);
322 if (result
!= eventNotHandledErr
|| read_socket_inev
== NULL
)
325 f
= mac_focus_frame (&one_mac_display_info
);
327 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
,
328 NULL
, sizeof (WindowRef
), NULL
, &wp
);
330 || wp
!= FRAME_MAC_WINDOW (f
))
333 err
= GetEventParameter (event
, kEventParamMouseWheelAxis
,
334 typeMouseWheelAxis
, NULL
,
335 sizeof (EventMouseWheelAxis
), NULL
, &axis
);
336 if (err
!= noErr
|| axis
!= kEventMouseWheelAxisY
)
339 err
= GetEventParameter (event
, kEventParamMouseLocation
,
340 typeQDPoint
, NULL
, sizeof (Point
),
345 point
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
346 point
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
347 if (point
.h
< 0 || point
.v
< 0
348 || EQ (window_from_coordinates (f
, point
.h
, point
.v
, 0, 0, 0, 1),
352 err
= GetEventParameter (event
, kEventParamMouseWheelDelta
,
353 typeSInt32
, NULL
, sizeof (SInt32
),
358 read_socket_inev
->kind
= WHEEL_EVENT
;
359 read_socket_inev
->code
= 0;
360 read_socket_inev
->modifiers
=
361 (mac_event_to_emacs_modifiers (event
)
362 | ((delta
< 0) ? down_modifier
: up_modifier
));
363 XSETINT (read_socket_inev
->x
, point
.h
);
364 XSETINT (read_socket_inev
->y
, point
.v
);
365 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
379 static pascal OSStatus
380 mac_handle_text_input_event (next_handler
, event
, data
)
381 EventHandlerCallRef next_handler
;
385 OSStatus err
, result
;
386 Lisp_Object id_key
= Qnil
;
388 const EventParamName
*names
;
389 const EventParamType
*types
;
390 static UInt32 seqno_uaia
= 0;
391 static const EventParamName names_uaia
[] =
392 {kEventParamTextInputSendComponentInstance
,
393 kEventParamTextInputSendRefCon
,
394 kEventParamTextInputSendSLRec
,
395 kEventParamTextInputSendFixLen
,
396 kEventParamTextInputSendText
,
397 kEventParamTextInputSendUpdateRng
,
398 kEventParamTextInputSendHiliteRng
,
399 kEventParamTextInputSendClauseRng
,
400 kEventParamTextInputSendPinRng
,
401 kEventParamTextInputSendTextServiceEncoding
,
402 kEventParamTextInputSendTextServiceMacEncoding
,
403 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
};
404 static const EventParamType types_uaia
[] =
405 {typeComponentInstance
,
421 static const EventParamName names_ufke
[] =
422 {kEventParamTextInputSendComponentInstance
,
423 kEventParamTextInputSendRefCon
,
424 kEventParamTextInputSendSLRec
,
425 kEventParamTextInputSendText
};
426 static const EventParamType types_ufke
[] =
427 {typeComponentInstance
,
432 result
= CallNextEventHandler (next_handler
, event
);
433 if (result
!= eventNotHandledErr
)
436 switch (GetEventKind (event
))
438 case kEventTextInputUpdateActiveInputArea
:
439 id_key
= Qupdate_active_input_area
;
440 num_params
= sizeof (names_uaia
) / sizeof (names_uaia
[0]);
443 SetEventParameter (event
, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER
,
444 typeUInt32
, sizeof (UInt32
), &seqno_uaia
);
449 case kEventTextInputUnicodeForKeyEvent
:
452 UInt32 actual_size
, modifiers
, key_code
;
454 err
= GetEventParameter (event
, kEventParamTextInputSendKeyboardEvent
,
455 typeEventRef
, NULL
, sizeof (EventRef
), NULL
,
458 err
= GetEventParameter (kbd_event
, kEventParamKeyModifiers
,
460 sizeof (UInt32
), NULL
, &modifiers
);
462 err
= GetEventParameter (kbd_event
, kEventParamKeyCode
,
463 typeUInt32
, NULL
, sizeof (UInt32
),
465 if (err
== noErr
&& mac_mapped_modifiers (modifiers
, key_code
))
466 /* There're mapped modifier keys. Process it in
470 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
471 typeUnicodeText
, NULL
, 0, &actual_size
,
473 if (err
== noErr
&& actual_size
== sizeof (UniChar
))
477 err
= GetEventParameter (kbd_event
, kEventParamKeyUnicodes
,
478 typeUnicodeText
, NULL
,
479 sizeof (UniChar
), NULL
, &code
);
480 if (err
== noErr
&& code
< 0x80)
482 /* ASCII character. Process it in do_keystroke. */
483 if (read_socket_inev
&& code
>= 0x20 && code
<= 0x7e
484 && !(key_code
<= 0x7f
485 && keycode_to_xkeysym_table
[key_code
]))
487 struct frame
*f
= mac_focus_frame (&one_mac_display_info
);
489 read_socket_inev
->kind
= ASCII_KEYSTROKE_EVENT
;
490 read_socket_inev
->code
= code
;
491 read_socket_inev
->modifiers
=
492 mac_to_emacs_modifiers (modifiers
, 0);
493 read_socket_inev
->modifiers
|=
494 (extra_keyboard_modifiers
495 & (meta_modifier
| alt_modifier
496 | hyper_modifier
| super_modifier
));
497 XSETFRAME (read_socket_inev
->frame_or_window
, f
);
504 /* Non-ASCII keystrokes without mapped modifiers are
505 processed at the Lisp level. */
506 id_key
= Qunicode_for_key_event
;
507 num_params
= sizeof (names_ufke
) / sizeof (names_ufke
[0]);
515 case kEventTextInputOffsetToPos
:
521 if (!OVERLAYP (Vmac_ts_active_input_overlay
))
524 /* Strictly speaking, this is not always correct because
525 previous events may change some states about display. */
526 if (!NILP (Foverlay_get (Vmac_ts_active_input_overlay
, Qbefore_string
)))
528 /* Active input area is displayed around the current point. */
529 f
= SELECTED_FRAME ();
530 w
= XWINDOW (f
->selected_window
);
532 else if (WINDOWP (echo_area_window
))
534 /* Active input area is displayed in the echo area. */
535 w
= XWINDOW (echo_area_window
);
536 f
= WINDOW_XFRAME (w
);
541 p
.h
= (WINDOW_TO_FRAME_PIXEL_X (w
, w
->cursor
.x
)
542 + WINDOW_LEFT_FRINGE_WIDTH (w
)
543 + f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
));
544 p
.v
= (WINDOW_TO_FRAME_PIXEL_Y (w
, w
->cursor
.y
)
545 + FONT_BASE (FRAME_FONT (f
))
546 + f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
));
547 err
= SetEventParameter (event
, kEventParamTextInputReplyPoint
,
548 typeQDPoint
, sizeof (typeQDPoint
), &p
);
559 err
= mac_store_event_ref_as_apple_event (0, 0, Qtext_input
, id_key
,
567 install_application_handler ()
569 OSStatus err
= noErr
;
573 static const EventTypeSpec specs
[] =
574 {{kEventClassKeyboard
, kEventRawKeyDown
},
575 {kEventClassKeyboard
, kEventRawKeyRepeat
},
576 {kEventClassKeyboard
, kEventRawKeyUp
}};
578 err
= InstallApplicationEventHandler (NewEventHandlerUPP
579 (mac_handle_keyboard_event
),
580 GetEventTypeCount (specs
),
586 static const EventTypeSpec specs
[] =
587 {{kEventClassCommand
, kEventCommandProcess
}};
589 err
= InstallApplicationEventHandler (NewEventHandlerUPP
590 (mac_handle_command_event
),
591 GetEventTypeCount (specs
),
597 static const EventTypeSpec specs
[] =
598 {{kEventClassMouse
, kEventMouseWheelMoved
}};
600 err
= InstallApplicationEventHandler (NewEventHandlerUPP
601 (mac_handle_mouse_event
),
602 GetEventTypeCount (specs
),
609 static const EventTypeSpec spec
[] =
610 {{kEventClassTextInput
, kEventTextInputUpdateActiveInputArea
},
611 {kEventClassTextInput
, kEventTextInputUnicodeForKeyEvent
},
612 {kEventClassTextInput
, kEventTextInputOffsetToPos
}};
614 err
= InstallApplicationEventHandler (NewEventHandlerUPP
615 (mac_handle_text_input_event
),
616 GetEventTypeCount (spec
),
622 err
= install_menu_target_item_handler ();
626 err
= install_service_handler ();
631 #endif /* TARGET_API_MAC_CARBON */
634 /************************************************************************
636 ************************************************************************/
638 #define DEFAULT_NUM_COLS 80
640 #define MIN_DOC_SIZE 64
641 #define MAX_DOC_SIZE 32767
644 static OSErr install_drag_handler
P_ ((WindowRef
));
645 static void remove_drag_handler
P_ ((WindowRef
));
648 static void mac_prepare_for_quickdraw
P_ ((struct frame
*));
651 extern void mac_handle_visibility_change
P_ ((struct frame
*));
652 extern void mac_handle_origin_change
P_ ((struct frame
*));
653 extern void mac_handle_size_change
P_ ((struct frame
*, int, int));
655 #if TARGET_API_MAC_CARBON
657 extern Lisp_Object Qwindow
;
658 extern Lisp_Object Qtoolbar_switch_mode
;
663 do_window_update (WindowRef win
)
665 struct frame
*f
= mac_window_to_frame (win
);
669 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
671 if (win
!= tip_window
)
673 if (f
->async_visible
== 0)
675 /* Update events may occur when a frame gets iconified. */
677 f
->async_visible
= 1;
678 f
->async_iconified
= 0;
679 SET_FRAME_GARBAGED (f
);
685 #if TARGET_API_MAC_CARBON
686 RgnHandle region
= NewRgn ();
688 GetPortVisibleRegion (GetWindowPort (win
), region
);
689 GetRegionBounds (region
, &r
);
690 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
692 mac_prepare_for_quickdraw (f
);
694 UpdateControls (win
, region
);
697 r
= (*win
->visRgn
)->rgnBBox
;
698 expose_frame (f
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
);
699 UpdateControls (win
, win
->visRgn
);
708 is_emacs_window (WindowRef win
)
710 Lisp_Object tail
, frame
;
715 FOR_EACH_FRAME (tail
, frame
)
716 if (FRAME_MAC_P (XFRAME (frame
)))
717 if (FRAME_MAC_WINDOW (XFRAME (frame
)) == win
)
723 /* Handle drags in size box. Based on code contributed by Ben
724 Mesander and IM - Window Manager A. */
727 do_grow_window (w
, e
)
729 const EventRecord
*e
;
732 int rows
, columns
, width
, height
;
733 struct frame
*f
= mac_window_to_frame (w
);
734 XSizeHints
*size_hints
= FRAME_SIZE_HINTS (f
);
735 int min_width
= MIN_DOC_SIZE
, min_height
= MIN_DOC_SIZE
;
736 #if TARGET_API_MAC_CARBON
742 if (size_hints
->flags
& PMinSize
)
744 min_width
= size_hints
->min_width
;
745 min_height
= size_hints
->min_height
;
747 SetRect (&limit_rect
, min_width
, min_height
, MAX_DOC_SIZE
, MAX_DOC_SIZE
);
749 #if TARGET_API_MAC_CARBON
750 if (!ResizeWindow (w
, e
->where
, &limit_rect
, &new_rect
))
752 height
= new_rect
.bottom
- new_rect
.top
;
753 width
= new_rect
.right
- new_rect
.left
;
755 grow_size
= GrowWindow (w
, e
->where
, &limit_rect
);
756 /* see if it really changed size */
759 height
= HiWord (grow_size
);
760 width
= LoWord (grow_size
);
763 if (width
!= FRAME_PIXEL_WIDTH (f
)
764 || height
!= FRAME_PIXEL_HEIGHT (f
))
766 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
767 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
769 x_set_window_size (f
, 0, columns
, rows
);
773 #if TARGET_API_MAC_CARBON
775 mac_get_ideal_size (f
)
778 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
779 WindowRef w
= FRAME_MAC_WINDOW (f
);
782 int height
, width
, columns
, rows
;
784 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
785 ideal_size
.v
= dpyinfo
->height
;
786 IsWindowInStandardState (w
, &ideal_size
, &standard_rect
);
787 /* Adjust the standard size according to character boundaries. */
788 width
= standard_rect
.right
- standard_rect
.left
;
789 height
= standard_rect
.bottom
- standard_rect
.top
;
790 columns
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f
, width
);
791 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, height
);
792 ideal_size
.h
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, columns
);
793 ideal_size
.v
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
798 static pascal OSStatus
799 mac_handle_window_event (next_handler
, event
, data
)
800 EventHandlerCallRef next_handler
;
805 OSStatus err
, result
= eventNotHandledErr
;
808 XSizeHints
*size_hints
;
810 err
= GetEventParameter (event
, kEventParamDirectObject
, typeWindowRef
,
811 NULL
, sizeof (WindowRef
), NULL
, &wp
);
813 return eventNotHandledErr
;
815 f
= mac_window_to_frame (wp
);
816 switch (GetEventKind (event
))
818 /* -- window refresh events -- */
820 case kEventWindowUpdate
:
821 result
= CallNextEventHandler (next_handler
, event
);
822 if (result
!= eventNotHandledErr
)
825 do_window_update (wp
);
829 /* -- window state change events -- */
831 case kEventWindowShowing
:
832 size_hints
= FRAME_SIZE_HINTS (f
);
833 if (!(size_hints
->flags
& (USPosition
| PPosition
)))
835 struct frame
*sf
= SELECTED_FRAME ();
837 if (!(FRAME_MAC_P (sf
) && sf
->async_visible
))
838 RepositionWindow (wp
, NULL
, kWindowCenterOnMainScreen
);
841 RepositionWindow (wp
, FRAME_MAC_WINDOW (sf
),
842 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
843 kWindowCascadeStartAtParentWindowScreen
845 kWindowCascadeOnParentWindowScreen
849 /* This is a workaround. RepositionWindow fails to put
850 a window at the cascading position when its parent
851 window has a Carbon HIToolbar. */
852 if ((f
->left_pos
== sf
->left_pos
853 && f
->top_pos
== sf
->top_pos
)
854 || (f
->left_pos
== sf
->left_pos
+ 10 * 2
855 && f
->top_pos
== sf
->top_pos
+ 32 * 2))
856 MoveWindowStructure (wp
, sf
->left_pos
+ 10, sf
->top_pos
+ 32);
863 case kEventWindowHiding
:
864 /* Before unmapping the window, update the WM_SIZE_HINTS
865 property to claim that the current position of the window is
866 user-specified, rather than program-specified, so that when
867 the window is mapped again, it will be placed at the same
868 location, without forcing the user to position it by hand
869 again (they have already done that once for this window.) */
870 x_wm_set_size_hint (f
, (long) 0, 1);
874 case kEventWindowShown
:
875 case kEventWindowHidden
:
876 case kEventWindowCollapsed
:
877 case kEventWindowExpanded
:
878 mac_handle_visibility_change (f
);
882 case kEventWindowBoundsChanging
:
883 result
= CallNextEventHandler (next_handler
, event
);
884 if (result
!= eventNotHandledErr
)
887 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
888 NULL
, sizeof (UInt32
), NULL
, &attributes
);
892 size_hints
= FRAME_SIZE_HINTS (f
);
893 if ((attributes
& kWindowBoundsChangeUserResize
)
894 && ((size_hints
->flags
& (PResizeInc
| PBaseSize
| PMinSize
))
895 == (PResizeInc
| PBaseSize
| PMinSize
)))
900 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
901 typeQDRectangle
, NULL
, sizeof (Rect
),
906 width
= bounds
.right
- bounds
.left
;
907 height
= bounds
.bottom
- bounds
.top
;
909 if (width
< size_hints
->min_width
)
910 width
= size_hints
->min_width
;
912 width
= size_hints
->base_width
913 + (int) ((width
- size_hints
->base_width
)
914 / (float) size_hints
->width_inc
+ .5)
915 * size_hints
->width_inc
;
917 if (height
< size_hints
->min_height
)
918 height
= size_hints
->min_height
;
920 height
= size_hints
->base_height
921 + (int) ((height
- size_hints
->base_height
)
922 / (float) size_hints
->height_inc
+ .5)
923 * size_hints
->height_inc
;
925 bounds
.right
= bounds
.left
+ width
;
926 bounds
.bottom
= bounds
.top
+ height
;
927 SetEventParameter (event
, kEventParamCurrentBounds
,
928 typeQDRectangle
, sizeof (Rect
), &bounds
);
933 case kEventWindowBoundsChanged
:
934 err
= GetEventParameter (event
, kEventParamAttributes
, typeUInt32
,
935 NULL
, sizeof (UInt32
), NULL
, &attributes
);
939 if (attributes
& kWindowBoundsChangeSizeChanged
)
943 err
= GetEventParameter (event
, kEventParamCurrentBounds
,
944 typeQDRectangle
, NULL
, sizeof (Rect
),
950 width
= bounds
.right
- bounds
.left
;
951 height
= bounds
.bottom
- bounds
.top
;
952 mac_handle_size_change (f
, width
, height
);
953 mac_wakeup_from_rne ();
957 if (attributes
& kWindowBoundsChangeOriginChanged
)
958 mac_handle_origin_change (f
);
963 /* -- window action events -- */
965 case kEventWindowClose
:
967 struct input_event buf
;
970 buf
.kind
= DELETE_WINDOW_EVENT
;
971 XSETFRAME (buf
.frame_or_window
, f
);
973 kbd_buffer_store_event (&buf
);
978 case kEventWindowGetIdealSize
:
979 result
= CallNextEventHandler (next_handler
, event
);
980 if (result
!= eventNotHandledErr
)
984 Point ideal_size
= mac_get_ideal_size (f
);
986 err
= SetEventParameter (event
, kEventParamDimensions
,
987 typeQDPoint
, sizeof (Point
), &ideal_size
);
994 case kEventWindowToolbarSwitchMode
:
996 static const EventParamName names
[] = {kEventParamDirectObject
,
997 kEventParamWindowMouseLocation
,
998 kEventParamKeyModifiers
,
999 kEventParamMouseButton
,
1000 kEventParamClickCount
,
1001 kEventParamMouseChord
};
1002 static const EventParamType types
[] = {typeWindowRef
,
1008 int num_params
= sizeof (names
) / sizeof (names
[0]);
1010 err
= mac_store_event_ref_as_apple_event (0, 0,
1012 Qtoolbar_switch_mode
,
1022 /* -- window focus events -- */
1024 case kEventWindowFocusAcquired
:
1025 err
= mac_tsm_resume ();
1030 case kEventWindowFocusRelinquish
:
1031 err
= mac_tsm_suspend ();
1045 /* Handle clicks in zoom box. Calculation of "standard state" based
1046 on code in IM - Window Manager A and code contributed by Ben
1047 Mesander. The standard state of an Emacs window is 80-characters
1048 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
1051 do_zoom_window (WindowRef w
, int zoom_in_or_out
)
1053 Rect zoom_rect
, port_rect
;
1055 struct frame
*f
= mac_window_to_frame (w
);
1056 #if TARGET_API_MAC_CARBON
1057 Point ideal_size
= mac_get_ideal_size (f
);
1059 GetWindowBounds (w
, kWindowContentRgn
, &port_rect
);
1060 if (IsWindowInStandardState (w
, &ideal_size
, &zoom_rect
)
1061 && port_rect
.left
== zoom_rect
.left
1062 && port_rect
.top
== zoom_rect
.top
)
1063 zoom_in_or_out
= inZoomIn
;
1065 zoom_in_or_out
= inZoomOut
;
1068 mac_clear_area (f
, 0, 0, port_rect
.right
- port_rect
.left
,
1069 port_rect
.bottom
- port_rect
.top
);
1071 ZoomWindowIdeal (w
, zoom_in_or_out
, &ideal_size
);
1072 #else /* not TARGET_API_MAC_CARBON */
1075 int w_title_height
, rows
;
1076 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
1078 GetPort (&save_port
);
1080 SetPortWindowPort (w
);
1082 /* Clear window to avoid flicker. */
1083 EraseRect (&(w
->portRect
));
1084 if (zoom_in_or_out
== inZoomOut
)
1086 SetPt (&top_left
, w
->portRect
.left
, w
->portRect
.top
);
1087 LocalToGlobal (&top_left
);
1089 /* calculate height of window's title bar */
1090 w_title_height
= top_left
.v
- 1
1091 - (**((WindowPeek
) w
)->strucRgn
).rgnBBox
.top
+ GetMBarHeight ();
1093 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
1094 zoom_rect
= qd
.screenBits
.bounds
;
1095 zoom_rect
.top
+= w_title_height
;
1096 InsetRect (&zoom_rect
, 8, 4); /* not too tight */
1098 zoom_rect
.right
= zoom_rect
.left
1099 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f
, DEFAULT_NUM_COLS
);
1101 /* Adjust the standard size according to character boundaries. */
1102 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f
, zoom_rect
.bottom
- zoom_rect
.top
);
1104 zoom_rect
.top
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f
, rows
);
1106 (**((WStateDataHandle
) ((WindowPeek
) w
)->dataHandle
)).stdState
1110 ZoomWindow (w
, zoom_in_or_out
, f
== mac_focus_frame (dpyinfo
));
1112 SetPort (save_port
);
1113 #endif /* not TARGET_API_MAC_CARBON */
1115 #if !TARGET_API_MAC_CARBON
1116 /* retrieve window size and update application values */
1117 port_rect
= w
->portRect
;
1118 height
= port_rect
.bottom
- port_rect
.top
;
1119 width
= port_rect
.right
- port_rect
.left
;
1121 mac_handle_size_change (f
, width
, height
);
1122 mac_handle_origin_change (f
);
1127 install_window_handler (window
)
1130 OSStatus err
= noErr
;
1132 #if TARGET_API_MAC_CARBON
1135 static const EventTypeSpec specs
[] =
1137 /* -- window refresh events -- */
1138 {kEventClassWindow
, kEventWindowUpdate
},
1139 /* -- window state change events -- */
1140 {kEventClassWindow
, kEventWindowShowing
},
1141 {kEventClassWindow
, kEventWindowHiding
},
1142 {kEventClassWindow
, kEventWindowShown
},
1143 {kEventClassWindow
, kEventWindowHidden
},
1144 {kEventClassWindow
, kEventWindowCollapsed
},
1145 {kEventClassWindow
, kEventWindowExpanded
},
1146 {kEventClassWindow
, kEventWindowBoundsChanging
},
1147 {kEventClassWindow
, kEventWindowBoundsChanged
},
1148 /* -- window action events -- */
1149 {kEventClassWindow
, kEventWindowClose
},
1150 {kEventClassWindow
, kEventWindowGetIdealSize
},
1152 {kEventClassWindow
, kEventWindowToolbarSwitchMode
},
1155 /* -- window focus events -- */
1156 {kEventClassWindow
, kEventWindowFocusAcquired
},
1157 {kEventClassWindow
, kEventWindowFocusRelinquish
},
1160 static EventHandlerUPP handle_window_eventUPP
= NULL
;
1162 if (handle_window_eventUPP
== NULL
)
1163 handle_window_eventUPP
= NewEventHandlerUPP (mac_handle_window_event
);
1165 err
= InstallWindowEventHandler (window
, handle_window_eventUPP
,
1166 GetEventTypeCount (specs
),
1172 err
= install_drag_handler (window
);
1178 remove_window_handler (window
)
1181 remove_drag_handler (window
);
1185 mac_get_window_bounds (f
, inner
, outer
)
1187 Rect
*inner
, *outer
;
1189 #if TARGET_API_MAC_CARBON
1190 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, inner
);
1191 GetWindowBounds (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, outer
);
1192 #else /* not TARGET_API_MAC_CARBON */
1193 RgnHandle region
= NewRgn ();
1195 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowContentRgn
, region
);
1196 *inner
= (*region
)->rgnBBox
;
1197 GetWindowRegion (FRAME_MAC_WINDOW (f
), kWindowStructureRgn
, region
);
1198 *outer
= (*region
)->rgnBBox
;
1199 DisposeRgn (region
);
1200 #endif /* not TARGET_API_MAC_CARBON */
1204 mac_get_frame_bounds (f
, r
)
1208 #if TARGET_API_MAC_CARBON
1209 return GetWindowPortBounds (FRAME_MAC_WINDOW (f
), r
);
1211 *r
= FRAME_MAC_WINDOW (f
)->portRect
;
1218 mac_get_frame_mouse (f
, point
)
1222 #if TARGET_API_MAC_CARBON
1223 GetGlobalMouse (point
);
1224 point
->h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1225 point
->v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1227 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1233 mac_convert_frame_point_to_global (f
, x
, y
)
1237 *x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
1238 *y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
1241 #if TARGET_API_MAC_CARBON
1243 mac_update_proxy_icon (f
)
1247 Lisp_Object file_name
=
1248 XBUFFER (XWINDOW (FRAME_SELECTED_WINDOW (f
))->buffer
)->filename
;
1249 Window w
= FRAME_MAC_WINDOW (f
);
1250 AliasHandle alias
= NULL
;
1252 err
= GetWindowProxyAlias (w
, &alias
);
1253 if (err
== errWindowDoesNotHaveProxy
&& !STRINGP (file_name
))
1256 if (STRINGP (file_name
))
1260 FSRef fref
, fref_proxy
;
1262 FSSpec fss
, fss_proxy
;
1265 Lisp_Object encoded_file_name
= ENCODE_FILE (file_name
);
1268 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (encoded_file_name
),
1269 SBYTES (encoded_file_name
), typeFSRef
, &desc
);
1271 SetPortWindowPort (w
);
1272 err
= AECoercePtr (TYPE_FILE_NAME
, SDATA (encoded_file_name
),
1273 SBYTES (encoded_file_name
), typeFSS
, &desc
);
1278 err
= AEGetDescData (&desc
, &fref
, sizeof (FSRef
));
1280 err
= AEGetDescData (&desc
, &fss
, sizeof (FSSpec
));
1282 AEDisposeDesc (&desc
);
1288 /* (FS)ResolveAlias never sets `changed' to true if
1289 `alias' is minimal. */
1291 err
= FSResolveAlias (NULL
, alias
, &fref_proxy
, &changed
);
1293 err
= FSCompareFSRefs (&fref
, &fref_proxy
);
1295 err
= ResolveAlias (NULL
, alias
, &fss_proxy
, &changed
);
1297 err
= !(fss
.vRefNum
== fss_proxy
.vRefNum
1298 && fss
.parID
== fss_proxy
.parID
1299 && EqualString (fss
.name
, fss_proxy
.name
,
1303 if (err
!= noErr
|| alias
== NULL
)
1306 DisposeHandle ((Handle
) alias
);
1308 err
= FSNewAliasMinimal (&fref
, &alias
);
1310 err
= NewAliasMinimal (&fss
, &alias
);
1317 err
= SetWindowProxyAlias (w
, alias
);
1321 DisposeHandle ((Handle
) alias
);
1323 if (err
!= noErr
|| !STRINGP (file_name
))
1324 RemoveWindowProxy (w
);
1328 /* Mac replacement for XSetWindowBackground. */
1331 mac_set_frame_window_background (f
, color
)
1333 unsigned long color
;
1335 WindowRef w
= FRAME_MAC_WINDOW (f
);
1336 #if !TARGET_API_MAC_CARBON
1337 AuxWinHandle aw_handle
;
1338 CTabHandle ctab_handle
;
1339 ColorSpecPtr ct_table
;
1344 bg_color
.red
= RED16_FROM_ULONG (color
);
1345 bg_color
.green
= GREEN16_FROM_ULONG (color
);
1346 bg_color
.blue
= BLUE16_FROM_ULONG (color
);
1348 #if TARGET_API_MAC_CARBON
1349 SetWindowContentColor (w
, &bg_color
);
1351 if (GetAuxWin (w
, &aw_handle
))
1353 ctab_handle
= (*aw_handle
)->awCTable
;
1354 HandToHand ((Handle
*) &ctab_handle
);
1355 ct_table
= (*ctab_handle
)->ctTable
;
1356 ct_size
= (*ctab_handle
)->ctSize
;
1357 while (ct_size
> -1)
1359 if (ct_table
->value
== 0)
1361 ct_table
->rgb
= bg_color
;
1362 CTabChanged (ctab_handle
);
1363 SetWinColor (w
, (WCTabHandle
) ctab_handle
);
1371 /* Flush display of frame F, or of all frames if F is null. */
1377 #if TARGET_API_MAC_CARBON
1380 mac_prepare_for_quickdraw (f
);
1383 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f
)), NULL
);
1385 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL
);
1392 mac_flush_display_optional (f
)
1396 mac_prepare_for_quickdraw (f
);
1402 mac_update_begin (f
)
1405 #if TARGET_API_MAC_CARBON
1406 /* During update of a frame, availability of input events is
1407 periodically checked with ReceiveNextEvent if
1408 redisplay-dont-pause is nil. That normally flushes window buffer
1409 changes for every check, and thus screen update looks waving even
1410 if no input is available. So we disable screen updates during
1411 update of a frame. */
1412 DisableScreenUpdates ();
1420 #if TARGET_API_MAC_CARBON
1421 EnableScreenUpdates ();
1426 mac_frame_up_to_date (f
)
1429 /* Nothing to do. */
1433 mac_create_frame_window (f
, tooltip_p
)
1438 #if TARGET_API_MAC_CARBON
1439 WindowClass window_class
;
1440 WindowAttributes attributes
;
1444 Boolean go_away_flag
;
1449 SetRect (&r
, f
->left_pos
, f
->top_pos
,
1450 f
->left_pos
+ FRAME_PIXEL_WIDTH (f
),
1451 f
->top_pos
+ FRAME_PIXEL_HEIGHT (f
));
1452 #if TARGET_API_MAC_CARBON
1453 window_class
= kDocumentWindowClass
;
1454 attributes
= (kWindowStandardDocumentAttributes
1456 | kWindowToolbarButtonAttribute
1460 proc_id
= zoomDocProc
;
1461 behind
= (WindowRef
) -1;
1462 go_away_flag
= true;
1467 SetRect (&r
, 0, 0, 1, 1);
1468 #if TARGET_API_MAC_CARBON
1469 window_class
= kHelpWindowClass
;
1470 attributes
= (kWindowNoUpdatesAttribute
1471 | kWindowNoActivatesAttribute
1472 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
1473 | kWindowIgnoreClicksAttribute
1477 proc_id
= plainDBox
;
1479 go_away_flag
= false;
1483 #if TARGET_API_MAC_CARBON
1484 CreateNewWindow (window_class
, attributes
, &r
, &FRAME_MAC_WINDOW (f
));
1485 if (FRAME_MAC_WINDOW (f
))
1487 SetWRefCon (FRAME_MAC_WINDOW (f
), (long) f
->output_data
.mac
);
1489 if (install_window_handler (FRAME_MAC_WINDOW (f
)) != noErr
)
1491 DisposeWindow (FRAME_MAC_WINDOW (f
));
1492 FRAME_MAC_WINDOW (f
) = NULL
;
1495 #else /* !TARGET_API_MAC_CARBON */
1496 FRAME_MAC_WINDOW (f
)
1497 = NewCWindow (NULL
, &r
, "\p", false, proc_id
, behind
, go_away_flag
,
1498 (long) f
->output_data
.mac
);
1499 #endif /* !TARGET_API_MAC_CARBON */
1500 /* so that update events can find this mac_output struct */
1501 f
->output_data
.mac
->mFP
= f
; /* point back to emacs frame */
1505 if (FRAME_MAC_WINDOW (f
))
1507 ControlRef root_control
;
1509 if (CreateRootControl (FRAME_MAC_WINDOW (f
), &root_control
) != noErr
)
1511 DisposeWindow (FRAME_MAC_WINDOW (f
));
1512 FRAME_MAC_WINDOW (f
) = NULL
;
1518 /* Dispose of the Mac window of the frame F. */
1521 mac_dispose_frame_window (f
)
1524 WindowRef window
= FRAME_MAC_WINDOW (f
);
1526 if (window
!= tip_window
)
1527 remove_window_handler (window
);
1530 mac_prepare_for_quickdraw (f
);
1532 DisposeWindow (window
);
1536 /************************************************************************
1538 ************************************************************************/
1541 #define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context)
1544 mac_begin_cg_clip (f
, gc
)
1548 CGContextRef context
= FRAME_CG_CONTEXT (f
);
1552 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)), &context
);
1553 FRAME_CG_CONTEXT (f
) = context
;
1556 CGContextSaveGState (context
);
1557 CGContextTranslateCTM (context
, 0, FRAME_PIXEL_HEIGHT (f
));
1558 CGContextScaleCTM (context
, 1, -1);
1559 if (gc
&& gc
->n_clip_rects
)
1560 CGContextClipToRects (context
, gc
->clip_rects
, gc
->n_clip_rects
);
1569 CGContextRestoreGState (FRAME_CG_CONTEXT (f
));
1573 mac_prepare_for_quickdraw (f
)
1578 Lisp_Object rest
, frame
;
1579 FOR_EACH_FRAME (rest
, frame
)
1580 if (FRAME_MAC_P (XFRAME (frame
)))
1581 mac_prepare_for_quickdraw (XFRAME (frame
));
1585 CGContextRef context
= FRAME_CG_CONTEXT (f
);
1589 CGContextSynchronize (context
);
1590 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f
)),
1591 &FRAME_CG_CONTEXT (f
));
1597 static RgnHandle saved_port_clip_region
= NULL
;
1600 mac_begin_clip (f
, gc
)
1604 static RgnHandle new_region
= NULL
;
1606 if (saved_port_clip_region
== NULL
)
1607 saved_port_clip_region
= NewRgn ();
1608 if (new_region
== NULL
)
1609 new_region
= NewRgn ();
1612 mac_prepare_for_quickdraw (f
);
1614 SetPortWindowPort (FRAME_MAC_WINDOW (f
));
1616 if (gc
&& gc
->n_clip_rects
)
1618 GetClip (saved_port_clip_region
);
1619 SectRgn (saved_port_clip_region
, gc
->clip_region
, new_region
);
1620 SetClip (new_region
);
1625 mac_end_clip (f
, gc
)
1629 if (gc
&& gc
->n_clip_rects
)
1630 SetClip (saved_port_clip_region
);
1633 #if TARGET_API_MAC_CARBON
1634 /* Mac replacement for XCopyArea: used only for scrolling. */
1637 mac_scroll_area (f
, gc
, src_x
, src_y
, width
, height
, dest_x
, dest_y
)
1641 unsigned int width
, height
;
1645 RgnHandle dummy
= NewRgn (); /* For avoiding update events. */
1647 SetRect (&src_r
, src_x
, src_y
, src_x
+ width
, src_y
+ height
);
1649 mac_prepare_for_quickdraw (f
);
1651 ScrollWindowRect (FRAME_MAC_WINDOW (f
),
1652 &src_r
, dest_x
- src_x
, dest_y
- src_y
,
1653 kScrollWindowNoOptions
, dummy
);
1659 /************************************************************************
1661 ************************************************************************/
1663 extern struct scroll_bar
*tracked_scroll_bar
;
1664 extern Lisp_Object last_mouse_scroll_bar
;
1665 extern Time last_mouse_movement_time
;
1667 static void x_scroll_bar_handle_click
P_ ((struct scroll_bar
*,
1669 const EventRecord
*,
1670 struct input_event
*));
1671 #ifndef USE_TOOLKIT_SCROLL_BARS
1672 static void x_scroll_bar_note_movement
P_ ((struct scroll_bar
*, int, Time
));
1673 #else /* USE_TOOLKIT_SCROLL_BARS */
1674 static void x_scroll_bar_handle_press
P_ ((struct scroll_bar
*,
1675 ControlPartCode
, Point
,
1676 struct input_event
*));
1677 static void x_scroll_bar_handle_release
P_ ((struct scroll_bar
*,
1678 struct input_event
*));
1679 static void x_scroll_bar_handle_drag
P_ ((WindowRef
, struct scroll_bar
*,
1680 Point
, struct input_event
*));
1681 static pascal void scroll_bar_timer_callback
P_ ((EventLoopTimerRef
, void *));
1682 static OSStatus install_scroll_bar_timer
P_ ((void));
1683 static OSStatus set_scroll_bar_timer
P_ ((EventTimerInterval
));
1684 static int control_part_code_to_scroll_bar_part
P_ ((ControlPartCode
));
1685 static void construct_scroll_bar_click
P_ ((struct scroll_bar
*, int,
1686 struct input_event
*));
1687 static OSStatus get_control_part_bounds
P_ ((ControlRef
, ControlPartCode
,
1689 static void update_scroll_bar_track_info
P_ ((struct scroll_bar
*));
1691 /* Last scroll bar part sent in x_scroll_bar_handle_*. */
1693 static int last_scroll_bar_part
;
1695 static EventLoopTimerRef scroll_bar_timer
;
1697 static int scroll_bar_timer_event_posted_p
;
1699 #define SCROLL_BAR_FIRST_DELAY 0.5
1700 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
1703 scroll_bar_timer_callback (timer
, data
)
1704 EventLoopTimerRef timer
;
1709 err
= mac_post_mouse_moved_event ();
1711 scroll_bar_timer_event_posted_p
= 1;
1715 install_scroll_bar_timer ()
1717 static EventLoopTimerUPP scroll_bar_timer_callbackUPP
= NULL
;
1719 if (scroll_bar_timer_callbackUPP
== NULL
)
1720 scroll_bar_timer_callbackUPP
=
1721 NewEventLoopTimerUPP (scroll_bar_timer_callback
);
1723 if (scroll_bar_timer
== NULL
)
1724 /* Mac OS X and CarbonLib 1.5 and later allow us to specify
1725 kEventDurationForever as delays. */
1727 InstallEventLoopTimer (GetCurrentEventLoop (),
1728 kEventDurationForever
, kEventDurationForever
,
1729 scroll_bar_timer_callbackUPP
, NULL
,
1734 set_scroll_bar_timer (delay
)
1735 EventTimerInterval delay
;
1737 if (scroll_bar_timer
== NULL
)
1738 install_scroll_bar_timer ();
1740 scroll_bar_timer_event_posted_p
= 0;
1742 return SetEventLoopTimerNextFireTime (scroll_bar_timer
, delay
);
1746 control_part_code_to_scroll_bar_part (part_code
)
1747 ControlPartCode part_code
;
1751 case kControlUpButtonPart
: return scroll_bar_up_arrow
;
1752 case kControlDownButtonPart
: return scroll_bar_down_arrow
;
1753 case kControlPageUpPart
: return scroll_bar_above_handle
;
1754 case kControlPageDownPart
: return scroll_bar_below_handle
;
1755 case kControlIndicatorPart
: return scroll_bar_handle
;
1762 construct_scroll_bar_click (bar
, part
, bufp
)
1763 struct scroll_bar
*bar
;
1765 struct input_event
*bufp
;
1767 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
1768 bufp
->frame_or_window
= bar
->window
;
1772 XSETINT (bufp
->x
, 0);
1773 XSETINT (bufp
->y
, 0);
1774 bufp
->modifiers
= 0;
1778 get_control_part_bounds (ch
, part_code
, rect
)
1780 ControlPartCode part_code
;
1783 RgnHandle region
= NewRgn ();
1786 err
= GetControlRegion (ch
, part_code
, region
);
1788 GetRegionBounds (region
, rect
);
1789 DisposeRgn (region
);
1795 x_scroll_bar_handle_press (bar
, part_code
, mouse_pos
, bufp
)
1796 struct scroll_bar
*bar
;
1797 ControlPartCode part_code
;
1799 struct input_event
*bufp
;
1801 int part
= control_part_code_to_scroll_bar_part (part_code
);
1806 if (part
!= scroll_bar_handle
)
1808 construct_scroll_bar_click (bar
, part
, bufp
);
1809 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
1810 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY
);
1811 bar
->dragging
= Qnil
;
1817 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
1818 kControlIndicatorPart
, &r
);
1819 XSETINT (bar
->dragging
, - (mouse_pos
.v
- r
.top
) - 1);
1822 last_scroll_bar_part
= part
;
1823 tracked_scroll_bar
= bar
;
1827 x_scroll_bar_handle_release (bar
, bufp
)
1828 struct scroll_bar
*bar
;
1829 struct input_event
*bufp
;
1831 if (last_scroll_bar_part
!= scroll_bar_handle
1832 || (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) >= 0))
1833 construct_scroll_bar_click (bar
, scroll_bar_end_scroll
, bufp
);
1835 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
1836 set_scroll_bar_timer (kEventDurationForever
);
1838 last_scroll_bar_part
= -1;
1839 bar
->dragging
= Qnil
;
1840 tracked_scroll_bar
= NULL
;
1844 x_scroll_bar_handle_drag (win
, bar
, mouse_pos
, bufp
)
1846 struct scroll_bar
*bar
;
1848 struct input_event
*bufp
;
1850 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
1852 if (last_scroll_bar_part
== scroll_bar_handle
)
1857 get_control_part_bounds (SCROLL_BAR_CONTROL_REF (bar
),
1858 kControlIndicatorPart
, &r
);
1860 if (INTEGERP (bar
->dragging
) && XINT (bar
->dragging
) < 0)
1861 XSETINT (bar
->dragging
, - (XINT (bar
->dragging
) + 1));
1863 top
= mouse_pos
.v
- XINT (bar
->dragging
) - XINT (bar
->track_top
);
1864 top_range
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
1868 if (top
> top_range
)
1871 construct_scroll_bar_click (bar
, scroll_bar_handle
, bufp
);
1872 XSETINT (bufp
->x
, top
);
1873 XSETINT (bufp
->y
, top_range
);
1877 ControlPartCode part_code
;
1878 int unhilite_p
= 0, part
;
1880 if (ch
!= FindControlUnderMouse (mouse_pos
, win
, &part_code
))
1884 part
= control_part_code_to_scroll_bar_part (part_code
);
1886 switch (last_scroll_bar_part
)
1888 case scroll_bar_above_handle
:
1889 case scroll_bar_below_handle
:
1890 if (part
!= scroll_bar_above_handle
1891 && part
!= scroll_bar_below_handle
)
1895 case scroll_bar_up_arrow
:
1896 case scroll_bar_down_arrow
:
1897 if (part
!= scroll_bar_up_arrow
1898 && part
!= scroll_bar_down_arrow
)
1905 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), 0);
1906 else if (part
!= last_scroll_bar_part
1907 || scroll_bar_timer_event_posted_p
)
1909 construct_scroll_bar_click (bar
, part
, bufp
);
1910 last_scroll_bar_part
= part
;
1911 HiliteControl (SCROLL_BAR_CONTROL_REF (bar
), part_code
);
1912 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY
);
1917 /* Update BAR->track_top, BAR->track_height, and BAR->min_handle for
1918 the scroll bar BAR. This function should be called when the bounds
1919 of the scroll bar is changed. */
1922 update_scroll_bar_track_info (bar
)
1923 struct scroll_bar
*bar
;
1925 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
1928 GetControlBounds (ch
, &r0
);
1930 if (r0
.right
- r0
.left
>= r0
.bottom
- r0
.top
1932 || r0
.right
- r0
.left
< MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH
1936 XSETINT (bar
->track_top
, 0);
1937 XSETINT (bar
->track_height
, 0);
1938 XSETINT (bar
->min_handle
, 0);
1944 SetControl32BitMinimum (ch
, 0);
1945 SetControl32BitMaximum (ch
, 1 << 30);
1946 SetControlViewSize (ch
, 1);
1948 /* Move the scroll bar thumb to the top. */
1949 SetControl32BitValue (ch
, 0);
1950 get_control_part_bounds (ch
, kControlIndicatorPart
, &r0
);
1952 /* Move the scroll bar thumb to the bottom. */
1953 SetControl32BitValue (ch
, 1 << 30);
1954 get_control_part_bounds (ch
, kControlIndicatorPart
, &r1
);
1956 UnionRect (&r0
, &r1
, &r0
);
1957 XSETINT (bar
->track_top
, r0
.top
);
1958 XSETINT (bar
->track_height
, r0
.bottom
- r0
.top
);
1959 XSETINT (bar
->min_handle
, r1
.bottom
- r1
.top
);
1961 /* Don't show the scroll bar if its height is not enough to
1962 display the scroll bar thumb. */
1963 if (r0
.bottom
- r0
.top
> 0)
1970 /* Set the thumb size and position of scroll bar BAR. We are currently
1971 displaying PORTION out of a whole WHOLE, and our position POSITION. */
1974 x_set_toolkit_scroll_bar_thumb (bar
, portion
, position
, whole
)
1975 struct scroll_bar
*bar
;
1976 int portion
, position
, whole
;
1978 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
1979 int value
, viewsize
, maximum
;
1981 if (XINT (bar
->track_height
) == 0)
1984 if (whole
<= portion
)
1985 value
= 0, viewsize
= 1, maximum
= 0;
1990 maximum
= XINT (bar
->track_height
) - XINT (bar
->min_handle
);
1991 scale
= (float) maximum
/ (whole
- portion
);
1992 value
= position
* scale
+ 0.5f
;
1993 viewsize
= (int) (portion
* scale
+ 0.5f
) + XINT (bar
->min_handle
);
1998 if (GetControlViewSize (ch
) != viewsize
1999 || GetControl32BitValue (ch
) != value
2000 || GetControl32BitMaximum (ch
) != maximum
)
2002 /* Temporarily hide the scroll bar to avoid multiple redraws. */
2003 SetControlVisibility (ch
, false, false);
2005 SetControl32BitMaximum (ch
, maximum
);
2006 SetControl32BitValue (ch
, value
);
2007 SetControlViewSize (ch
, viewsize
);
2009 SetControlVisibility (ch
, true, true);
2015 #endif /* USE_TOOLKIT_SCROLL_BARS */
2017 /* Create a scroll bar control for BAR. BOUNDS and VISIBLE specifies
2018 the initial geometry and visibility, respectively. The created
2019 control is stored in some members of BAR. */
2022 mac_create_scroll_bar (bar
, bounds
, visible
)
2023 struct scroll_bar
*bar
;
2027 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2031 mac_prepare_for_quickdraw (f
);
2033 ch
= NewControl (FRAME_MAC_WINDOW (f
), bounds
, "\p", visible
, 0, 0, 0,
2034 #if TARGET_API_MAC_CARBON
2035 kControlScrollBarProc
,
2040 SET_SCROLL_BAR_CONTROL_REF (bar
, ch
);
2042 XSETINT (bar
->start
, 0);
2043 XSETINT (bar
->end
, 0);
2044 bar
->dragging
= Qnil
;
2046 #ifdef USE_TOOLKIT_SCROLL_BARS
2047 update_scroll_bar_track_info (bar
);
2051 /* Dispose of the scroll bar control stored in some members of
2055 mac_dispose_scroll_bar (bar
)
2056 struct scroll_bar
*bar
;
2059 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2061 mac_prepare_for_quickdraw (f
);
2063 DisposeControl (SCROLL_BAR_CONTROL_REF (bar
));
2066 /* Set bounds of the scroll bar BAR to BOUNDS. */
2069 mac_set_scroll_bar_bounds (bar
, bounds
)
2070 struct scroll_bar
*bar
;
2073 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
2074 SInt16 width
, height
;
2076 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2078 mac_prepare_for_quickdraw (f
);
2081 width
= bounds
->right
- bounds
->left
;
2082 height
= bounds
->bottom
- bounds
->top
;
2084 MoveControl (ch
, bounds
->left
, bounds
->top
);
2085 SizeControl (ch
, width
, height
);
2086 #ifdef USE_TOOLKIT_SCROLL_BARS
2087 update_scroll_bar_track_info (bar
);
2094 /* Draw the scroll bar BAR. */
2097 mac_redraw_scroll_bar (bar
)
2098 struct scroll_bar
*bar
;
2101 struct frame
*f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2103 mac_prepare_for_quickdraw (f
);
2105 Draw1Control (SCROLL_BAR_CONTROL_REF (bar
));
2108 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
2109 is set to something other than NO_EVENT, it is enqueued.
2111 This may be called from a signal handler, so we have to ignore GC
2115 x_scroll_bar_handle_click (bar
, part_code
, er
, bufp
)
2116 struct scroll_bar
*bar
;
2117 ControlPartCode part_code
;
2118 const EventRecord
*er
;
2119 struct input_event
*bufp
;
2121 int win_y
, top_range
;
2123 if (! GC_WINDOWP (bar
->window
))
2126 bufp
->kind
= SCROLL_BAR_CLICK_EVENT
;
2127 bufp
->frame_or_window
= bar
->window
;
2130 bar
->dragging
= Qnil
;
2134 case kControlUpButtonPart
:
2135 bufp
->part
= scroll_bar_up_arrow
;
2137 case kControlDownButtonPart
:
2138 bufp
->part
= scroll_bar_down_arrow
;
2140 case kControlPageUpPart
:
2141 bufp
->part
= scroll_bar_above_handle
;
2143 case kControlPageDownPart
:
2144 bufp
->part
= scroll_bar_below_handle
;
2146 #if TARGET_API_MAC_CARBON
2149 case kControlIndicatorPart
:
2151 if (er
->what
== mouseDown
)
2152 bar
->dragging
= make_number (0);
2153 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2154 bufp
->part
= scroll_bar_handle
;
2158 win_y
= XINT (bufp
->y
) - XINT (bar
->top
);
2159 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar
->height
));
2161 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2165 if (! NILP (bar
->dragging
))
2166 win_y
-= XINT (bar
->dragging
);
2170 if (win_y
> top_range
)
2173 XSETINT (bufp
->x
, win_y
);
2174 XSETINT (bufp
->y
, top_range
);
2177 /* Return information to the user about the current position of the mouse
2178 on the scroll bar. */
2181 x_scroll_bar_report_motion (fp
, bar_window
, part
, x
, y
, time
)
2183 Lisp_Object
*bar_window
;
2184 enum scroll_bar_part
*part
;
2186 unsigned long *time
;
2188 struct scroll_bar
*bar
= XSCROLL_BAR (last_mouse_scroll_bar
);
2189 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
2190 #if TARGET_API_MAC_CARBON
2191 WindowRef wp
= GetControlOwner (ch
);
2193 WindowRef wp
= (*ch
)->contrlOwner
;
2196 struct frame
*f
= mac_window_to_frame (wp
);
2197 int win_y
, top_range
;
2199 #if TARGET_API_MAC_CARBON
2200 GetGlobalMouse (&mouse_pos
);
2201 mouse_pos
.h
-= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
2202 mouse_pos
.v
-= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
2204 SetPortWindowPort (wp
);
2205 GetMouse (&mouse_pos
);
2208 win_y
= mouse_pos
.v
- XINT (bar
->top
);
2209 top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
2211 win_y
-= VERTICAL_SCROLL_BAR_TOP_BORDER
;
2215 if (! NILP (bar
->dragging
))
2216 win_y
-= XINT (bar
->dragging
);
2220 if (win_y
> top_range
)
2224 *bar_window
= bar
->window
;
2226 if (! NILP (bar
->dragging
))
2227 *part
= scroll_bar_handle
;
2228 else if (win_y
< XINT (bar
->start
))
2229 *part
= scroll_bar_above_handle
;
2230 else if (win_y
< XINT (bar
->end
) + VERTICAL_SCROLL_BAR_MIN_HANDLE
)
2231 *part
= scroll_bar_handle
;
2233 *part
= scroll_bar_below_handle
;
2235 XSETINT (*x
, win_y
);
2236 XSETINT (*y
, top_range
);
2239 last_mouse_scroll_bar
= Qnil
;
2241 *time
= last_mouse_movement_time
;
2244 #ifndef USE_TOOLKIT_SCROLL_BARS
2245 /* Draw BAR's handle in the proper position.
2247 If the handle is already drawn from START to END, don't bother
2248 redrawing it, unless REBUILD is non-zero; in that case, always
2249 redraw it. (REBUILD is handy for drawing the handle after expose
2252 Normally, we want to constrain the start and end of the handle to
2253 fit inside its rectangle, but if the user is dragging the scroll
2254 bar handle, we want to let them drag it down all the way, so that
2255 the bar's top is as far down as it goes; otherwise, there's no way
2256 to move to the very end of the buffer. */
2259 x_scroll_bar_set_handle (bar
, start
, end
, rebuild
)
2260 struct scroll_bar
*bar
;
2264 int dragging
= ! NILP (bar
->dragging
);
2265 ControlRef ch
= SCROLL_BAR_CONTROL_REF (bar
);
2266 FRAME_PTR f
= XFRAME (WINDOW_FRAME (XWINDOW (bar
->window
)));
2267 int top_range
= VERTICAL_SCROLL_BAR_TOP_RANGE (f
, XINT (bar
->height
));
2268 int length
= end
- start
;
2270 /* If the display is already accurate, do nothing. */
2272 && start
== XINT (bar
->start
)
2273 && end
== XINT (bar
->end
))
2278 /* Make sure the values are reasonable, and try to preserve the
2279 distance between start and end. */
2282 else if (start
> top_range
)
2284 end
= start
+ length
;
2288 else if (end
> top_range
&& ! dragging
)
2291 /* Store the adjusted setting in the scroll bar. */
2292 XSETINT (bar
->start
, start
);
2293 XSETINT (bar
->end
, end
);
2295 /* Clip the end position, just for display. */
2296 if (end
> top_range
)
2299 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
2300 top positions, to make sure the handle is always at least that
2301 many pixels tall. */
2302 end
+= VERTICAL_SCROLL_BAR_MIN_HANDLE
;
2304 SetControlMinimum (ch
, 0);
2305 /* Don't inadvertently activate deactivated scroll bars */
2306 if (GetControlMaximum (ch
) != -1)
2307 SetControlMaximum (ch
, top_range
+ VERTICAL_SCROLL_BAR_MIN_HANDLE
2309 SetControlValue (ch
, start
);
2310 #if TARGET_API_MAC_CARBON
2311 SetControlViewSize (ch
, end
- start
);
2317 /* Handle some mouse motion while someone is dragging the scroll bar.
2319 This may be called from a signal handler, so we have to ignore GC
2323 x_scroll_bar_note_movement (bar
, y_pos
, t
)
2324 struct scroll_bar
*bar
;
2328 FRAME_PTR f
= XFRAME (XWINDOW (bar
->window
)->frame
);
2330 last_mouse_movement_time
= t
;
2333 XSETVECTOR (last_mouse_scroll_bar
, bar
);
2335 /* If we're dragging the bar, display it. */
2336 if (! GC_NILP (bar
->dragging
))
2338 /* Where should the handle be now? */
2339 int new_start
= y_pos
- 24;
2341 if (new_start
!= XINT (bar
->start
))
2343 int new_end
= new_start
+ (XINT (bar
->end
) - XINT (bar
->start
));
2345 x_scroll_bar_set_handle (bar
, new_start
, new_end
, 0);
2349 #endif /* !USE_TOOLKIT_SCROLL_BARS */
2352 /***********************************************************************
2354 ***********************************************************************/
2357 /* In identifiers such as function/variable names, Emacs tool bar is
2358 referred to as `tool_bar', and Carbon HIToolbar as `toolbar'. */
2360 #define TOOLBAR_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar"))
2361 #define TOOLBAR_ICON_ITEM_IDENTIFIER (CFSTR ("org.gnu.Emacs.toolbar.icon"))
2363 #define TOOLBAR_ITEM_COMMAND_ID_OFFSET 'Tb\0\0'
2364 #define TOOLBAR_ITEM_COMMAND_ID_P(id) \
2365 (((id) & ~0xffff) == TOOLBAR_ITEM_COMMAND_ID_OFFSET)
2366 #define TOOLBAR_ITEM_COMMAND_ID_VALUE(id) \
2367 ((id) - TOOLBAR_ITEM_COMMAND_ID_OFFSET)
2368 #define TOOLBAR_ITEM_MAKE_COMMAND_ID(value) \
2369 ((value) + TOOLBAR_ITEM_COMMAND_ID_OFFSET)
2371 static OSStatus mac_handle_toolbar_command_event
P_ ((EventHandlerCallRef
,
2374 extern Rect last_mouse_glyph
;
2376 extern void mac_move_window_with_gravity
P_ ((struct frame
*, int,
2378 extern void mac_get_window_origin_with_gravity
P_ ((struct frame
*, int,
2380 extern CGImageRef mac_image_spec_to_cg_image
P_ ((struct frame
*,
2384 mac_handle_toolbar_event (next_handler
, event
, data
)
2385 EventHandlerCallRef next_handler
;
2389 OSStatus result
= eventNotHandledErr
;
2391 switch (GetEventKind (event
))
2393 case kEventToolbarGetDefaultIdentifiers
:
2397 case kEventToolbarGetAllowedIdentifiers
:
2399 CFMutableArrayRef array
;
2401 GetEventParameter (event
, kEventParamMutableArray
,
2402 typeCFMutableArrayRef
, NULL
,
2403 sizeof (CFMutableArrayRef
), NULL
, &array
);
2404 CFArrayAppendValue (array
, TOOLBAR_ICON_ITEM_IDENTIFIER
);
2409 case kEventToolbarCreateItemWithIdentifier
:
2411 CFStringRef identifier
;
2412 HIToolbarItemRef item
= NULL
;
2414 GetEventParameter (event
, kEventParamToolbarItemIdentifier
,
2415 typeCFStringRef
, NULL
,
2416 sizeof (CFStringRef
), NULL
, &identifier
);
2418 if (CFStringCompare (identifier
, TOOLBAR_ICON_ITEM_IDENTIFIER
, 0)
2419 == kCFCompareEqualTo
)
2420 HIToolbarItemCreate (identifier
,
2421 kHIToolbarItemAllowDuplicates
2422 | kHIToolbarItemCantBeRemoved
, &item
);
2426 SetEventParameter (event
, kEventParamToolbarItem
,
2427 typeHIToolbarItemRef
,
2428 sizeof (HIToolbarItemRef
), &item
);
2441 /* Create a tool bar for frame F. */
2444 mac_create_frame_tool_bar (f
)
2448 HIToolbarRef toolbar
;
2450 err
= HIToolbarCreate (TOOLBAR_IDENTIFIER
, kHIToolbarNoAttributes
,
2454 static const EventTypeSpec specs
[] =
2455 {{kEventClassToolbar
, kEventToolbarGetDefaultIdentifiers
},
2456 {kEventClassToolbar
, kEventToolbarGetAllowedIdentifiers
},
2457 {kEventClassToolbar
, kEventToolbarCreateItemWithIdentifier
}};
2459 err
= InstallEventHandler (HIObjectGetEventTarget (toolbar
),
2460 mac_handle_toolbar_event
,
2461 GetEventTypeCount (specs
), specs
,
2466 err
= HIToolbarSetDisplayMode (toolbar
, kHIToolbarDisplayModeIconOnly
);
2469 static const EventTypeSpec specs
[] =
2470 {{kEventClassCommand
, kEventCommandProcess
}};
2472 err
= InstallWindowEventHandler (FRAME_MAC_WINDOW (f
),
2473 mac_handle_toolbar_command_event
,
2474 GetEventTypeCount (specs
),
2478 err
= SetWindowToolbar (FRAME_MAC_WINDOW (f
), toolbar
);
2481 CFRelease (toolbar
);
2486 /* Update the tool bar for frame F. Add new buttons and remove old. */
2489 update_frame_tool_bar (f
)
2492 HIToolbarRef toolbar
= NULL
;
2494 CFArrayRef old_items
= NULL
;
2496 int i
, pos
, win_gravity
= f
->output_data
.mac
->toolbar_win_gravity
;
2497 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2501 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
2502 if (toolbar
== NULL
)
2504 mac_create_frame_tool_bar (f
);
2505 GetWindowToolbar (FRAME_MAC_WINDOW (f
), &toolbar
);
2506 if (toolbar
== NULL
)
2508 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
2509 mac_get_window_origin_with_gravity (f
, win_gravity
, &left
, &top
);
2512 HIToolbarCopyItems (toolbar
, &old_items
);
2513 if (old_items
== NULL
)
2516 old_count
= CFArrayGetCount (old_items
);
2518 for (i
= 0; i
< f
->n_tool_bar_items
; ++i
)
2520 #define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
2522 int enabled_p
= !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
));
2523 int selected_p
= !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P
));
2526 CGImageRef cg_image
;
2528 HIToolbarItemRef item
;
2530 /* If image is a vector, choose the image according to the
2532 image
= PROP (TOOL_BAR_ITEM_IMAGES
);
2533 if (VECTORP (image
))
2537 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
2538 : TOOL_BAR_IMAGE_ENABLED_DESELECTED
);
2541 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
2542 : TOOL_BAR_IMAGE_DISABLED_DESELECTED
);
2544 xassert (ASIZE (image
) >= idx
);
2545 image
= AREF (image
, idx
);
2550 cg_image
= mac_image_spec_to_cg_image (f
, image
);
2551 /* Ignore invalid image specifications. */
2552 if (cg_image
== NULL
)
2555 label
= cfstring_create_with_string (PROP (TOOL_BAR_ITEM_CAPTION
));
2559 if (pos
< old_count
)
2561 CGImageRef old_cg_image
= NULL
;
2562 CFStringRef old_label
= NULL
;
2563 Boolean old_enabled_p
;
2565 item
= (HIToolbarItemRef
) CFArrayGetValueAtIndex (old_items
, pos
);
2567 HIToolbarItemCopyImage (item
, &old_cg_image
);
2568 if (cg_image
!= old_cg_image
)
2569 HIToolbarItemSetImage (item
, cg_image
);
2570 CGImageRelease (old_cg_image
);
2572 HIToolbarItemCopyLabel (item
, &old_label
);
2573 if (CFStringCompare (label
, old_label
, 0) != kCFCompareEqualTo
)
2574 HIToolbarItemSetLabel (item
, label
);
2575 CFRelease (old_label
);
2577 old_enabled_p
= HIToolbarItemIsEnabled (item
);
2578 if ((enabled_p
|| idx
>= 0) != old_enabled_p
)
2579 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
2584 HIToolbarCreateItemWithIdentifier (toolbar
,
2585 TOOLBAR_ICON_ITEM_IDENTIFIER
,
2589 HIToolbarItemSetImage (item
, cg_image
);
2590 HIToolbarItemSetLabel (item
, label
);
2591 HIToolbarItemSetEnabled (item
, (enabled_p
|| idx
>= 0));
2592 HIToolbarAppendItem (toolbar
, item
);
2600 HIToolbarItemSetCommandID (item
, TOOLBAR_ITEM_MAKE_COMMAND_ID (i
));
2605 CFRelease (old_items
);
2607 while (pos
< old_count
)
2608 HIToolbarRemoveItemAtIndex (toolbar
, --old_count
);
2610 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), true,
2611 !win_gravity
&& f
== mac_focus_frame (dpyinfo
));
2612 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events on
2613 toolbar visibility change. */
2614 mac_handle_origin_change (f
);
2615 if (win_gravity
>= NorthWestGravity
&& win_gravity
<= SouthEastGravity
)
2617 mac_move_window_with_gravity (f
, win_gravity
, left
, top
);
2618 /* If the title bar is completely outside the screen, adjust the
2620 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f
), kWindowTitleBarRgn
,
2621 kWindowConstrainMoveRegardlessOfFit
2622 | kWindowConstrainAllowPartial
, NULL
, NULL
);
2623 f
->output_data
.mac
->toolbar_win_gravity
= 0;
2630 /* Hide the tool bar on frame F. Unlike the counterpart on GTK+, it
2631 doesn't deallocate the resources. */
2634 free_frame_tool_bar (f
)
2637 if (IsWindowToolbarVisible (FRAME_MAC_WINDOW (f
)))
2639 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2642 ShowHideWindowToolbar (FRAME_MAC_WINDOW (f
), false,
2643 (NILP (find_symbol_value
2644 (intern ("frame-notice-user-settings")))
2645 && f
== mac_focus_frame (dpyinfo
)));
2646 /* Mac OS X 10.3 does not issue kEventWindowBoundsChanged events
2647 on toolbar visibility change. */
2648 mac_handle_origin_change (f
);
2653 /* Report a mouse movement over toolbar to the mainstream Emacs
2657 mac_tool_bar_note_mouse_movement (f
, event
)
2662 struct mac_display_info
*dpyinfo
= FRAME_MAC_DISPLAY_INFO (f
);
2665 WindowPartCode part_code
;
2666 HIViewRef item_view
;
2669 mouse_down_p
= (dpyinfo
->grabbed
2670 && f
== last_mouse_frame
2671 && FRAME_LIVE_P (f
));
2675 err
= GetEventParameter (event
, kEventParamWindowRef
, typeWindowRef
, NULL
,
2676 sizeof (WindowRef
), NULL
, &window
);
2677 if (err
!= noErr
|| window
!= FRAME_MAC_WINDOW (f
))
2680 err
= GetEventParameter (event
, kEventParamWindowPartCode
,
2681 typeWindowPartCode
, NULL
,
2682 sizeof (WindowPartCode
), NULL
, &part_code
);
2683 if (err
!= noErr
|| part_code
!= inStructure
)
2686 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window
), event
, &item_view
);
2687 /* This doesn't work on Mac OS X 10.2. On Mac OS X 10.3 and 10.4, a
2688 toolbar item view seems to have the same command ID with that of
2689 the toolbar item. */
2691 err
= GetControlCommandID (item_view
, &command_id
);
2692 if (err
== noErr
&& TOOLBAR_ITEM_COMMAND_ID_P (command_id
))
2694 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command_id
);
2696 if (i
< f
->n_tool_bar_items
)
2699 HIViewRef content_view
;
2701 err
= HIViewGetBounds (item_view
, &bounds
);
2703 err
= HIViewFindByID (HIViewGetRoot (window
),
2704 kHIViewWindowContentID
, &content_view
);
2706 err
= HIViewConvertRect (&bounds
, item_view
, content_view
);
2708 SetRect (&last_mouse_glyph
,
2709 CGRectGetMinX (bounds
), CGRectGetMinY (bounds
),
2710 CGRectGetMaxX (bounds
), CGRectGetMaxY (bounds
));
2712 help_echo_object
= help_echo_window
= Qnil
;
2714 help_echo_string
= PROP (TOOL_BAR_ITEM_HELP
);
2715 if (NILP (help_echo_string
))
2716 help_echo_string
= PROP (TOOL_BAR_ITEM_CAPTION
);
2722 mac_handle_toolbar_command_event (next_handler
, event
, data
)
2723 EventHandlerCallRef next_handler
;
2727 OSStatus err
, result
= eventNotHandledErr
;
2728 struct frame
*f
= (struct frame
*) data
;
2731 err
= GetEventParameter (event
, kEventParamDirectObject
,
2732 typeHICommand
, NULL
,
2733 sizeof (HICommand
), NULL
, &command
);
2737 switch (GetEventKind (event
))
2739 case kEventCommandProcess
:
2740 if (!TOOLBAR_ITEM_COMMAND_ID_P (command
.commandID
))
2741 result
= CallNextEventHandler (next_handler
, event
);
2744 int i
= TOOLBAR_ITEM_COMMAND_ID_VALUE (command
.commandID
);
2746 if (i
< f
->n_tool_bar_items
2747 && !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P
)))
2750 struct input_event buf
;
2754 XSETFRAME (frame
, f
);
2755 buf
.kind
= TOOL_BAR_EVENT
;
2756 buf
.frame_or_window
= frame
;
2758 kbd_buffer_store_event (&buf
);
2760 buf
.kind
= TOOL_BAR_EVENT
;
2761 buf
.frame_or_window
= frame
;
2762 buf
.arg
= PROP (TOOL_BAR_ITEM_KEY
);
2763 buf
.modifiers
= mac_event_to_emacs_modifiers (event
);
2764 kbd_buffer_store_event (&buf
);
2778 #endif /* USE_MAC_TOOLBAR */
2781 /***********************************************************************
2783 ***********************************************************************/
2785 #if USE_MAC_FONT_PANEL
2786 /* Whether Font Panel has been shown before. The first call to font
2787 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is
2788 slow. This variable is used for deferring such a call as much as
2790 static int font_panel_shown_p
= 0;
2792 extern Lisp_Object Qpanel_closed
, Qselection
;
2793 extern Lisp_Object Qfont
;
2795 /* Whether the font panel is currently visible. */
2798 mac_font_panel_visible_p ()
2800 return font_panel_shown_p
&& FPIsFontPanelVisible ();
2803 static pascal OSStatus
2804 mac_handle_font_event (next_handler
, event
, data
)
2805 EventHandlerCallRef next_handler
;
2809 OSStatus result
, err
;
2812 const EventParamName
*names
;
2813 const EventParamType
*types
;
2814 static const EventParamName names_sel
[] = {kEventParamATSUFontID
,
2815 kEventParamATSUFontSize
,
2816 kEventParamFMFontFamily
,
2817 kEventParamFMFontStyle
,
2818 kEventParamFMFontSize
,
2819 kEventParamFontColor
};
2820 static const EventParamType types_sel
[] = {typeATSUFontID
,
2827 result
= CallNextEventHandler (next_handler
, event
);
2828 if (result
!= eventNotHandledErr
)
2831 switch (GetEventKind (event
))
2833 case kEventFontPanelClosed
:
2834 id_key
= Qpanel_closed
;
2840 case kEventFontSelection
:
2841 id_key
= Qselection
;
2842 num_params
= sizeof (names_sel
) / sizeof (names_sel
[0]);
2848 err
= mac_store_event_ref_as_apple_event (0, 0, Qfont
, id_key
,
2857 /* Toggle visiblity of the font panel. */
2860 mac_show_hide_font_panel ()
2862 if (!font_panel_shown_p
)
2866 static const EventTypeSpec specs
[] =
2867 {{kEventClassFont
, kEventFontPanelClosed
},
2868 {kEventClassFont
, kEventFontSelection
}};
2870 err
= InstallApplicationEventHandler (mac_handle_font_event
,
2871 GetEventTypeCount (specs
),
2876 font_panel_shown_p
= 1;
2879 return FPShowHideFontPanel ();
2882 /* Set the font selected in the font panel to the one corresponding to
2883 the face FACE_ID and the charcacter C in the frame F. */
2886 mac_set_font_info_for_selection (f
, face_id
, c
)
2891 EventTargetRef target
= NULL
;
2892 XFontStruct
*font
= NULL
;
2894 if (!mac_font_panel_visible_p ())
2899 target
= GetWindowEventTarget (FRAME_MAC_WINDOW (f
));
2901 if (FRAME_FACE_CACHE (f
) && CHAR_VALID_P (c
, 0))
2905 face_id
= FACE_FOR_CHAR (f
, FACE_FROM_ID (f
, face_id
), c
);
2906 face
= FACE_FROM_ID (f
, face_id
);
2912 err
= SetFontInfoForSelection (kFontSelectionATSUIType
, 0, NULL
, target
);
2915 if (font
->mac_fontnum
!= -1)
2917 FontSelectionQDStyle qd_style
;
2919 qd_style
.version
= kFontSelectionQDStyleVersionZero
;
2920 qd_style
.instance
.fontFamily
= font
->mac_fontnum
;
2921 qd_style
.instance
.fontStyle
= font
->mac_fontface
;
2922 qd_style
.size
= font
->mac_fontsize
;
2923 qd_style
.hasColor
= false;
2925 err
= SetFontInfoForSelection (kFontSelectionQDType
,
2926 1, &qd_style
, target
);
2929 err
= SetFontInfoForSelection (kFontSelectionATSUIType
,
2930 1, &font
->mac_style
, target
);
2935 #endif /* USE_MAC_FONT_PANEL */
2938 /************************************************************************
2940 ************************************************************************/
2942 /* Non-zero means that a HELP_EVENT has been generated since Emacs
2945 static int any_help_event_p
;
2947 /* Last window where we saw the mouse. Used by mouse-autoselect-window. */
2948 static Lisp_Object last_window
;
2950 static Point saved_menu_event_location
;
2952 extern struct frame
*pending_autoraise_frame
;
2954 extern FRAME_PTR last_mouse_glyph_frame
;
2957 extern int volatile input_signal_count
;
2959 extern int input_signal_count
;
2962 extern int mac_screen_config_changed
;
2964 extern Lisp_Object Vmac_emulate_three_button_mouse
;
2965 #if TARGET_API_MAC_CARBON
2966 extern int mac_wheel_button_is_mouse_2
;
2967 extern int mac_pass_command_to_system
;
2968 extern int mac_pass_control_to_system
;
2969 #endif /* TARGET_API_MAC_CARBON */
2970 extern int mac_ready_for_apple_events
;
2972 extern void mac_focus_changed
P_ ((int, struct mac_display_info
*,
2973 struct frame
*, struct input_event
*));
2974 extern int mac_get_emulated_btn
P_ ((UInt32
));
2975 extern int note_mouse_movement
P_ ((FRAME_PTR
, Point
*));
2976 extern void mac_get_screen_info
P_ ((struct mac_display_info
*));
2978 /* The focus may have changed. Figure out if it is a real focus change,
2979 by checking both FocusIn/Out and Enter/LeaveNotify events.
2981 Returns FOCUS_IN_EVENT event in *BUFP. */
2984 x_detect_focus_change (dpyinfo
, event
, bufp
)
2985 struct mac_display_info
*dpyinfo
;
2986 const EventRecord
*event
;
2987 struct input_event
*bufp
;
2989 struct frame
*frame
;
2991 frame
= mac_window_to_frame ((WindowRef
) event
->message
);
2995 /* On Mac, this is only called from focus events, so no switch needed. */
2996 mac_focus_changed ((event
->modifiers
& activeFlag
),
2997 dpyinfo
, frame
, bufp
);
3000 #if TARGET_API_MAC_CARBON
3001 /* Obtains the event modifiers from the event EVENTREF and then calls
3002 mac_to_emacs_modifiers. */
3005 mac_event_to_emacs_modifiers (EventRef eventRef
)
3007 UInt32 mods
= 0, class;
3009 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
3010 sizeof (UInt32
), NULL
, &mods
);
3011 class = GetEventClass (eventRef
);
3012 if (!NILP (Vmac_emulate_three_button_mouse
) &&
3013 (class == kEventClassMouse
|| class == kEventClassCommand
))
3015 mods
&= ~(optionKey
| cmdKey
);
3017 return mac_to_emacs_modifiers (mods
, 0);
3020 /* Given an event REF, return the code to use for the mouse button
3021 code in the emacs input_event. */
3024 mac_get_mouse_btn (EventRef ref
)
3026 EventMouseButton result
= kEventMouseButtonPrimary
;
3027 GetEventParameter (ref
, kEventParamMouseButton
, typeMouseButton
, NULL
,
3028 sizeof (EventMouseButton
), NULL
, &result
);
3031 case kEventMouseButtonPrimary
:
3032 if (NILP (Vmac_emulate_three_button_mouse
))
3036 GetEventParameter (ref
, kEventParamKeyModifiers
, typeUInt32
, NULL
,
3037 sizeof (UInt32
), NULL
, &mods
);
3038 return mac_get_emulated_btn(mods
);
3040 case kEventMouseButtonSecondary
:
3041 return mac_wheel_button_is_mouse_2
? 2 : 1;
3042 case kEventMouseButtonTertiary
:
3043 case 4: /* 4 is the number for the mouse wheel button */
3044 return mac_wheel_button_is_mouse_2
? 1 : 2;
3050 /* Normally, ConvertEventRefToEventRecord will correctly handle all
3051 events. However the click of the mouse wheel is not converted to a
3052 mouseDown or mouseUp event. Likewise for dead key events. This
3053 calls ConvertEventRefToEventRecord, but then checks to see if it is
3054 a mouse up/down, or a dead key Carbon event that has not been
3055 converted, and if so, converts it by hand (to be picked up in the
3056 XTread_socket loop). */
3057 static Boolean
mac_convert_event_ref (EventRef eventRef
, EventRecord
*eventRec
)
3060 Boolean result
= ConvertEventRefToEventRecord (eventRef
, eventRec
);
3066 switch (GetEventClass (eventRef
))
3068 case kEventClassMouse
:
3069 switch (GetEventKind (eventRef
))
3071 case kEventMouseDown
:
3072 eventRec
->what
= mouseDown
;
3077 eventRec
->what
= mouseUp
;
3086 case kEventClassKeyboard
:
3087 switch (GetEventKind (eventRef
))
3089 case kEventRawKeyDown
:
3091 goto keystroke_common
;
3092 case kEventRawKeyRepeat
:
3094 goto keystroke_common
;
3095 case kEventRawKeyUp
:
3099 unsigned char char_codes
;
3102 err
= GetEventParameter (eventRef
, kEventParamKeyMacCharCodes
,
3103 typeChar
, NULL
, sizeof (char),
3106 err
= GetEventParameter (eventRef
, kEventParamKeyCode
,
3107 typeUInt32
, NULL
, sizeof (UInt32
),
3111 eventRec
->what
= action
;
3112 eventRec
->message
= char_codes
| ((key_code
& 0xff) << 8);
3129 /* Need where and when. */
3132 GetEventParameter (eventRef
, kEventParamMouseLocation
, typeQDPoint
,
3133 NULL
, sizeof (Point
), NULL
, &eventRec
->where
);
3134 /* Use two step process because new event modifiers are 32-bit
3135 and old are 16-bit. Currently, only loss is NumLock & Fn. */
3136 GetEventParameter (eventRef
, kEventParamKeyModifiers
, typeUInt32
,
3137 NULL
, sizeof (UInt32
), NULL
, &mods
);
3138 eventRec
->modifiers
= mods
;
3140 eventRec
->when
= EventTimeToTicks (GetEventTime (eventRef
));
3145 #endif /* TARGET_API_MAC_CARBON */
3147 #if !TARGET_API_MAC_CARBON
3148 static RgnHandle mouse_region
= NULL
;
3151 mac_wait_next_event (er
, sleep_time
, dequeue
)
3156 static EventRecord er_buf
= {nullEvent
};
3157 UInt32 target_tick
, current_tick
;
3158 EventMask event_mask
;
3160 if (mouse_region
== NULL
)
3161 mouse_region
= NewRgn ();
3163 event_mask
= everyEvent
;
3164 if (!mac_ready_for_apple_events
)
3165 event_mask
-= highLevelEventMask
;
3167 current_tick
= TickCount ();
3168 target_tick
= current_tick
+ sleep_time
;
3170 if (er_buf
.what
== nullEvent
)
3171 while (!WaitNextEvent (event_mask
, &er_buf
,
3172 target_tick
- current_tick
, mouse_region
))
3174 current_tick
= TickCount ();
3175 if (target_tick
<= current_tick
)
3181 er_buf
.what
= nullEvent
;
3184 #endif /* not TARGET_API_MAC_CARBON */
3186 #if TARGET_API_MAC_CARBON
3188 mac_post_mouse_moved_event ()
3190 EventRef event
= NULL
;
3193 err
= CreateEvent (NULL
, kEventClassMouse
, kEventMouseMoved
, 0,
3194 kEventAttributeNone
, &event
);
3199 GetGlobalMouse (&mouse_pos
);
3200 err
= SetEventParameter (event
, kEventParamMouseLocation
, typeQDPoint
,
3201 sizeof (Point
), &mouse_pos
);
3205 UInt32 modifiers
= GetCurrentKeyModifiers ();
3207 err
= SetEventParameter (event
, kEventParamKeyModifiers
, typeUInt32
,
3208 sizeof (UInt32
), &modifiers
);
3211 err
= PostEventToQueue (GetCurrentEventQueue (), event
,
3212 kEventPriorityStandard
);
3214 ReleaseEvent (event
);
3221 /* Run the current run loop in the default mode until some input
3222 happens or TIMEOUT seconds passes unless it is negative. Return
3223 true if timeout occurs first. */
3226 mac_run_loop_run_once (timeout
)
3227 EventTimeout timeout
;
3230 mac_prepare_for_quickdraw (NULL
);
3232 return (CFRunLoopRunInMode (kCFRunLoopDefaultMode
,
3233 timeout
>= 0 ? timeout
: 100000, true)
3234 == kCFRunLoopRunTimedOut
);
3238 /* Emacs calls this whenever it wants to read an input event from the
3242 XTread_socket (sd
, expected
, hold_quit
)
3244 struct input_event
*hold_quit
;
3246 struct input_event inev
;
3248 #if TARGET_API_MAC_CARBON
3250 EventTargetRef toolbox_dispatcher
;
3253 struct mac_display_info
*dpyinfo
= &one_mac_display_info
;
3255 if (interrupt_input_blocked
)
3257 interrupt_input_pending
= 1;
3261 interrupt_input_pending
= 0;
3264 /* So people can tell when we have read the available input. */
3265 input_signal_count
++;
3269 #if TARGET_API_MAC_CARBON
3270 toolbox_dispatcher
= GetEventDispatcherTarget ();
3274 mac_prepare_for_quickdraw (NULL
),
3276 !ReceiveNextEvent (0, NULL
, kEventDurationNoWait
,
3277 kEventRemoveFromQueue
, &eventRef
))
3278 #else /* !TARGET_API_MAC_CARBON */
3279 while (mac_wait_next_event (&er
, 0, true))
3280 #endif /* !TARGET_API_MAC_CARBON */
3284 unsigned long timestamp
;
3287 inev
.kind
= NO_EVENT
;
3290 #if TARGET_API_MAC_CARBON
3291 timestamp
= GetEventTime (eventRef
) / kEventDurationMillisecond
;
3293 if (!mac_convert_event_ref (eventRef
, &er
))
3295 #else /* !TARGET_API_MAC_CARBON */
3296 timestamp
= er
.when
* (1000 / 60); /* ticks to milliseconds */
3297 #endif /* !TARGET_API_MAC_CARBON */
3304 WindowRef window_ptr
;
3305 ControlPartCode part_code
;
3308 #if TARGET_API_MAC_CARBON
3311 /* This is needed to send mouse events like aqua window
3312 buttons to the correct handler. */
3313 read_socket_inev
= &inev
;
3314 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
3315 read_socket_inev
= NULL
;
3316 if (err
!= eventNotHandledErr
)
3319 last_mouse_glyph_frame
= 0;
3321 if (dpyinfo
->grabbed
&& last_mouse_frame
3322 && FRAME_LIVE_P (last_mouse_frame
))
3324 window_ptr
= FRAME_MAC_WINDOW (last_mouse_frame
);
3325 part_code
= inContent
;
3329 part_code
= FindWindow (er
.where
, &window_ptr
);
3330 if (tip_window
&& window_ptr
== tip_window
)
3332 HideWindow (tip_window
);
3333 part_code
= FindWindow (er
.where
, &window_ptr
);
3337 if (er
.what
!= mouseDown
3338 && (part_code
!= inContent
|| dpyinfo
->grabbed
== 0))
3344 f
= mac_focus_frame (dpyinfo
);
3345 saved_menu_event_location
= er
.where
;
3346 inev
.kind
= MENU_BAR_ACTIVATE_EVENT
;
3347 XSETFRAME (inev
.frame_or_window
, f
);
3352 #if TARGET_API_MAC_CARBON
3353 FrontNonFloatingWindow ()
3358 || (mac_window_to_frame (window_ptr
)
3359 != dpyinfo
->x_focus_frame
))
3360 SelectWindow (window_ptr
);
3363 ControlPartCode control_part_code
;
3367 ControlKind control_kind
;
3370 f
= mac_window_to_frame (window_ptr
);
3371 /* convert to local coordinates of new window */
3372 mouse_loc
.h
= (er
.where
.h
3374 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
3375 mouse_loc
.v
= (er
.where
.v
3377 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
3378 #if TARGET_API_MAC_CARBON
3379 ch
= FindControlUnderMouse (mouse_loc
, window_ptr
,
3380 &control_part_code
);
3383 GetControlKind (ch
, &control_kind
);
3386 control_part_code
= FindControl (mouse_loc
, window_ptr
,
3390 #if TARGET_API_MAC_CARBON
3391 inev
.code
= mac_get_mouse_btn (eventRef
);
3392 inev
.modifiers
= mac_event_to_emacs_modifiers (eventRef
);
3394 inev
.code
= mac_get_emulated_btn (er
.modifiers
);
3395 inev
.modifiers
= mac_to_emacs_modifiers (er
.modifiers
, 0);
3397 XSETINT (inev
.x
, mouse_loc
.h
);
3398 XSETINT (inev
.y
, mouse_loc
.v
);
3400 if ((dpyinfo
->grabbed
&& tracked_scroll_bar
)
3402 #ifndef USE_TOOLKIT_SCROLL_BARS
3403 /* control_part_code becomes kControlNoPart if
3404 a progress indicator is clicked. */
3405 && control_part_code
!= kControlNoPart
3406 #else /* USE_TOOLKIT_SCROLL_BARS */
3408 && control_kind
.kind
== kControlKindScrollBar
3409 #endif /* MAC_OSX */
3410 #endif /* USE_TOOLKIT_SCROLL_BARS */
3413 struct scroll_bar
*bar
;
3415 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
3417 bar
= tracked_scroll_bar
;
3418 #ifndef USE_TOOLKIT_SCROLL_BARS
3419 control_part_code
= kControlIndicatorPart
;
3423 bar
= (struct scroll_bar
*) GetControlReference (ch
);
3424 #ifdef USE_TOOLKIT_SCROLL_BARS
3425 /* Make the "Ctrl-Mouse-2 splits window" work
3426 for toolkit scroll bars. */
3427 if (inev
.modifiers
& ctrl_modifier
)
3428 x_scroll_bar_handle_click (bar
, control_part_code
,
3430 else if (er
.what
== mouseDown
)
3431 x_scroll_bar_handle_press (bar
, control_part_code
,
3434 x_scroll_bar_handle_release (bar
, &inev
);
3435 #else /* not USE_TOOLKIT_SCROLL_BARS */
3436 x_scroll_bar_handle_click (bar
, control_part_code
,
3438 if (er
.what
== mouseDown
3439 && control_part_code
== kControlIndicatorPart
)
3440 tracked_scroll_bar
= bar
;
3442 tracked_scroll_bar
= NULL
;
3443 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3448 int x
= mouse_loc
.h
;
3449 int y
= mouse_loc
.v
;
3451 window
= window_from_coordinates (f
, x
, y
, 0, 0, 0, 1);
3452 if (EQ (window
, f
->tool_bar_window
))
3454 if (er
.what
== mouseDown
)
3455 handle_tool_bar_click (f
, x
, y
, 1, 0);
3457 handle_tool_bar_click (f
, x
, y
, 0,
3463 XSETFRAME (inev
.frame_or_window
, f
);
3464 inev
.kind
= MOUSE_CLICK_EVENT
;
3468 if (er
.what
== mouseDown
)
3470 dpyinfo
->grabbed
|= (1 << inev
.code
);
3471 last_mouse_frame
= f
;
3474 last_tool_bar_item
= -1;
3478 if ((dpyinfo
->grabbed
& (1 << inev
.code
)) == 0)
3479 /* If a button is released though it was not
3480 previously pressed, that would be because
3481 of multi-button emulation. */
3482 dpyinfo
->grabbed
= 0;
3484 dpyinfo
->grabbed
&= ~(1 << inev
.code
);
3487 /* Ignore any mouse motion that happened before
3488 this event; any subsequent mouse-movement Emacs
3489 events should reflect only motion after the
3494 #ifdef USE_TOOLKIT_SCROLL_BARS
3495 if (inev
.kind
== MOUSE_CLICK_EVENT
3496 || (inev
.kind
== SCROLL_BAR_CLICK_EVENT
3497 && (inev
.modifiers
& ctrl_modifier
)))
3502 inev
.modifiers
|= down_modifier
;
3505 inev
.modifiers
|= up_modifier
;
3512 #if TARGET_API_MAC_CARBON
3514 if (IsWindowPathSelectClick (window_ptr
, &er
))
3516 WindowPathSelect (window_ptr
, NULL
, NULL
);
3519 if (part_code
== inProxyIcon
3520 && (TrackWindowProxyDrag (window_ptr
, er
.where
)
3521 != errUserWantsToDragWindow
))
3523 DragWindow (window_ptr
, er
.where
, NULL
);
3524 #else /* not TARGET_API_MAC_CARBON */
3525 DragWindow (window_ptr
, er
.where
, &qd
.screenBits
.bounds
);
3526 /* Update the frame parameters. */
3528 struct frame
*f
= mac_window_to_frame (window_ptr
);
3530 if (f
&& !f
->async_iconified
)
3531 mac_handle_origin_change (f
);
3533 #endif /* not TARGET_API_MAC_CARBON */
3537 if (TrackGoAway (window_ptr
, er
.where
))
3539 inev
.kind
= DELETE_WINDOW_EVENT
;
3540 XSETFRAME (inev
.frame_or_window
,
3541 mac_window_to_frame (window_ptr
));
3545 /* window resize handling added --ben */
3547 do_grow_window (window_ptr
, &er
);
3550 /* window zoom handling added --ben */
3553 if (TrackBox (window_ptr
, er
.where
, part_code
))
3554 do_zoom_window (window_ptr
, part_code
);
3563 err
= HIViewGetViewForMouseEvent (HIViewGetRoot (window_ptr
),
3565 /* This doesn't work on Mac OS X 10.2. */
3567 HIViewClick (ch
, eventRef
);
3570 #endif /* USE_MAC_TOOLBAR */
3578 #if !TARGET_API_MAC_CARBON
3580 do_window_update ((WindowRef
) er
.message
);
3585 #if TARGET_API_MAC_CARBON
3586 if (SendEventToEventTarget (eventRef
, toolbox_dispatcher
)
3587 != eventNotHandledErr
)
3590 switch ((er
.message
>> 24) & 0x000000FF)
3593 case suspendResumeMessage
:
3594 if (er
.message
& resumeFlag
)
3601 case mouseMovedMessage
:
3602 #if !TARGET_API_MAC_CARBON
3603 SetRectRgn (mouse_region
, er
.where
.h
, er
.where
.v
,
3604 er
.where
.h
+ 1, er
.where
.v
+ 1);
3606 previous_help_echo_string
= help_echo_string
;
3607 help_echo_string
= Qnil
;
3609 if (dpyinfo
->grabbed
&& last_mouse_frame
3610 && FRAME_LIVE_P (last_mouse_frame
))
3611 f
= last_mouse_frame
;
3613 f
= dpyinfo
->x_focus_frame
;
3615 if (dpyinfo
->mouse_face_hidden
)
3617 dpyinfo
->mouse_face_hidden
= 0;
3618 clear_mouse_face (dpyinfo
);
3623 WindowRef wp
= FRAME_MAC_WINDOW (f
);
3626 mouse_pos
.h
= (er
.where
.h
3628 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
3629 mouse_pos
.v
= (er
.where
.v
3631 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
3632 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
3633 #ifdef USE_TOOLKIT_SCROLL_BARS
3634 x_scroll_bar_handle_drag (wp
, tracked_scroll_bar
,
3636 #else /* not USE_TOOLKIT_SCROLL_BARS */
3637 x_scroll_bar_note_movement (tracked_scroll_bar
,
3639 - XINT (tracked_scroll_bar
->top
),
3640 er
.when
* (1000 / 60));
3641 #endif /* not USE_TOOLKIT_SCROLL_BARS */
3644 /* Generate SELECT_WINDOW_EVENTs when needed. */
3645 if (!NILP (Vmouse_autoselect_window
))
3649 window
= window_from_coordinates (f
,
3654 /* Window will be selected only when it is
3655 not selected now and last mouse movement
3656 event was not in it. Minibuffer window
3657 will be selected only when it is active. */
3658 if (WINDOWP (window
)
3659 && !EQ (window
, last_window
)
3660 && !EQ (window
, selected_window
)
3661 /* For click-to-focus window managers
3662 create event iff we don't leave the
3664 && (focus_follows_mouse
3665 || (EQ (XWINDOW (window
)->frame
,
3666 XWINDOW (selected_window
)->frame
))))
3668 inev
.kind
= SELECT_WINDOW_EVENT
;
3669 inev
.frame_or_window
= window
;
3674 if (!note_mouse_movement (f
, &mouse_pos
))
3675 help_echo_string
= previous_help_echo_string
;
3678 mac_tool_bar_note_mouse_movement (f
, eventRef
);
3683 /* If the contents of the global variable
3684 help_echo_string has changed, generate a
3686 if (!NILP (help_echo_string
) || !NILP (previous_help_echo_string
))
3694 WindowRef window_ptr
= (WindowRef
) er
.message
;
3696 ControlRef root_control
;
3698 if (window_ptr
== tip_window
)
3700 HideWindow (tip_window
);
3704 if (!is_emacs_window (window_ptr
))
3707 f
= mac_window_to_frame (window_ptr
);
3709 if ((er
.modifiers
& activeFlag
) != 0)
3711 /* A window has been activated */
3714 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3716 ActivateControl (root_control
);
3718 x_detect_focus_change (dpyinfo
, &er
, &inev
);
3720 mouse_loc
.h
= (er
.where
.h
3722 + FRAME_OUTER_TO_INNER_DIFF_X (f
)));
3723 mouse_loc
.v
= (er
.where
.v
3725 + FRAME_OUTER_TO_INNER_DIFF_Y (f
)));
3726 /* Window-activated event counts as mouse movement,
3727 so update things that depend on mouse position. */
3728 note_mouse_movement (f
, &mouse_loc
);
3732 /* A window has been deactivated */
3733 err
= GetRootControl (FRAME_MAC_WINDOW (f
), &root_control
);
3735 DeactivateControl (root_control
);
3737 #ifdef USE_TOOLKIT_SCROLL_BARS
3738 if (dpyinfo
->grabbed
&& tracked_scroll_bar
)
3740 struct input_event event
;
3743 event
.kind
= NO_EVENT
;
3744 x_scroll_bar_handle_release (tracked_scroll_bar
, &event
);
3745 if (event
.kind
!= NO_EVENT
)
3747 event
.timestamp
= timestamp
;
3748 kbd_buffer_store_event_hold (&event
, hold_quit
);
3753 dpyinfo
->grabbed
= 0;
3755 x_detect_focus_change (dpyinfo
, &er
, &inev
);
3757 if (f
== dpyinfo
->mouse_face_mouse_frame
)
3759 /* If we move outside the frame, then we're
3760 certainly no longer on any text in the
3762 clear_mouse_face (dpyinfo
);
3763 dpyinfo
->mouse_face_mouse_frame
= 0;
3766 /* Generate a nil HELP_EVENT to cancel a help-echo.
3767 Do it only if there's something to cancel.
3768 Otherwise, the startup message is cleared when the
3769 mouse leaves the frame. */
3770 if (any_help_event_p
)
3781 f
= mac_focus_frame (dpyinfo
);
3782 XSETFRAME (inev
.frame_or_window
, f
);
3784 /* If mouse-highlight is an integer, input clears out mouse
3786 if (!dpyinfo
->mouse_face_hidden
&& INTEGERP (Vmouse_highlight
)
3787 && !EQ (f
->tool_bar_window
, dpyinfo
->mouse_face_window
))
3789 clear_mouse_face (dpyinfo
);
3790 dpyinfo
->mouse_face_hidden
= 1;
3794 UInt32 modifiers
= er
.modifiers
, mapped_modifiers
;
3795 UInt32 key_code
= (er
.message
& keyCodeMask
) >> 8;
3798 GetEventParameter (eventRef
, kEventParamKeyModifiers
,
3800 sizeof (UInt32
), NULL
, &modifiers
);
3802 mapped_modifiers
= mac_mapped_modifiers (modifiers
, key_code
);
3804 #if TARGET_API_MAC_CARBON
3805 if (!(mapped_modifiers
3806 & ~(mac_pass_command_to_system
? cmdKey
: 0)
3807 & ~(mac_pass_control_to_system
? controlKey
: 0)))
3811 if (er
.what
!= keyUp
)
3812 do_keystroke (er
.what
, er
.message
& charCodeMask
,
3813 key_code
, modifiers
, timestamp
, &inev
);
3817 case kHighLevelEvent
:
3818 AEProcessAppleEvent (&er
);
3823 #if TARGET_API_MAC_CARBON
3827 read_socket_inev
= &inev
;
3828 err
= SendEventToEventTarget (eventRef
, toolbox_dispatcher
);
3829 read_socket_inev
= NULL
;
3834 #if TARGET_API_MAC_CARBON
3835 ReleaseEvent (eventRef
);
3838 if (inev
.kind
!= NO_EVENT
)
3840 inev
.timestamp
= timestamp
;
3841 kbd_buffer_store_event_hold (&inev
, hold_quit
);
3846 && !(hold_quit
&& hold_quit
->kind
!= NO_EVENT
))
3851 XSETFRAME (frame
, f
);
3857 any_help_event_p
= 1;
3858 gen_help_event (help_echo_string
, frame
, help_echo_window
,
3859 help_echo_object
, help_echo_pos
);
3863 help_echo_string
= Qnil
;
3864 gen_help_event (Qnil
, frame
, Qnil
, Qnil
, 0);
3870 /* If the focus was just given to an autoraising frame,
3872 /* ??? This ought to be able to handle more than one such frame. */
3873 if (pending_autoraise_frame
)
3875 x_raise_frame (pending_autoraise_frame
);
3876 pending_autoraise_frame
= 0;
3879 if (mac_screen_config_changed
)
3881 mac_get_screen_info (dpyinfo
);
3882 mac_screen_config_changed
= 0;
3885 #if !TARGET_API_MAC_CARBON
3886 /* Check which frames are still visible. We do this here because
3887 there doesn't seem to be any direct notification from the Window
3888 Manager that the visibility of a window has changed (at least,
3889 not in all cases). */
3891 Lisp_Object tail
, frame
;
3893 FOR_EACH_FRAME (tail
, frame
)
3895 struct frame
*f
= XFRAME (frame
);
3897 /* The tooltip has been drawn already. Avoid the
3898 SET_FRAME_GARBAGED in mac_handle_visibility_change. */
3899 if (EQ (frame
, tip_frame
))
3902 if (FRAME_MAC_P (f
))
3903 mac_handle_visibility_change (f
);
3914 /***********************************************************************
3916 ***********************************************************************/
3918 #if TARGET_API_MAC_CARBON
3919 /* Show the spinning progress indicator for the frame F. Create it if
3920 it doesn't exist yet. */
3923 mac_show_hourglass (f
)
3927 mac_prepare_for_quickdraw (f
);
3929 if (!f
->output_data
.mac
->hourglass_control
)
3931 Window w
= FRAME_MAC_WINDOW (f
);
3935 GetWindowPortBounds (w
, &r
);
3936 r
.left
= r
.right
- HOURGLASS_WIDTH
;
3937 r
.bottom
= r
.top
+ HOURGLASS_HEIGHT
;
3938 if (CreateChasingArrowsControl (w
, &r
, &c
) == noErr
)
3939 f
->output_data
.mac
->hourglass_control
= c
;
3942 if (f
->output_data
.mac
->hourglass_control
)
3943 ShowControl (f
->output_data
.mac
->hourglass_control
);
3946 /* Hide the spinning progress indicator for the frame F. Do nothing
3947 it doesn't exist yet. */
3950 mac_hide_hourglass (f
)
3953 if (f
->output_data
.mac
->hourglass_control
)
3956 mac_prepare_for_quickdraw (f
);
3958 HideControl (f
->output_data
.mac
->hourglass_control
);
3962 /* Reposition the spinning progress indicator for the frame F. Do
3963 nothing it doesn't exist yet. */
3966 mac_reposition_hourglass (f
)
3969 if (f
->output_data
.mac
->hourglass_control
)
3972 mac_prepare_for_quickdraw (f
);
3974 MoveControl (f
->output_data
.mac
->hourglass_control
,
3975 FRAME_PIXEL_WIDTH (f
) - HOURGLASS_WIDTH
, 0);
3978 #endif /* TARGET_API_MAC_CARBON */
3981 /***********************************************************************
3982 File selection dialog
3983 ***********************************************************************/
3985 #if TARGET_API_MAC_CARBON
3986 extern Lisp_Object Qfile_name_history
;
3988 static pascal void mac_nav_event_callback
P_ ((NavEventCallbackMessage
,
3989 NavCBRecPtr
, void *));
3991 /* The actual implementation of Fx_file_dialog. */
3994 mac_file_dialog (prompt
, dir
, default_filename
, mustmatch
, only_dir_p
)
3995 Lisp_Object prompt
, dir
, default_filename
, mustmatch
, only_dir_p
;
3997 Lisp_Object file
= Qnil
;
3998 int count
= SPECPDL_INDEX ();
3999 struct gcpro gcpro1
, gcpro2
, gcpro3
, gcpro4
, gcpro5
, gcpro6
;
4000 char filename
[MAXPATHLEN
];
4001 static NavEventUPP mac_nav_event_callbackUPP
= NULL
;
4005 GCPRO6 (prompt
, dir
, default_filename
, mustmatch
, file
, only_dir_p
);
4006 CHECK_STRING (prompt
);
4009 /* Create the dialog with PROMPT as title, using DIR as initial
4010 directory and using "*" as pattern. */
4011 dir
= Fexpand_file_name (dir
, Qnil
);
4015 NavDialogCreationOptions options
;
4016 NavDialogRef dialogRef
;
4017 NavTypeListHandle fileTypes
= NULL
;
4018 NavUserAction userAction
;
4019 CFStringRef message
=NULL
, saveName
= NULL
;
4022 /* No need for a callback function because we are modal */
4023 NavGetDefaultDialogCreationOptions(&options
);
4024 options
.modality
= kWindowModalityAppModal
;
4025 options
.location
.h
= options
.location
.v
= -1;
4026 options
.optionFlags
= kNavDefaultNavDlogOptions
;
4027 options
.optionFlags
|= kNavAllFilesInPopup
; /* All files allowed */
4028 options
.optionFlags
|= kNavSelectAllReadableItem
;
4029 options
.optionFlags
&= ~kNavAllowMultipleFiles
;
4032 message
= cfstring_create_with_string (prompt
);
4033 options
.message
= message
;
4035 /* Don't set the application, let it use default.
4036 options.clientName = CFSTR ("Emacs");
4039 if (mac_nav_event_callbackUPP
== NULL
)
4040 mac_nav_event_callbackUPP
= NewNavEventUPP (mac_nav_event_callback
);
4042 if (!NILP (only_dir_p
))
4043 status
= NavCreateChooseFolderDialog(&options
, mac_nav_event_callbackUPP
,
4044 NULL
, NULL
, &dialogRef
);
4045 else if (NILP (mustmatch
))
4047 /* This is a save dialog */
4048 options
.optionFlags
|= kNavDontConfirmReplacement
;
4049 options
.actionButtonLabel
= CFSTR ("Ok");
4050 options
.windowTitle
= CFSTR ("Enter name");
4052 if (STRINGP (default_filename
))
4054 Lisp_Object utf8
= ENCODE_UTF_8 (default_filename
);
4055 char *begPtr
= SDATA(utf8
);
4056 char *filePtr
= begPtr
+ SBYTES(utf8
);
4057 while (filePtr
!= begPtr
&& !IS_DIRECTORY_SEP(filePtr
[-1]))
4059 saveName
= cfstring_create_with_utf8_cstring (filePtr
);
4060 options
.saveFileName
= saveName
;
4061 options
.optionFlags
|= kNavSelectDefaultLocation
;
4063 status
= NavCreatePutFileDialog(&options
,
4064 'TEXT', kNavGenericSignature
,
4065 mac_nav_event_callbackUPP
, NULL
,
4070 /* This is an open dialog*/
4071 status
= NavCreateChooseFileDialog(&options
, fileTypes
,
4072 mac_nav_event_callbackUPP
, NULL
,
4073 NULL
, NULL
, &dialogRef
);
4076 /* Set the default location and continue*/
4077 if (status
== noErr
)
4079 Lisp_Object encoded_dir
= ENCODE_FILE (dir
);
4082 status
= AECreateDesc (TYPE_FILE_NAME
, SDATA (encoded_dir
),
4083 SBYTES (encoded_dir
), &defLocAed
);
4084 if (status
== noErr
)
4086 NavCustomControl(dialogRef
, kNavCtlSetLocation
, (void*) &defLocAed
);
4087 AEDisposeDesc(&defLocAed
);
4089 status
= NavDialogRun(dialogRef
);
4092 if (saveName
) CFRelease(saveName
);
4093 if (message
) CFRelease(message
);
4095 if (status
== noErr
) {
4096 userAction
= NavDialogGetUserAction(dialogRef
);
4099 case kNavUserActionNone
:
4100 case kNavUserActionCancel
:
4101 break; /* Treat cancel like C-g */
4102 case kNavUserActionOpen
:
4103 case kNavUserActionChoose
:
4104 case kNavUserActionSaveAs
:
4106 NavReplyRecord reply
;
4109 status
= NavDialogGetReply(dialogRef
, &reply
);
4110 if (status
!= noErr
)
4112 status
= AEGetNthPtr (&reply
.selection
, 1, TYPE_FILE_NAME
,
4113 NULL
, NULL
, filename
,
4114 sizeof (filename
) - 1, &len
);
4115 if (status
== noErr
)
4117 len
= min (len
, sizeof (filename
) - 1);
4118 filename
[len
] = '\0';
4119 if (reply
.saveFileName
)
4121 /* If it was a saved file, we need to add the file name */
4122 if (len
&& len
< sizeof (filename
) - 1
4123 && filename
[len
-1] != '/')
4124 filename
[len
++] = '/';
4125 CFStringGetCString(reply
.saveFileName
, filename
+len
,
4126 sizeof (filename
) - len
,
4128 kCFStringEncodingUTF8
4130 CFStringGetSystemEncoding ()
4134 file
= DECODE_FILE (make_unibyte_string (filename
,
4135 strlen (filename
)));
4137 NavDisposeReply(&reply
);
4141 NavDialogDispose(dialogRef
);
4146 /* Fall back on minibuffer if there was a problem */
4147 file
= Fcompleting_read (prompt
, intern ("read-file-name-internal"),
4148 dir
, mustmatch
, dir
, Qfile_name_history
,
4149 default_filename
, Qnil
);
4155 /* Make "Cancel" equivalent to C-g. */
4157 Fsignal (Qquit
, Qnil
);
4159 return unbind_to (count
, file
);
4162 /* Need to register some event callback function for enabling drag and
4163 drop in Navigation Service dialogs. */
4165 mac_nav_event_callback (selector
, parms
, data
)
4166 NavEventCallbackMessage selector
;
4174 /************************************************************************
4176 ************************************************************************/
4178 #if !TARGET_API_MAC_CARBON
4179 #include <MacTypes.h>
4181 #include <Quickdraw.h>
4182 #include <ToolUtils.h>
4184 #include <Controls.h>
4185 #include <Windows.h>
4187 #if defined (__MRC__) || (__MSL__ >= 0x6000)
4188 #include <ControlDefinitions.h>
4190 #endif /* not TARGET_API_MAC_CARBON */
4192 extern int menu_item_selection
;
4193 extern int popup_activated_flag
;
4194 extern int name_is_separator
P_ ((const char *));
4195 extern void find_and_call_menu_selection
P_ ((FRAME_PTR
, int, Lisp_Object
,
4197 extern void set_frame_menubar
P_ ((FRAME_PTR
, int, int));
4199 enum mac_menu_kind
{ /* Menu ID range */
4200 MAC_MENU_APPLE
, /* 0 (Reserved by Apple) */
4201 MAC_MENU_MENU_BAR
, /* 1 .. 233 */
4202 MAC_MENU_M_APPLE
, /* 234 (== M_APPLE) */
4203 MAC_MENU_POPUP
, /* 235 */
4204 MAC_MENU_DRIVER
, /* 236 .. 255 (Reserved) */
4205 MAC_MENU_MENU_BAR_SUB
, /* 256 .. 16383 */
4206 MAC_MENU_POPUP_SUB
, /* 16384 .. 32767 */
4207 MAC_MENU_END
/* 32768 */
4210 static const int min_menu_id
[] = {0, 1, 234, 235, 236, 256, 16384, 32768};
4212 static int fill_menu
P_ ((MenuRef
, widget_value
*, enum mac_menu_kind
, int));
4213 static void dispose_menus
P_ ((enum mac_menu_kind
, int));
4215 #if !TARGET_API_MAC_CARBON
4217 do_apple_menu (SInt16 menu_item
)
4220 SInt16 da_driver_refnum
;
4222 if (menu_item
== I_ABOUT
)
4223 NoteAlert (ABOUT_ALERT_ID
, NULL
);
4226 GetMenuItemText (GetMenuRef (M_APPLE
), menu_item
, item_name
);
4227 da_driver_refnum
= OpenDeskAcc (item_name
);
4230 #endif /* !TARGET_API_MAC_CARBON */
4232 /* Activate the menu bar of frame F.
4233 This is called from keyboard.c when it gets the
4234 MENU_BAR_ACTIVATE_EVENT out of the Emacs event queue.
4236 To activate the menu bar, we use the button-press event location
4237 that was saved in saved_menu_event_location.
4239 But first we recompute the menu bar contents (the whole tree).
4241 The reason for saving the button event until here, instead of
4242 passing it to the toolkit right away, is that we can safely
4243 execute Lisp code. */
4246 x_activate_menubar (f
)
4250 SInt16 menu_id
, menu_item
;
4251 extern Point saved_menu_event_location
;
4253 set_frame_menubar (f
, 0, 1);
4256 popup_activated_flag
= 1;
4257 menu_choice
= MenuSelect (saved_menu_event_location
);
4258 popup_activated_flag
= 0;
4259 menu_id
= HiWord (menu_choice
);
4260 menu_item
= LoWord (menu_choice
);
4262 #if !TARGET_API_MAC_CARBON
4263 if (menu_id
== min_menu_id
[MAC_MENU_M_APPLE
])
4264 do_apple_menu (menu_item
);
4269 MenuRef menu
= GetMenuRef (menu_id
);
4275 GetMenuItemRefCon (menu
, menu_item
, &refcon
);
4276 find_and_call_menu_selection (f
, f
->menu_bar_items_used
,
4277 f
->menu_bar_vector
, (void *) refcon
);
4286 #if TARGET_API_MAC_CARBON
4287 extern Lisp_Object Vshow_help_function
;
4290 restore_show_help_function (old_show_help_function
)
4291 Lisp_Object old_show_help_function
;
4293 Vshow_help_function
= old_show_help_function
;
4298 static pascal OSStatus
4299 menu_target_item_handler (next_handler
, event
, data
)
4300 EventHandlerCallRef next_handler
;
4306 MenuItemIndex menu_item
;
4309 int specpdl_count
= SPECPDL_INDEX ();
4311 /* Don't be bothered with the overflowed toolbar items menu. */
4312 if (!popup_activated ())
4313 return eventNotHandledErr
;
4315 err
= GetEventParameter (event
, kEventParamDirectObject
, typeMenuRef
,
4316 NULL
, sizeof (MenuRef
), NULL
, &menu
);
4318 err
= GetEventParameter (event
, kEventParamMenuItemIndex
,
4319 typeMenuItemIndex
, NULL
,
4320 sizeof (MenuItemIndex
), NULL
, &menu_item
);
4322 err
= GetMenuItemProperty (menu
, menu_item
,
4323 MAC_EMACS_CREATOR_CODE
, 'help',
4324 sizeof (Lisp_Object
), NULL
, &help
);
4328 /* Temporarily bind Vshow_help_function to Qnil because we don't
4329 want tooltips during menu tracking. */
4330 record_unwind_protect (restore_show_help_function
, Vshow_help_function
);
4331 Vshow_help_function
= Qnil
;
4333 show_help_echo (help
, Qnil
, Qnil
, Qnil
, 1);
4335 unbind_to (specpdl_count
, Qnil
);
4337 return err
== noErr
? noErr
: eventNotHandledErr
;
4340 /* Showing help echo string during menu tracking. */
4343 install_menu_target_item_handler ()
4345 static const EventTypeSpec specs
[] =
4346 {{kEventClassMenu
, kEventMenuTargetItem
}};
4348 return InstallApplicationEventHandler (NewEventHandlerUPP
4349 (menu_target_item_handler
),
4350 GetEventTypeCount (specs
),
4353 #endif /* TARGET_API_MAC_CARBON */
4355 /* Event handler function that pops down a menu on C-g. We can only pop
4356 down menus if CancelMenuTracking is present (OSX 10.3 or later). */
4358 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
4359 static pascal OSStatus
4360 menu_quit_handler (nextHandler
, theEvent
, userData
)
4361 EventHandlerCallRef nextHandler
;
4367 UInt32 keyModifiers
;
4369 err
= GetEventParameter (theEvent
, kEventParamKeyCode
,
4370 typeUInt32
, NULL
, sizeof(UInt32
), NULL
, &keyCode
);
4373 err
= GetEventParameter (theEvent
, kEventParamKeyModifiers
,
4374 typeUInt32
, NULL
, sizeof(UInt32
),
4375 NULL
, &keyModifiers
);
4377 if (err
== noErr
&& mac_quit_char_key_p (keyModifiers
, keyCode
))
4379 MenuRef menu
= userData
!= 0
4380 ? (MenuRef
)userData
: AcquireRootMenu ();
4382 CancelMenuTracking (menu
, true, 0);
4383 if (!userData
) ReleaseMenu (menu
);
4387 return CallNextEventHandler (nextHandler
, theEvent
);
4389 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
4391 /* Add event handler to all menus that belong to KIND so we can detect
4392 C-g. ROOT_MENU is the root menu of the tracking session to dismiss
4393 when C-g is detected. NULL means the menu bar. If
4394 CancelMenuTracking isn't available, do nothing. */
4397 install_menu_quit_handler (kind
, root_menu
)
4398 enum mac_menu_kind kind
;
4401 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030
4402 static const EventTypeSpec typesList
[] =
4403 {{kEventClassKeyboard
, kEventRawKeyDown
}};
4406 #if MAC_OS_X_VERSION_MIN_REQUIRED == 1020
4407 if (CancelMenuTracking
== NULL
)
4410 for (id
= min_menu_id
[kind
]; id
< min_menu_id
[kind
+ 1]; id
++)
4412 MenuRef menu
= GetMenuRef (id
);
4416 InstallMenuEventHandler (menu
, menu_quit_handler
,
4417 GetEventTypeCount (typesList
),
4418 typesList
, root_menu
, NULL
);
4420 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */
4427 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
4428 FRAME_PTR f
= p
->pointer
;
4429 MenuRef menu
= GetMenuRef (min_menu_id
[MAC_MENU_POPUP
]);
4433 /* Must reset this manually because the button release event is not
4434 passed to Emacs event loop. */
4435 FRAME_MAC_DISPLAY_INFO (f
)->grabbed
= 0;
4437 /* delete all menus */
4438 dispose_menus (MAC_MENU_POPUP_SUB
, 0);
4439 DeleteMenu (min_menu_id
[MAC_MENU_POPUP
]);
4447 /* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop
4448 until the menu pops down. Return the selection. */
4451 create_and_show_popup_menu (f
, first_wv
, x
, y
, for_click
)
4453 widget_value
*first_wv
;
4459 MenuRef menu
= NewMenu (min_menu_id
[MAC_MENU_POPUP
], "\p");
4460 int menu_item_choice
;
4461 int specpdl_count
= SPECPDL_INDEX ();
4463 InsertMenu (menu
, -1);
4464 fill_menu (menu
, first_wv
->contents
, MAC_MENU_POPUP_SUB
,
4465 min_menu_id
[MAC_MENU_POPUP_SUB
]);
4467 /* Add event handler so we can detect C-g. */
4468 install_menu_quit_handler (MAC_MENU_POPUP
, menu
);
4469 install_menu_quit_handler (MAC_MENU_POPUP_SUB
, menu
);
4471 record_unwind_protect (pop_down_menu
, make_save_value (f
, 0));
4473 /* Adjust coordinates to be root-window-relative. */
4474 x
+= f
->left_pos
+ FRAME_OUTER_TO_INNER_DIFF_X (f
);
4475 y
+= f
->top_pos
+ FRAME_OUTER_TO_INNER_DIFF_Y (f
);
4477 /* Display the menu. */
4478 popup_activated_flag
= 1;
4479 menu_item_choice
= PopUpMenuSelect (menu
, y
, x
, 0);
4480 popup_activated_flag
= 0;
4482 /* Get the refcon to find the correct item */
4483 if (menu_item_choice
)
4485 MenuRef sel_menu
= GetMenuRef (HiWord (menu_item_choice
));
4488 GetMenuItemRefCon (sel_menu
, LoWord (menu_item_choice
),
4489 (UInt32
*) &result
);
4492 unbind_to (specpdl_count
, Qnil
);
4494 menu_item_selection
= result
;
4498 add_menu_item (menu
, pos
, wv
)
4503 #if TARGET_API_MAC_CARBON
4504 CFStringRef item_name
;
4509 if (name_is_separator (wv
->name
))
4510 AppendMenu (menu
, "\p-");
4513 AppendMenu (menu
, "\pX");
4515 #if TARGET_API_MAC_CARBON
4516 item_name
= cfstring_create_with_utf8_cstring (wv
->name
);
4518 if (wv
->key
!= NULL
)
4520 CFStringRef name
, key
;
4523 key
= cfstring_create_with_utf8_cstring (wv
->key
);
4524 item_name
= CFStringCreateWithFormat (NULL
, NULL
, CFSTR ("%@ %@"),
4530 SetMenuItemTextWithCFString (menu
, pos
, item_name
);
4531 CFRelease (item_name
);
4534 EnableMenuItem (menu
, pos
);
4536 DisableMenuItem (menu
, pos
);
4538 if (STRINGP (wv
->help
))
4539 SetMenuItemProperty (menu
, pos
, MAC_EMACS_CREATOR_CODE
, 'help',
4540 sizeof (Lisp_Object
), &wv
->help
);
4541 #else /* ! TARGET_API_MAC_CARBON */
4542 item_name
[sizeof (item_name
) - 1] = '\0';
4543 strncpy (item_name
, wv
->name
, sizeof (item_name
) - 1);
4544 if (wv
->key
!= NULL
)
4546 int len
= strlen (item_name
);
4548 strncpy (item_name
+ len
, " ", sizeof (item_name
) - 1 - len
);
4549 len
= strlen (item_name
);
4550 strncpy (item_name
+ len
, wv
->key
, sizeof (item_name
) - 1 - len
);
4553 SetMenuItemText (menu
, pos
, item_name
);
4556 EnableItem (menu
, pos
);
4558 DisableItem (menu
, pos
);
4559 #endif /* ! TARGET_API_MAC_CARBON */
4561 /* Draw radio buttons and tickboxes. */
4562 if (wv
->selected
&& (wv
->button_type
== BUTTON_TYPE_TOGGLE
4563 || wv
->button_type
== BUTTON_TYPE_RADIO
))
4564 SetItemMark (menu
, pos
, checkMark
);
4566 SetItemMark (menu
, pos
, noMark
);
4568 SetMenuItemRefCon (menu
, pos
, (UInt32
) wv
->call_data
);
4572 /* Construct native Mac OS menu based on widget_value tree. */
4575 fill_menu (menu
, wv
, kind
, submenu_id
)
4578 enum mac_menu_kind kind
;
4583 for (pos
= 1; wv
!= NULL
; wv
= wv
->next
, pos
++)
4585 add_menu_item (menu
, pos
, wv
);
4586 if (wv
->contents
&& submenu_id
< min_menu_id
[kind
+ 1])
4588 MenuRef submenu
= NewMenu (submenu_id
, "\pX");
4590 InsertMenu (submenu
, -1);
4591 #if TARGET_API_MAC_CARBON
4592 SetMenuItemHierarchicalMenu (menu
, pos
, submenu
);
4594 SetMenuItemHierarchicalID (menu
, pos
, submenu_id
);
4596 submenu_id
= fill_menu (submenu
, wv
->contents
, kind
, submenu_id
+ 1);
4603 /* Fill menu bar with the items defined by WV. If DEEP_P, consider
4604 the entire menu trees we supply, rather than just the menu bar item
4608 mac_fill_menubar (wv
, deep_p
)
4613 #if !TARGET_API_MAC_CARBON
4614 int title_changed_p
= 0;
4617 /* Clean up the menu bar when filled by the entire menu trees. */
4620 dispose_menus (MAC_MENU_MENU_BAR
, 0);
4621 dispose_menus (MAC_MENU_MENU_BAR_SUB
, 0);
4622 #if !TARGET_API_MAC_CARBON
4623 title_changed_p
= 1;
4627 /* Fill menu bar titles and submenus. Reuse the existing menu bar
4628 titles as much as possible to minimize redraw (if !deep_p). */
4629 submenu_id
= min_menu_id
[MAC_MENU_MENU_BAR_SUB
];
4630 for (id
= min_menu_id
[MAC_MENU_MENU_BAR
];
4631 wv
!= NULL
&& id
< min_menu_id
[MAC_MENU_MENU_BAR
+ 1];
4632 wv
= wv
->next
, id
++)
4634 OSStatus err
= noErr
;
4636 #if TARGET_API_MAC_CARBON
4639 title
= CFStringCreateWithCString (NULL
, wv
->name
,
4640 kCFStringEncodingMacRoman
);
4644 strncpy (title
, wv
->name
, 255);
4649 menu
= GetMenuRef (id
);
4652 #if TARGET_API_MAC_CARBON
4653 CFStringRef old_title
;
4655 err
= CopyMenuTitleAsCFString (menu
, &old_title
);
4658 if (CFStringCompare (title
, old_title
, 0) != kCFCompareEqualTo
)
4661 if (id
+ 1 == min_menu_id
[MAC_MENU_MENU_BAR
+ 1]
4662 || GetMenuRef (id
+ 1) == NULL
)
4664 /* This is a workaround for Mac OS X 10.5 where
4665 just calling SetMenuTitleWithCFString fails
4666 to change the title of the last (Help) menu
4673 #endif /* MAC_OSX */
4674 err
= SetMenuTitleWithCFString (menu
, title
);
4676 CFRelease (old_title
);
4679 err
= SetMenuTitleWithCFString (menu
, title
);
4680 #else /* !TARGET_API_MAC_CARBON */
4681 if (!EqualString (title
, (*menu
)->menuData
, false, false))
4685 menu
= NewMenu (id
, title
);
4686 InsertMenu (menu
, GetMenuRef (id
+ 1) ? id
+ 1 : 0);
4687 title_changed_p
= 1;
4689 #endif /* !TARGET_API_MAC_CARBON */
4694 #if TARGET_API_MAC_CARBON
4695 err
= CreateNewMenu (id
, 0, &menu
);
4697 err
= SetMenuTitleWithCFString (menu
, title
);
4699 menu
= NewMenu (id
, title
);
4703 InsertMenu (menu
, 0);
4704 #if !TARGET_API_MAC_CARBON
4705 title_changed_p
= 1;
4709 #if TARGET_API_MAC_CARBON
4715 submenu_id
= fill_menu (menu
, wv
->contents
, MAC_MENU_MENU_BAR_SUB
,
4719 if (id
< min_menu_id
[MAC_MENU_MENU_BAR
+ 1] && GetMenuRef (id
))
4721 dispose_menus (MAC_MENU_MENU_BAR
, id
);
4722 #if !TARGET_API_MAC_CARBON
4723 title_changed_p
= 1;
4727 #if !TARGET_API_MAC_CARBON
4728 if (title_changed_p
)
4732 /* Add event handler so we can detect C-g. */
4733 install_menu_quit_handler (MAC_MENU_MENU_BAR
, NULL
);
4734 install_menu_quit_handler (MAC_MENU_MENU_BAR_SUB
, NULL
);
4737 /* Dispose of menus that belong to KIND, and remove them from the menu
4738 list. ID is the lower bound of menu IDs that will be processed. */
4741 dispose_menus (kind
, id
)
4742 enum mac_menu_kind kind
;
4745 for (id
= max (id
, min_menu_id
[kind
]); id
< min_menu_id
[kind
+ 1]; id
++)
4747 MenuRef menu
= GetMenuRef (id
);
4762 MenuItemIndex menu_index
;
4764 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandQuit
, 1,
4765 &menu
, &menu_index
);
4767 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
4768 EnableMenuCommand (NULL
, kHICommandPreferences
);
4769 err
= GetIndMenuItemWithCommandID (NULL
, kHICommandPreferences
, 1,
4770 &menu
, &menu_index
);
4773 SetMenuItemCommandKey (menu
, menu_index
, false, 0);
4774 InsertMenuItemTextWithCFString (menu
, NULL
,
4775 0, kMenuItemAttrSeparator
, 0);
4776 InsertMenuItemTextWithCFString (menu
, CFSTR ("About Emacs"),
4777 0, 0, kHICommandAbout
);
4779 #else /* !MAC_OSX */
4780 #if TARGET_API_MAC_CARBON
4781 SetMenuItemCommandID (GetMenuRef (M_APPLE
), I_ABOUT
, kHICommandAbout
);
4787 /***********************************************************************
4789 ***********************************************************************/
4791 #if TARGET_API_MAC_CARBON
4792 #define DIALOG_BUTTON_COMMAND_ID_OFFSET 'Bt\0\0'
4793 #define DIALOG_BUTTON_COMMAND_ID_P(id) \
4794 (((id) & ~0xffff) == DIALOG_BUTTON_COMMAND_ID_OFFSET)
4795 #define DIALOG_BUTTON_COMMAND_ID_VALUE(id) \
4796 ((id) - DIALOG_BUTTON_COMMAND_ID_OFFSET)
4797 #define DIALOG_BUTTON_MAKE_COMMAND_ID(value) \
4798 ((value) + DIALOG_BUTTON_COMMAND_ID_OFFSET)
4800 extern EMACS_TIME timer_check
P_ ((int));
4801 static int quit_dialog_event_loop
;
4803 static pascal OSStatus
4804 mac_handle_dialog_event (next_handler
, event
, data
)
4805 EventHandlerCallRef next_handler
;
4809 OSStatus err
, result
= eventNotHandledErr
;
4810 WindowRef window
= (WindowRef
) data
;
4812 switch (GetEventClass (event
))
4814 case kEventClassCommand
:
4818 err
= GetEventParameter (event
, kEventParamDirectObject
,
4819 typeHICommand
, NULL
, sizeof (HICommand
),
4822 if (DIALOG_BUTTON_COMMAND_ID_P (command
.commandID
))
4824 SetWRefCon (window
, command
.commandID
);
4825 quit_dialog_event_loop
= 1;
4829 result
= CallNextEventHandler (next_handler
, event
);
4833 case kEventClassKeyboard
:
4838 result
= CallNextEventHandler (next_handler
, event
);
4839 if (result
!= eventNotHandledErr
)
4842 err
= GetEventParameter (event
, kEventParamKeyMacCharCodes
,
4843 typeChar
, NULL
, sizeof (char),
4848 case kEscapeCharCode
:
4849 quit_dialog_event_loop
= 1;
4854 UInt32 modifiers
, key_code
;
4856 err
= GetEventParameter (event
, kEventParamKeyModifiers
,
4857 typeUInt32
, NULL
, sizeof (UInt32
),
4860 err
= GetEventParameter (event
, kEventParamKeyCode
,
4861 typeUInt32
, NULL
, sizeof (UInt32
),
4864 if (mac_quit_char_key_p (modifiers
, key_code
))
4865 quit_dialog_event_loop
= 1;
4876 if (quit_dialog_event_loop
)
4878 err
= QuitEventLoop (GetCurrentEventLoop ());
4887 install_dialog_event_handler (window
)
4890 static const EventTypeSpec specs
[] =
4891 {{kEventClassCommand
, kEventCommandProcess
},
4892 {kEventClassKeyboard
, kEventRawKeyDown
}};
4893 static EventHandlerUPP handle_dialog_eventUPP
= NULL
;
4895 if (handle_dialog_eventUPP
== NULL
)
4896 handle_dialog_eventUPP
= NewEventHandlerUPP (mac_handle_dialog_event
);
4897 return InstallWindowEventHandler (window
, handle_dialog_eventUPP
,
4898 GetEventTypeCount (specs
), specs
,
4903 pop_down_dialog (arg
)
4906 struct Lisp_Save_Value
*p
= XSAVE_VALUE (arg
);
4907 WindowRef window
= p
->pointer
;
4911 if (popup_activated_flag
)
4912 EndAppModalStateForWindow (window
);
4913 DisposeWindow (window
);
4914 popup_activated_flag
= 0;
4921 /* Pop up the dialog for frame F defined by FIRST_WV and loop until the
4923 menu_item_selection will be set to the selection. */
4926 create_and_show_dialog (f
, first_wv
)
4928 widget_value
*first_wv
;
4931 char *dialog_name
, *message
;
4932 int nb_buttons
, first_group_count
, i
, result
= 0;
4934 short buttons_height
, text_height
, inner_width
, inner_height
;
4935 Rect empty_rect
, *rects
;
4936 WindowRef window
= NULL
;
4937 ControlRef
*buttons
, default_button
= NULL
, text
;
4938 int specpdl_count
= SPECPDL_INDEX ();
4940 dialog_name
= first_wv
->name
;
4941 nb_buttons
= dialog_name
[1] - '0';
4942 first_group_count
= nb_buttons
- (dialog_name
[4] - '0');
4944 wv
= first_wv
->contents
;
4945 message
= wv
->value
;
4948 SetRect (&empty_rect
, 0, 0, 0, 0);
4950 /* Create dialog window. */
4951 err
= CreateNewWindow (kMovableModalWindowClass
,
4952 kWindowStandardHandlerAttribute
,
4953 &empty_rect
, &window
);
4956 record_unwind_protect (pop_down_dialog
, make_save_value (window
, 0));
4957 err
= SetThemeWindowBackground (window
, kThemeBrushMovableModalBackground
,
4961 err
= SetWindowTitleWithCFString (window
, (dialog_name
[0] == 'Q'
4962 ? CFSTR ("Question")
4963 : CFSTR ("Information")));
4965 /* Create button controls and measure their optimal bounds. */
4968 buttons
= alloca (sizeof (ControlRef
) * nb_buttons
);
4969 rects
= alloca (sizeof (Rect
) * nb_buttons
);
4970 for (i
= 0; i
< nb_buttons
; i
++)
4972 CFStringRef label
= cfstring_create_with_utf8_cstring (wv
->value
);
4978 err
= CreatePushButtonControl (window
, &empty_rect
,
4979 label
, &buttons
[i
]);
4987 err
= DisableControl (buttons
[i
]);
4989 err
= DeactivateControl (buttons
[i
]);
4992 else if (default_button
== NULL
)
4993 default_button
= buttons
[i
];
4999 rects
[i
] = empty_rect
;
5000 err
= GetBestControlRect (buttons
[i
], &rects
[i
], &unused
);
5006 OffsetRect (&rects
[i
], -rects
[i
].left
, -rects
[i
].top
);
5007 if (rects
[i
].right
< DIALOG_BUTTON_MIN_WIDTH
)
5008 rects
[i
].right
= DIALOG_BUTTON_MIN_WIDTH
;
5009 else if (rects
[i
].right
> DIALOG_MAX_INNER_WIDTH
)
5010 rects
[i
].right
= DIALOG_MAX_INNER_WIDTH
;
5012 command_id
= DIALOG_BUTTON_MAKE_COMMAND_ID ((int) wv
->call_data
);
5013 err
= SetControlCommandID (buttons
[i
], command_id
);
5021 /* Layout buttons. rects[i] is set relative to the bottom-right
5022 corner of the inner box. */
5025 short bottom
, right
, max_height
, left_align_shift
;
5027 inner_width
= DIALOG_MIN_INNER_WIDTH
;
5028 bottom
= right
= max_height
= 0;
5029 for (i
= 0; i
< nb_buttons
; i
++)
5031 if (right
- rects
[i
].right
< - inner_width
)
5033 if (i
!= first_group_count
5034 && right
- rects
[i
].right
>= - DIALOG_MAX_INNER_WIDTH
)
5035 inner_width
= - (right
- rects
[i
].right
);
5038 bottom
-= max_height
+ DIALOG_BUTTON_BUTTON_VERTICAL_SPACE
;
5039 right
= max_height
= 0;
5042 if (max_height
< rects
[i
].bottom
)
5043 max_height
= rects
[i
].bottom
;
5044 OffsetRect (&rects
[i
], right
- rects
[i
].right
,
5045 bottom
- rects
[i
].bottom
);
5046 right
= rects
[i
].left
- DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE
;
5047 if (i
== first_group_count
- 1)
5048 right
-= DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE
;
5050 buttons_height
= - (bottom
- max_height
);
5052 left_align_shift
= - (inner_width
+ rects
[nb_buttons
- 1].left
);
5053 for (i
= nb_buttons
- 1; i
>= first_group_count
; i
--)
5055 if (bottom
!= rects
[i
].bottom
)
5057 left_align_shift
= - (inner_width
+ rects
[i
].left
);
5058 bottom
= rects
[i
].bottom
;
5060 OffsetRect (&rects
[i
], left_align_shift
, 0);
5064 /* Create a static text control and measure its bounds. */
5067 CFStringRef message_string
;
5070 message_string
= cfstring_create_with_utf8_cstring (message
);
5071 if (message_string
== NULL
)
5075 ControlFontStyleRec text_style
;
5077 text_style
.flags
= 0;
5078 SetRect (&bounds
, 0, 0, inner_width
, 0);
5079 err
= CreateStaticTextControl (window
, &bounds
, message_string
,
5080 &text_style
, &text
);
5081 CFRelease (message_string
);
5087 bounds
= empty_rect
;
5088 err
= GetBestControlRect (text
, &bounds
, &unused
);
5092 text_height
= bounds
.bottom
- bounds
.top
;
5093 if (text_height
< DIALOG_TEXT_MIN_HEIGHT
)
5094 text_height
= DIALOG_TEXT_MIN_HEIGHT
;
5098 /* Place buttons. */
5101 inner_height
= (text_height
+ DIALOG_TEXT_BUTTONS_VERTICAL_SPACE
5104 for (i
= 0; i
< nb_buttons
; i
++)
5106 OffsetRect (&rects
[i
], DIALOG_LEFT_MARGIN
+ inner_width
,
5107 DIALOG_TOP_MARGIN
+ inner_height
);
5108 SetControlBounds (buttons
[i
], &rects
[i
]);
5117 SetRect (&bounds
, DIALOG_LEFT_MARGIN
, DIALOG_TOP_MARGIN
,
5118 DIALOG_LEFT_MARGIN
+ inner_width
,
5119 DIALOG_TOP_MARGIN
+ text_height
);
5120 SetControlBounds (text
, &bounds
);
5123 /* Create the application icon at the upper-left corner. */
5126 ControlButtonContentInfo content
;
5128 static const ProcessSerialNumber psn
= {0, kCurrentProcess
};
5132 ProcessInfoRec pinfo
;
5137 content
.contentType
= kControlContentIconRef
;
5139 err
= GetProcessBundleLocation (&psn
, &app_location
);
5141 err
= GetIconRefFromFileInfo (&app_location
, 0, NULL
, 0, NULL
,
5142 kIconServicesNormalUsageFlag
,
5143 &content
.u
.iconRef
, &unused
);
5145 bzero (&pinfo
, sizeof (ProcessInfoRec
));
5146 pinfo
.processInfoLength
= sizeof (ProcessInfoRec
);
5147 pinfo
.processAppSpec
= &app_spec
;
5148 err
= GetProcessInformation (&psn
, &pinfo
);
5150 err
= GetIconRefFromFile (&app_spec
, &content
.u
.iconRef
, &unused
);
5156 SetRect (&bounds
, DIALOG_ICON_LEFT_MARGIN
, DIALOG_ICON_TOP_MARGIN
,
5157 DIALOG_ICON_LEFT_MARGIN
+ DIALOG_ICON_WIDTH
,
5158 DIALOG_ICON_TOP_MARGIN
+ DIALOG_ICON_HEIGHT
);
5159 err
= CreateIconControl (window
, &bounds
, &content
, true, &icon
);
5160 ReleaseIconRef (content
.u
.iconRef
);
5164 /* Show the dialog window and run event loop. */
5167 err
= SetWindowDefaultButton (window
, default_button
);
5169 err
= install_dialog_event_handler (window
);
5173 DIALOG_LEFT_MARGIN
+ inner_width
+ DIALOG_RIGHT_MARGIN
,
5174 DIALOG_TOP_MARGIN
+ inner_height
+ DIALOG_BOTTOM_MARGIN
,
5176 err
= RepositionWindow (window
, FRAME_MAC_WINDOW (f
),
5177 kWindowAlertPositionOnParentWindow
);
5181 SetWRefCon (window
, 0);
5182 ShowWindow (window
);
5183 BringToFront (window
);
5184 popup_activated_flag
= 1;
5185 err
= BeginAppModalStateForWindow (window
);
5189 EventTargetRef toolbox_dispatcher
= GetEventDispatcherTarget ();
5191 quit_dialog_event_loop
= 0;
5194 EMACS_TIME next_time
= timer_check (1);
5195 long secs
= EMACS_SECS (next_time
);
5196 long usecs
= EMACS_USECS (next_time
);
5197 EventTimeout timeout
;
5200 if (secs
< 0 || (secs
== 0 && usecs
== 0))
5202 /* Sometimes timer_check returns -1 (no timers) even if
5203 there are timers. So do a timeout anyway. */
5208 timeout
= (secs
* kEventDurationSecond
5209 + usecs
* kEventDurationMicrosecond
);
5210 err
= ReceiveNextEvent (0, NULL
, timeout
, kEventRemoveFromQueue
,
5214 SendEventToEventTarget (event
, toolbox_dispatcher
);
5215 ReleaseEvent (event
);
5217 #if 0 /* defined (MAC_OSX) */
5218 else if (err
!= eventLoopTimedOutErr
)
5220 if (err
== eventLoopQuitErr
)
5225 /* The return value of ReceiveNextEvent seems to be
5226 unreliable. Use our own global variable instead. */
5227 if (quit_dialog_event_loop
)
5237 UInt32 command_id
= GetWRefCon (window
);
5239 if (DIALOG_BUTTON_COMMAND_ID_P (command_id
))
5240 result
= DIALOG_BUTTON_COMMAND_ID_VALUE (command_id
);
5243 unbind_to (specpdl_count
, Qnil
);
5245 menu_item_selection
= result
;
5247 #else /* not TARGET_API_MAC_CARBON */
5248 #define DIALOG_WINDOW_RESOURCE 130
5251 mac_dialog (widget_value
*wv
)
5255 char **button_labels
;
5262 WindowRef window_ptr
;
5265 EventRecord event_record
;
5267 int control_part_code
;
5270 dialog_name
= wv
->name
;
5271 nb_buttons
= dialog_name
[1] - '0';
5272 left_count
= nb_buttons
- (dialog_name
[4] - '0');
5273 button_labels
= (char **) alloca (sizeof (char *) * nb_buttons
);
5274 ref_cons
= (UInt32
*) alloca (sizeof (UInt32
) * nb_buttons
);
5277 prompt
= (char *) alloca (strlen (wv
->value
) + 1);
5278 strcpy (prompt
, wv
->value
);
5282 for (i
= 0; i
< nb_buttons
; i
++)
5284 button_labels
[i
] = wv
->value
;
5285 button_labels
[i
] = (char *) alloca (strlen (wv
->value
) + 1);
5286 strcpy (button_labels
[i
], wv
->value
);
5287 c2pstr (button_labels
[i
]);
5288 ref_cons
[i
] = (UInt32
) wv
->call_data
;
5292 window_ptr
= GetNewCWindow (DIALOG_WINDOW_RESOURCE
, NULL
, (WindowRef
) -1);
5294 SetPortWindowPort (window_ptr
);
5297 /* Left and right margins in the dialog are 13 pixels each.*/
5299 /* Calculate width of dialog box: 8 pixels on each side of the text
5300 label in each button, 12 pixels between buttons. */
5301 for (i
= 0; i
< nb_buttons
; i
++)
5302 dialog_width
+= StringWidth (button_labels
[i
]) + 16 + 12;
5304 if (left_count
!= 0 && nb_buttons
- left_count
!= 0)
5307 dialog_width
= max (dialog_width
, StringWidth (prompt
) + 26);
5309 SizeWindow (window_ptr
, dialog_width
, 78, 0);
5310 ShowWindow (window_ptr
);
5312 SetPortWindowPort (window_ptr
);
5317 DrawString (prompt
);
5320 for (i
= 0; i
< nb_buttons
; i
++)
5322 int button_width
= StringWidth (button_labels
[i
]) + 16;
5323 SetRect (&rect
, left
, 45, left
+ button_width
, 65);
5324 ch
= NewControl (window_ptr
, &rect
, button_labels
[i
], 1, 0, 0, 0,
5325 kControlPushButtonProc
, ref_cons
[i
]);
5326 left
+= button_width
+ 12;
5327 if (i
== left_count
- 1)
5334 if (WaitNextEvent (mDownMask
, &event_record
, 10, NULL
))
5335 if (event_record
.what
== mouseDown
)
5337 part_code
= FindWindow (event_record
.where
, &window_ptr
);
5338 if (part_code
== inContent
)
5340 mouse
= event_record
.where
;
5341 GlobalToLocal (&mouse
);
5342 control_part_code
= FindControl (mouse
, window_ptr
, &ch
);
5343 if (control_part_code
== kControlButtonPart
)
5344 if (TrackControl (ch
, mouse
, NULL
))
5345 i
= GetControlReference (ch
);
5350 DisposeWindow (window_ptr
);
5354 #endif /* not TARGET_API_MAC_CARBON */
5357 /***********************************************************************
5359 ***********************************************************************/
5361 #if !TARGET_API_MAC_CARBON
5366 extern Lisp_Object Vselection_converter_alist
;
5367 extern Lisp_Object Qmac_scrap_name
, Qmac_ostype
;
5369 static ScrapFlavorType get_flavor_type_from_symbol
P_ ((Lisp_Object
,
5372 /* Get a reference to the selection corresponding to the symbol SYM.
5373 The reference is set to *SEL, and it becomes NULL if there's no
5374 corresponding selection. Clear the selection if CLEAR_P is
5378 mac_get_selection_from_symbol (sym
, clear_p
, sel
)
5383 OSStatus err
= noErr
;
5384 Lisp_Object str
= Fget (sym
, Qmac_scrap_name
);
5390 #if TARGET_API_MAC_CARBON
5392 CFStringRef scrap_name
= cfstring_create_with_string (str
);
5393 OptionBits options
= (clear_p
? kScrapClearNamedScrap
5394 : kScrapGetNamedScrap
);
5396 err
= GetScrapByName (scrap_name
, options
, sel
);
5397 CFRelease (scrap_name
);
5398 #else /* !MAC_OSX */
5400 err
= ClearCurrentScrap ();
5402 err
= GetCurrentScrap (sel
);
5403 #endif /* !MAC_OSX */
5404 #else /* !TARGET_API_MAC_CARBON */
5409 #endif /* !TARGET_API_MAC_CARBON */
5415 /* Get a scrap flavor type from the symbol SYM. Return 0 if no
5416 corresponding flavor type. If SEL is non-zero, the return value is
5417 non-zero only when the SEL has the flavor type. */
5419 static ScrapFlavorType
5420 get_flavor_type_from_symbol (sym
, sel
)
5424 Lisp_Object str
= Fget (sym
, Qmac_ostype
);
5425 ScrapFlavorType flavor_type
;
5427 if (STRINGP (str
) && SBYTES (str
) == 4)
5428 flavor_type
= EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
5432 if (flavor_type
&& sel
)
5434 #if TARGET_API_MAC_CARBON
5436 ScrapFlavorFlags flags
;
5438 err
= GetScrapFlavorFlags (sel
, flavor_type
, &flags
);
5441 #else /* !TARGET_API_MAC_CARBON */
5442 SInt32 size
, offset
;
5444 size
= GetScrap (NULL
, flavor_type
, &offset
);
5447 #endif /* !TARGET_API_MAC_CARBON */
5453 /* Check if the symbol SYM has a corresponding selection target type. */
5456 mac_valid_selection_target_p (sym
)
5459 return get_flavor_type_from_symbol (sym
, 0) != 0;
5462 /* Clear the selection whose reference is *SEL. */
5465 mac_clear_selection (sel
)
5468 #if TARGET_API_MAC_CARBON
5470 return ClearScrap (sel
);
5474 err
= ClearCurrentScrap ();
5476 err
= GetCurrentScrap (sel
);
5479 #else /* !TARGET_API_MAC_CARBON */
5480 return ZeroScrap ();
5481 #endif /* !TARGET_API_MAC_CARBON */
5484 /* Get ownership information for SEL. Emacs can detect a change of
5485 the ownership by comparing saved and current values of the
5486 ownership information. */
5489 mac_get_selection_ownership_info (sel
)
5492 #if TARGET_API_MAC_CARBON
5493 return long_to_cons ((unsigned long) sel
);
5494 #else /* !TARGET_API_MAC_CARBON */
5495 ScrapStuffPtr scrap_info
= InfoScrap ();
5497 return make_number (scrap_info
->scrapCount
);
5498 #endif /* !TARGET_API_MAC_CARBON */
5501 /* Return non-zero if VALUE is a valid selection value for TARGET. */
5504 mac_valid_selection_value_p (value
, target
)
5505 Lisp_Object value
, target
;
5507 return STRINGP (value
);
5510 /* Put Lisp object VALUE to the selection SEL. The target type is
5511 specified by TARGET. */
5514 mac_put_selection_value (sel
, target
, value
)
5516 Lisp_Object target
, value
;
5518 ScrapFlavorType flavor_type
= get_flavor_type_from_symbol (target
, 0);
5520 if (flavor_type
== 0 || !STRINGP (value
))
5523 #if TARGET_API_MAC_CARBON
5524 return PutScrapFlavor (sel
, flavor_type
, kScrapFlavorMaskNone
,
5525 SBYTES (value
), SDATA (value
));
5526 #else /* !TARGET_API_MAC_CARBON */
5527 return PutScrap (SBYTES (value
), flavor_type
, SDATA (value
));
5528 #endif /* !TARGET_API_MAC_CARBON */
5531 /* Check if data for the target type TARGET is available in SEL. */
5534 mac_selection_has_target_p (sel
, target
)
5538 return get_flavor_type_from_symbol (target
, sel
) != 0;
5541 /* Get data for the target type TARGET from SEL and create a Lisp
5542 string. Return nil if failed to get data. */
5545 mac_get_selection_value (sel
, target
)
5550 Lisp_Object result
= Qnil
;
5551 ScrapFlavorType flavor_type
= get_flavor_type_from_symbol (target
, sel
);
5552 #if TARGET_API_MAC_CARBON
5557 err
= GetScrapFlavorSize (sel
, flavor_type
, &size
);
5562 result
= make_uninit_string (size
);
5563 err
= GetScrapFlavorData (sel
, flavor_type
,
5564 &size
, SDATA (result
));
5567 else if (size
< SBYTES (result
))
5568 result
= make_unibyte_string (SDATA (result
), size
);
5570 while (STRINGP (result
) && size
> SBYTES (result
));
5575 SInt32 size
, offset
;
5578 size
= GetScrap (NULL
, flavor_type
, &offset
);
5581 handle
= NewHandle (size
);
5583 size
= GetScrap (handle
, flavor_type
, &offset
);
5585 result
= make_unibyte_string (*handle
, size
);
5586 DisposeHandle (handle
);
5593 /* Get the list of target types in SEL. The return value is a list of
5594 target type symbols possibly followed by scrap flavor type
5598 mac_get_selection_target_list (sel
)
5601 Lisp_Object result
= Qnil
, rest
, target
;
5602 #if TARGET_API_MAC_CARBON
5604 UInt32 count
, i
, type
;
5605 ScrapFlavorInfo
*flavor_info
= NULL
;
5606 Lisp_Object strings
= Qnil
;
5608 err
= GetScrapFlavorCount (sel
, &count
);
5610 flavor_info
= xmalloc (sizeof (ScrapFlavorInfo
) * count
);
5611 err
= GetScrapFlavorInfoList (sel
, &count
, flavor_info
);
5614 xfree (flavor_info
);
5617 if (flavor_info
== NULL
)
5620 for (rest
= Vselection_converter_alist
; CONSP (rest
); rest
= XCDR (rest
))
5622 ScrapFlavorType flavor_type
= 0;
5624 if (CONSP (XCAR (rest
))
5625 && (target
= XCAR (XCAR (rest
)),
5627 && (flavor_type
= get_flavor_type_from_symbol (target
, sel
)))
5629 result
= Fcons (target
, result
);
5630 #if TARGET_API_MAC_CARBON
5631 for (i
= 0; i
< count
; i
++)
5632 if (flavor_info
[i
].flavorType
== flavor_type
)
5634 flavor_info
[i
].flavorType
= 0;
5640 #if TARGET_API_MAC_CARBON
5643 for (i
= 0; i
< count
; i
++)
5644 if (flavor_info
[i
].flavorType
)
5646 type
= EndianU32_NtoB (flavor_info
[i
].flavorType
);
5647 strings
= Fcons (make_unibyte_string ((char *) &type
, 4), strings
);
5649 result
= nconc2 (result
, strings
);
5650 xfree (flavor_info
);
5658 /***********************************************************************
5660 ***********************************************************************/
5662 extern pascal OSErr mac_handle_apple_event
P_ ((const AppleEvent
*,
5663 AppleEvent
*, SInt32
));
5664 extern void cleanup_all_suspended_apple_events
P_ ((void));
5667 init_apple_event_handler ()
5672 /* Make sure we have Apple events before starting. */
5673 err
= Gestalt (gestaltAppleEventsAttr
, &result
);
5677 if (!(result
& (1 << gestaltAppleEventsPresent
)))
5680 err
= AEInstallEventHandler (typeWildCard
, typeWildCard
,
5681 #if TARGET_API_MAC_CARBON
5682 NewAEEventHandlerUPP (mac_handle_apple_event
),
5684 NewAEEventHandlerProc (mac_handle_apple_event
),
5690 atexit (cleanup_all_suspended_apple_events
);
5694 /***********************************************************************
5695 Drag and drop support
5696 ***********************************************************************/
5698 #if TARGET_API_MAC_CARBON
5699 extern Lisp_Object Vmac_dnd_known_types
;
5701 static pascal OSErr mac_do_track_drag
P_ ((DragTrackingMessage
, WindowRef
,
5703 static pascal OSErr mac_do_receive_drag
P_ ((WindowRef
, void *, DragRef
));
5704 static DragTrackingHandlerUPP mac_do_track_dragUPP
= NULL
;
5705 static DragReceiveHandlerUPP mac_do_receive_dragUPP
= NULL
;
5708 mac_store_drag_event (window
, mouse_pos
, modifiers
, desc
)
5714 struct input_event buf
;
5718 buf
.kind
= DRAG_N_DROP_EVENT
;
5719 buf
.modifiers
= mac_to_emacs_modifiers (modifiers
, 0);
5720 buf
.timestamp
= TickCount () * (1000 / 60);
5721 XSETINT (buf
.x
, mouse_pos
.h
);
5722 XSETINT (buf
.y
, mouse_pos
.v
);
5723 XSETFRAME (buf
.frame_or_window
, mac_window_to_frame (window
));
5724 buf
.arg
= mac_aedesc_to_lisp (desc
);
5725 kbd_buffer_store_event (&buf
);
5729 mac_do_track_drag (message
, window
, refcon
, drag
)
5730 DragTrackingMessage message
;
5736 static int can_accept
;
5737 UInt16 num_items
, index
;
5739 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
5740 return dragNotAcceptedErr
;
5744 case kDragTrackingEnterHandler
:
5745 err
= CountDragItems (drag
, &num_items
);
5749 for (index
= 1; index
<= num_items
; index
++)
5755 err
= GetDragItemReferenceNumber (drag
, index
, &item
);
5758 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
5764 if (!(STRINGP (str
) && SBYTES (str
) == 4))
5766 type
= EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
5768 err
= GetFlavorFlags (drag
, item
, type
, &flags
);
5778 case kDragTrackingEnterWindow
:
5781 RgnHandle hilite_rgn
= NewRgn ();
5787 GetWindowPortBounds (window
, &r
);
5788 OffsetRect (&r
, -r
.left
, -r
.top
);
5789 RectRgn (hilite_rgn
, &r
);
5790 ShowDragHilite (drag
, hilite_rgn
, true);
5791 DisposeRgn (hilite_rgn
);
5793 SetThemeCursor (kThemeCopyArrowCursor
);
5797 case kDragTrackingInWindow
:
5800 case kDragTrackingLeaveWindow
:
5803 HideDragHilite (drag
);
5804 SetThemeCursor (kThemeArrowCursor
);
5808 case kDragTrackingLeaveHandler
:
5813 return dragNotAcceptedErr
;
5818 mac_do_receive_drag (window
, refcon
, drag
)
5825 Lisp_Object rest
, str
;
5827 AppleEvent apple_event
;
5831 if (GetFrontWindowOfClass (kMovableModalWindowClass
, false))
5832 return dragNotAcceptedErr
;
5835 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
5838 if (STRINGP (str
) && SBYTES (str
) == 4)
5842 types
= xmalloc (sizeof (FlavorType
) * num_types
);
5844 for (rest
= Vmac_dnd_known_types
; CONSP (rest
); rest
= XCDR (rest
))
5847 if (STRINGP (str
) && SBYTES (str
) == 4)
5848 types
[i
++] = EndianU32_BtoN (*((UInt32
*) SDATA (str
)));
5851 err
= create_apple_event_from_drag_ref (drag
, num_types
, types
,
5856 err
= GetDragMouse (drag
, &mouse_pos
, NULL
);
5859 GlobalToLocal (&mouse_pos
);
5860 err
= GetDragModifiers (drag
, NULL
, NULL
, &modifiers
);
5864 UInt32 key_modifiers
= modifiers
;
5866 err
= AEPutParamPtr (&apple_event
, kEventParamKeyModifiers
,
5867 typeUInt32
, &key_modifiers
, sizeof (UInt32
));
5872 mac_store_drag_event (window
, mouse_pos
, 0, &apple_event
);
5873 AEDisposeDesc (&apple_event
);
5874 mac_wakeup_from_rne ();
5878 return dragNotAcceptedErr
;
5880 #endif /* TARGET_API_MAC_CARBON */
5883 install_drag_handler (window
)
5888 #if TARGET_API_MAC_CARBON
5889 if (mac_do_track_dragUPP
== NULL
)
5890 mac_do_track_dragUPP
= NewDragTrackingHandlerUPP (mac_do_track_drag
);
5891 if (mac_do_receive_dragUPP
== NULL
)
5892 mac_do_receive_dragUPP
= NewDragReceiveHandlerUPP (mac_do_receive_drag
);
5894 err
= InstallTrackingHandler (mac_do_track_dragUPP
, window
, NULL
);
5896 err
= InstallReceiveHandler (mac_do_receive_dragUPP
, window
, NULL
);
5903 remove_drag_handler (window
)
5906 #if TARGET_API_MAC_CARBON
5907 if (mac_do_track_dragUPP
)
5908 RemoveTrackingHandler (mac_do_track_dragUPP
, window
);
5909 if (mac_do_receive_dragUPP
)
5910 RemoveReceiveHandler (mac_do_receive_dragUPP
, window
);
5914 #if TARGET_API_MAC_CARBON
5915 /* Return default value for mac-dnd-known-types. */
5918 mac_dnd_default_known_types ()
5920 Lisp_Object result
= list4 (build_string ("hfs "), build_string ("utxt"),
5921 build_string ("TEXT"), build_string ("TIFF"));
5924 result
= Fcons (build_string ("furl"), result
);
5932 /***********************************************************************
5933 Services menu support
5934 ***********************************************************************/
5937 extern Lisp_Object Qservice
, Qpaste
, Qperform
;
5938 extern Lisp_Object Vmac_service_selection
;
5941 mac_store_service_event (event
)
5947 const EventParamName
*names
;
5948 const EventParamType
*types
;
5949 static const EventParamName names_pfm
[] =
5950 {kEventParamServiceMessageName
, kEventParamServiceUserData
};
5951 static const EventParamType types_pfm
[] =
5952 {typeCFStringRef
, typeCFStringRef
};
5954 switch (GetEventKind (event
))
5956 case kEventServicePaste
:
5963 case kEventServicePerform
:
5965 num_params
= sizeof (names_pfm
) / sizeof (names_pfm
[0]);
5974 err
= mac_store_event_ref_as_apple_event (0, 0, Qservice
, id_key
,
5982 copy_scrap_flavor_data (from_scrap
, to_scrap
, flavor_type
)
5983 ScrapRef from_scrap
, to_scrap
;
5984 ScrapFlavorType flavor_type
;
5987 Size size
, size_allocated
;
5990 err
= GetScrapFlavorSize (from_scrap
, flavor_type
, &size
);
5992 buf
= xmalloc (size
);
5995 size_allocated
= size
;
5996 err
= GetScrapFlavorData (from_scrap
, flavor_type
, &size
, buf
);
6002 else if (size_allocated
< size
)
6003 buf
= xrealloc (buf
, size
);
6013 err
= PutScrapFlavor (to_scrap
, flavor_type
, kScrapFlavorMaskNone
,
6023 mac_handle_service_event (call_ref
, event
, data
)
6024 EventHandlerCallRef call_ref
;
6028 OSStatus err
= noErr
;
6029 ScrapRef cur_scrap
, specific_scrap
;
6030 UInt32 event_kind
= GetEventKind (event
);
6031 CFMutableArrayRef copy_types
, paste_types
;
6034 ScrapFlavorType flavor_type
;
6036 /* Check if Vmac_service_selection is a valid selection that has a
6037 corresponding scrap. */
6038 if (!SYMBOLP (Vmac_service_selection
))
6039 err
= eventNotHandledErr
;
6041 err
= mac_get_selection_from_symbol (Vmac_service_selection
, 0, &cur_scrap
);
6042 if (!(err
== noErr
&& cur_scrap
))
6043 return eventNotHandledErr
;
6047 case kEventServiceGetTypes
:
6048 /* Set paste types. */
6049 err
= GetEventParameter (event
, kEventParamServicePasteTypes
,
6050 typeCFMutableArrayRef
, NULL
,
6051 sizeof (CFMutableArrayRef
), NULL
,
6056 for (rest
= Vselection_converter_alist
; CONSP (rest
);
6058 if (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))
6060 get_flavor_type_from_symbol (XCAR (XCAR (rest
)), 0)))
6062 type
= CreateTypeStringWithOSType (flavor_type
);
6065 CFArrayAppendValue (paste_types
, type
);
6070 /* Set copy types. */
6071 err
= GetEventParameter (event
, kEventParamServiceCopyTypes
,
6072 typeCFMutableArrayRef
, NULL
,
6073 sizeof (CFMutableArrayRef
), NULL
,
6078 if (NILP (Fx_selection_owner_p (Vmac_service_selection
)))
6081 goto copy_all_flavors
;
6083 case kEventServiceCopy
:
6084 err
= GetEventParameter (event
, kEventParamScrapRef
,
6086 sizeof (ScrapRef
), NULL
, &specific_scrap
);
6088 || NILP (Fx_selection_owner_p (Vmac_service_selection
)))
6090 err
= eventNotHandledErr
;
6097 ScrapFlavorInfo
*flavor_info
= NULL
;
6098 ScrapFlavorFlags flags
;
6100 err
= GetScrapFlavorCount (cur_scrap
, &count
);
6102 flavor_info
= xmalloc (sizeof (ScrapFlavorInfo
) * count
);
6103 err
= GetScrapFlavorInfoList (cur_scrap
, &count
, flavor_info
);
6106 xfree (flavor_info
);
6109 if (flavor_info
== NULL
)
6112 for (i
= 0; i
< count
; i
++)
6114 flavor_type
= flavor_info
[i
].flavorType
;
6115 err
= GetScrapFlavorFlags (cur_scrap
, flavor_type
, &flags
);
6116 if (err
== noErr
&& !(flags
& kScrapFlavorMaskSenderOnly
))
6118 if (event_kind
== kEventServiceCopy
)
6119 err
= copy_scrap_flavor_data (cur_scrap
, specific_scrap
,
6121 else /* event_kind == kEventServiceGetTypes */
6123 type
= CreateTypeStringWithOSType (flavor_type
);
6126 CFArrayAppendValue (copy_types
, type
);
6132 xfree (flavor_info
);
6136 case kEventServicePaste
:
6137 case kEventServicePerform
:
6139 int data_exists_p
= 0;
6141 err
= GetEventParameter (event
, kEventParamScrapRef
, typeScrapRef
,
6142 NULL
, sizeof (ScrapRef
), NULL
,
6145 err
= mac_clear_selection (&cur_scrap
);
6147 for (rest
= Vselection_converter_alist
; CONSP (rest
);
6150 if (! (CONSP (XCAR (rest
)) && SYMBOLP (XCAR (XCAR (rest
)))))
6152 flavor_type
= get_flavor_type_from_symbol (XCAR (XCAR (rest
)),
6154 if (flavor_type
== 0)
6156 err
= copy_scrap_flavor_data (specific_scrap
, cur_scrap
,
6162 err
= eventNotHandledErr
;
6164 err
= mac_store_service_event (event
);
6170 err
= eventNotHandledErr
;
6175 install_service_handler ()
6177 static const EventTypeSpec specs
[] =
6178 {{kEventClassService
, kEventServiceGetTypes
},
6179 {kEventClassService
, kEventServiceCopy
},
6180 {kEventClassService
, kEventServicePaste
},
6181 {kEventClassService
, kEventServicePerform
}};
6183 return InstallApplicationEventHandler (NewEventHandlerUPP
6184 (mac_handle_service_event
),
6185 GetEventTypeCount (specs
),
6188 #endif /* MAC_OSX */
6191 /***********************************************************************
6193 ***********************************************************************/
6196 mac_toolbox_initialize ()
6198 any_help_event_p
= 0;
6203 init_apple_event_handler ();