+static struct frame *
+mac_focus_frame (dpyinfo)
+ struct mac_display_info *dpyinfo;
+{
+ if (dpyinfo->x_focus_frame)
+ return dpyinfo->x_focus_frame;
+ else
+ /* Mac version may get events, such as a menu bar click, even when
+ all the frames are invisible. In this case, we regard the
+ event came to the selected frame. */
+ return SELECTED_FRAME ();
+}
+
+
+/* Return the current position of the mouse.
+ *FP should be a frame which indicates which display to ask about.
+
+ If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW,
+ and *PART to the frame, window, and scroll bar part that the mouse
+ is over. Set *X and *Y to the portion and whole of the mouse's
+ position on the scroll bar.
+
+ If the mouse movement started elsewhere, set *FP to the frame the
+ mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell
+ the mouse is over.
+
+ Set *TIME to the server time-stamp for the time at which the mouse
+ was at this position.
+
+ Don't store anything if we don't have a valid set of values to report.
+
+ This clears the mouse_moved flag, so we can wait for the next mouse
+ movement. */
+
+static void
+XTmouse_position (fp, insist, bar_window, part, x, y, time)
+ FRAME_PTR *fp;
+ int insist;
+ Lisp_Object *bar_window;
+ enum scroll_bar_part *part;
+ Lisp_Object *x, *y;
+ unsigned long *time;
+{
+ FRAME_PTR f1;
+
+ BLOCK_INPUT;
+
+ if (! NILP (last_mouse_scroll_bar) && insist == 0)
+ x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
+ else
+ {
+ Lisp_Object frame, tail;
+
+ /* Clear the mouse-moved flag for every frame on this display. */
+ FOR_EACH_FRAME (tail, frame)
+ XFRAME (frame)->mouse_moved = 0;
+
+ last_mouse_scroll_bar = Qnil;
+
+ if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
+ && FRAME_LIVE_P (last_mouse_frame))
+ f1 = last_mouse_frame;
+ else
+ f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp));
+
+ if (f1)
+ {
+ /* Ok, we found a frame. Store all the values.
+ last_mouse_glyph is a rectangle used to reduce the
+ generation of mouse events. To not miss any motion
+ events, we must divide the frame into rectangles of the
+ size of the smallest character that could be displayed
+ on it, i.e. into the same rectangles that matrices on
+ the frame are divided into. */
+ Point mouse_pos;
+
+ SetPortWindowPort (FRAME_MAC_WINDOW (f1));
+ GetMouse (&mouse_pos);
+ remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v,
+ &last_mouse_glyph);
+ last_mouse_glyph_frame = f1;
+
+ *bar_window = Qnil;
+ *part = 0;
+ *fp = f1;
+ XSETINT (*x, mouse_pos.h);
+ XSETINT (*y, mouse_pos.v);
+ *time = last_mouse_movement_time;
+ }
+ }
+
+ UNBLOCK_INPUT;
+}
+
+\f
+/************************************************************************
+ Toolkit scroll bars
+ ************************************************************************/
+
+#ifdef USE_TOOLKIT_SCROLL_BARS
+
+static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *));
+static OSStatus install_scroll_bar_timer P_ ((void));
+static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval));
+static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode));
+static void construct_scroll_bar_click P_ ((struct scroll_bar *, int,
+ struct input_event *));
+static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode,
+ Rect *));
+static void x_scroll_bar_handle_press P_ ((struct scroll_bar *,
+ ControlPartCode,
+ struct input_event *));
+static void x_scroll_bar_handle_release P_ ((struct scroll_bar *,
+ struct input_event *));
+static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *,
+ Point, struct input_event *));
+static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *,
+ int, int, int));
+
+/* Last scroll bar part sent in x_scroll_bar_handle_*. */
+
+static int last_scroll_bar_part;
+
+static EventLoopTimerRef scroll_bar_timer;
+
+static int scroll_bar_timer_event_posted_p;
+
+#define SCROLL_BAR_FIRST_DELAY 0.5
+#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
+
+static pascal void
+scroll_bar_timer_callback (timer, data)
+ EventLoopTimerRef timer;
+ void *data;
+{
+ EventRef event = NULL;
+ OSErr err;
+
+ err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0,
+ kEventAttributeNone, &event);
+ if (err == noErr)
+ {
+ Point mouse_pos;
+
+ GetMouse (&mouse_pos);
+ LocalToGlobal (&mouse_pos);
+ err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint,
+ sizeof (Point), &mouse_pos);
+ }
+ if (err == noErr)
+ {
+ UInt32 modifiers = GetCurrentKeyModifiers ();
+
+ err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32,
+ sizeof (UInt32), &modifiers);
+ }
+ if (err == noErr)
+ err = PostEventToQueue (GetCurrentEventQueue (), event,
+ kEventPriorityStandard);
+ if (err == noErr)
+ scroll_bar_timer_event_posted_p = 1;
+
+ if (event)
+ ReleaseEvent (event);
+}
+
+static OSStatus
+install_scroll_bar_timer ()
+{
+ static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL;
+
+ if (scroll_bar_timer_callbackUPP == NULL)
+ scroll_bar_timer_callbackUPP =
+ NewEventLoopTimerUPP (scroll_bar_timer_callback);
+
+ if (scroll_bar_timer == NULL)
+ /* Mac OS X and CarbonLib 1.5 and later allow us to specify
+ kEventDurationForever as delays. */
+ return
+ InstallEventLoopTimer (GetCurrentEventLoop (),
+ kEventDurationForever, kEventDurationForever,
+ scroll_bar_timer_callbackUPP, NULL,
+ &scroll_bar_timer);
+}
+
+static OSStatus
+set_scroll_bar_timer (delay)
+ EventTimerInterval delay;
+{
+ if (scroll_bar_timer == NULL)
+ install_scroll_bar_timer ();
+
+ scroll_bar_timer_event_posted_p = 0;
+
+ return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay);
+}