Implement horizontal scroll bars on NS

* lisp/scroll-bar.el (horizontal-scroll-bars-available-p): Remove NS
check.
* lisp/term/ns-win.el: Remove custom NS scroll-bar handlers and bind
scroll-bar mouse clicks to standard handlers.
* src/nsterm.h (EmacsScroller): Add 'horizontal' property and rename
pixel_height to pixel_length.
* src/nsterm.m (x_set_window_size): Remove left-hand scroll-bar code. It
caused scroll-bars to be over-drawn and the best working solution
appears to be complete removal.
(ns_set_horizontal_scroll_bar): Rewrite to handle horizontal scrollers
correctly.
(ns_set_vertical_scroll_bar): Set width to actual scroller width.
(setFrame): Handle horizontal case.
(dealloc): Handle horizontal case.
(judge): Handle horizontal case.
(setPosition): Rename pixel_height to pixel_length.
(sendScrollEventAtLoc): Handle horizontal case.
(mouseDown): Handle horizontal case and general tidy up of code.
(mouseDragged): Handle horizontal case. Call sendScrollEventAtLoc with
absolute pixel size instead of ratio.
* src/window.h: Remove NS check.
This commit is contained in:
Alan Third 2016-05-01 13:04:07 +02:00 committed by Martin Rudalics
parent 80a1e3b9b5
commit e683a2570b
5 changed files with 123 additions and 143 deletions

View file

@ -148,8 +148,7 @@ created in the future."
"Return non-nil when horizontal scroll bars are available on this system."
(and (display-graphic-p)
(boundp 'x-toolkit-scroll-bars)
x-toolkit-scroll-bars
(not (eq (window-system) 'ns))))
x-toolkit-scroll-bars))
(define-minor-mode horizontal-scroll-bar-mode
"Toggle horizontal scroll bars on all frames (Horizontal Scroll Bar mode).

View file

@ -717,60 +717,12 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
;;;; Scrollbar handling.
(global-set-key [vertical-scroll-bar down-mouse-1] 'ns-handle-scroll-bar-event)
(global-set-key [vertical-scroll-bar down-mouse-1] 'scroll-bar-toolkit-scroll)
(global-set-key [horizontal-scroll-bar down-mouse-1] 'scroll-bar-toolkit-horizontal-scroll)
(global-unset-key [vertical-scroll-bar mouse-1])
(global-unset-key [vertical-scroll-bar drag-mouse-1])
(declare-function scroll-bar-scale "scroll-bar" (num-denom whole))
(defun ns-scroll-bar-move (event)
"Scroll the frame according to a Nextstep scroller event."
(interactive "e")
(let* ((pos (event-end event))
(window (nth 0 pos))
(scale (nth 2 pos)))
(with-current-buffer (window-buffer window)
(cond
((eq (car scale) (cdr scale))
(goto-char (point-max)))
((= (car scale) 0)
(goto-char (point-min)))
(t
(goto-char (+ (point-min) 1
(scroll-bar-scale scale (- (point-max) (point-min)))))))
(beginning-of-line)
(set-window-start window (point))
(vertical-motion (/ (window-height window) 2) window))))
(defun ns-handle-scroll-bar-event (event)
"Handle scroll bar EVENT to emulate Nextstep style scrolling."
(interactive "e")
(let* ((position (event-start event))
(bar-part (nth 4 position))
(window (nth 0 position))
(old-window (selected-window)))
(cond
((eq bar-part 'ratio)
(ns-scroll-bar-move event))
((eq bar-part 'handle)
(if (eq window (selected-window))
(track-mouse (ns-scroll-bar-move event))
;; track-mouse faster for selected window, slower for unselected.
(ns-scroll-bar-move event)))
(t
(select-window window)
(cond
((eq bar-part 'up)
(goto-char (window-start window))
(scroll-down 1))
((eq bar-part 'above-handle)
(scroll-down))
((eq bar-part 'below-handle)
(scroll-up))
((eq bar-part 'down)
(goto-char (window-start window))
(scroll-up 1)))
(select-window old-window)))))
(global-unset-key [horizontal-scroll-bar mouse-1])
(global-unset-key [horizontal-scroll-bar drag-mouse-1])
;;;; Color support.

View file

@ -676,11 +676,13 @@ char const * nstrace_fullscreen_type_name (int);
/* offset to the bottom of knob of last mouse down */
CGFloat last_mouse_offset;
float min_portion;
int pixel_height;
int pixel_length;
enum scroll_bar_part last_hit_part;
BOOL condemned;
BOOL horizontal;
/* optimize against excessive positioning calls generated by emacs */
int em_position;
int em_portion;

View file

@ -1801,23 +1801,6 @@ static void hide_bell ()
[window setFrame: wr display: YES];
/* This is a trick to compensate for Emacs' managing the scrollbar area
as a fixed number of standard character columns. Instead of leaving
blank space for the extra, we chopped it off above. Now for
left-hand scrollbars, we shift all rendering to the left by the
difference between the real width and Emacs' imagined one. For
right-hand bars, don't worry about it since the extra is never used.
(Obviously doesn't work for vertically split windows tho..) */
{
NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
- NS_SCROLL_BAR_WIDTH (f), 0)
: NSMakePoint (0, 0);
[view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
[view setBoundsOrigin: origin];
}
[view updateFrameSize: NO];
unblock_input ();
}
@ -4351,7 +4334,7 @@ in certain situations (rapid incoming events).
window_box (window, ANY_AREA, 0, &window_y, 0, &window_height);
top = window_y;
height = window_height;
width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
width = NS_SCROLL_BAR_WIDTH (f);
left = WINDOW_SCROLL_BAR_AREA_X (window);
r = NSMakeRect (left, top, width, height);
@ -4442,34 +4425,20 @@ in certain situations (rapid incoming events).
NSTRACE ("ns_set_horizontal_scroll_bar");
/* Get dimensions. */
window_box (window, ANY_AREA, 0, &window_x, &window_width, 0);
window_box (window, ANY_AREA, &window_x, 0, &window_width, 0);
left = window_x;
width = window_width;
height = WINDOW_CONFIG_SCROLL_BAR_LINES (window) * FRAME_LINE_HEIGHT (f);
height = NS_SCROLL_BAR_HEIGHT (f);
top = WINDOW_SCROLL_BAR_AREA_Y (window);
r = NSMakeRect (left, top, width, height);
/* the parent view is flipped, so we need to flip y value */
v = [view frame];
/* ??????? PXW/scrollbars !!!!!!!!!!!!!!!!!!!! */
r.origin.y = (v.size.height - r.size.height - r.origin.y);
XSETWINDOW (win, window);
block_input ();
if (WINDOW_TOTAL_COLS (window) < 5)
{
if (!NILP (window->horizontal_scroll_bar))
{
bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
[bar removeFromSuperview];
wset_horizontal_scroll_bar (window, Qnil);
}
ns_clear_frame_area (f, left, top, width, height);
unblock_input ();
return;
}
if (NILP (window->horizontal_scroll_bar))
{
if (width > 0 && height > 0)
@ -4484,16 +4453,22 @@ in certain situations (rapid incoming events).
NSRect oldRect;
bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
oldRect = [bar frame];
r.size.width = oldRect.size.width;
if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
{
if (oldRect.origin.x != r.origin.x)
ns_clear_frame_area (f, left, top, width, height);
if (oldRect.origin.y != r.origin.y)
ns_clear_frame_area (f, left, top, width, height);
[bar setFrame: r];
update_p = YES;
}
}
/* If there are both horizontal and vertical scroll-bars they leave
a square that belongs to neither. We need to clear it otherwise
it fills with junk. */
if (!NILP (window->vertical_scroll_bar))
ns_clear_frame_area (f, WINDOW_SCROLL_BAR_AREA_X (window), top,
NS_SCROLL_BAR_HEIGHT (f), height);
if (update_p)
[bar setPosition: position portion: portion whole: whole];
unblock_input ();
@ -4531,13 +4506,15 @@ in certain situations (rapid incoming events).
{
id bar;
NSTRACE ("ns_redeem_scroll_bar");
if (!NILP (window->vertical_scroll_bar))
if (!NILP (window->vertical_scroll_bar)
&& WINDOW_HAS_VERTICAL_SCROLL_BAR (window))
{
bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
[bar reprieve];
}
if (!NILP (window->horizontal_scroll_bar))
if (!NILP (window->horizontal_scroll_bar)
&& WINDOW_HAS_HORIZONTAL_SCROLL_BAR (window))
{
bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar);
[bar reprieve];
@ -8110,12 +8087,15 @@ + (CGFloat) scrollerWidth
return r;
}
- initFrame: (NSRect )r window: (Lisp_Object)nwin
{
NSTRACE ("[EmacsScroller initFrame: window:]");
r.size.width = [EmacsScroller scrollerWidth];
if (r.size.width > r.size.height)
horizontal = YES;
else
horizontal = NO;
[super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
[self setContinuous: YES];
[self setEnabled: YES];
@ -8131,9 +8111,12 @@ + (CGFloat) scrollerWidth
window = XWINDOW (nwin);
condemned = NO;
pixel_height = NSHeight (r);
if (pixel_height == 0) pixel_height = 1;
min_portion = 20 / pixel_height;
if (horizontal)
pixel_length = NSWidth (r);
else
pixel_length = NSHeight (r);
if (pixel_length == 0) pixel_length = 1;
min_portion = 20 / pixel_length;
frame = XFRAME (window->frame);
if (FRAME_LIVE_P (frame))
@ -8162,9 +8145,12 @@ - (void)setFrame: (NSRect)newRect
NSTRACE ("[EmacsScroller setFrame:]");
/* block_input (); */
pixel_height = NSHeight (newRect);
if (pixel_height == 0) pixel_height = 1;
min_portion = 20 / pixel_height;
if (horizontal)
pixel_length = NSWidth (newRect);
else
pixel_length = NSHeight (newRect);
if (pixel_length == 0) pixel_length = 1;
min_portion = 20 / pixel_length;
[super setFrame: newRect];
/* unblock_input (); */
}
@ -8174,7 +8160,12 @@ - (void)dealloc
{
NSTRACE ("[EmacsScroller dealloc]");
if (window)
wset_vertical_scroll_bar (window, Qnil);
{
if (horizontal)
wset_horizontal_scroll_bar (window, Qnil);
else
wset_vertical_scroll_bar (window, Qnil);
}
window = 0;
[super dealloc];
}
@ -8209,7 +8200,12 @@ -(bool)judge
if (view != nil)
view->scrollbarsNeedingUpdate++;
if (window)
wset_vertical_scroll_bar (window, Qnil);
{
if (horizontal)
wset_horizontal_scroll_bar (window, Qnil);
else
wset_vertical_scroll_bar (window, Qnil);
}
window = 0;
[self removeFromSuperview];
[self release];
@ -8259,7 +8255,7 @@ - (int) checkSamePosition: (int) position portion: (int) portion
{
float pos;
CGFloat por;
portion = max ((float)whole*min_portion/pixel_height, portion);
portion = max ((float)whole*min_portion/pixel_length, portion);
pos = (float)position / (whole - portion);
por = (CGFloat)portion/whole;
#ifdef NS_IMPL_COCOA
@ -8289,10 +8285,20 @@ - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
XSETWINDOW (win, window);
emacs_event->frame_or_window = win;
emacs_event->timestamp = EV_TIMESTAMP (e);
emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
emacs_event->arg = Qnil;
XSETINT (emacs_event->x, loc * pixel_height);
XSETINT (emacs_event->y, pixel_height-20);
if (horizontal)
{
emacs_event->kind = HORIZONTAL_SCROLL_BAR_CLICK_EVENT;
XSETINT (emacs_event->x, em_whole * loc / pixel_length);
XSETINT (emacs_event->y, em_whole);
}
else
{
emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
XSETINT (emacs_event->x, loc);
XSETINT (emacs_event->y, pixel_length-20);
}
if (q_event_ptr)
{
@ -8355,15 +8361,15 @@ - (void)mouseDown: (NSEvent *)e
switch (part)
{
case NSScrollerDecrementPage:
last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
last_hit_part = horizontal ? scroll_bar_before_handle : scroll_bar_above_handle; break;
case NSScrollerIncrementPage:
last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
last_hit_part = horizontal ? scroll_bar_after_handle : scroll_bar_below_handle; break;
case NSScrollerDecrementLine:
last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
last_hit_part = horizontal ? scroll_bar_left_arrow : scroll_bar_up_arrow; break;
case NSScrollerIncrementLine:
last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
last_hit_part = horizontal ? scroll_bar_right_arrow : scroll_bar_down_arrow; break;
case NSScrollerKnob:
last_hit_part = scroll_bar_handle; break;
last_hit_part = horizontal ? scroll_bar_horizontal_handle : scroll_bar_handle; break;
case NSScrollerKnobSlot: /* GNUstep-only */
last_hit_part = scroll_bar_move_ratio; break;
default: /* NSScrollerNoPart? */
@ -8372,36 +8378,34 @@ - (void)mouseDown: (NSEvent *)e
return;
}
if (inc != 0.0)
{
pos = 0; /* ignored */
/* set a timer to repeat, as we can't let superclass do this modally */
scroll_repeat_entry
= [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
target: self
selector: @selector (repeatScroll:)
userInfo: 0
repeats: YES]
retain];
}
else
if (part == NSScrollerKnob || part == NSScrollerKnobSlot)
{
/* handle, or on GNUstep possibly slot */
NSEvent *fake_event;
int length;
/* compute float loc in slot and mouse offset on knob */
sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
toView: nil];
loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
if (horizontal)
{
length = NSWidth (sr);
loc = ([e locationInWindow].x - NSMinX (sr));
}
else
{
length = NSHeight (sr);
loc = length - ([e locationInWindow].y - NSMinY (sr));
}
if (loc <= 0.0)
{
loc = 0.0;
edge = -1;
}
else if (loc >= NSHeight (sr))
else if (loc >= length)
{
loc = NSHeight (sr);
loc = length;
edge = 1;
}
@ -8411,17 +8415,16 @@ - (void)mouseDown: (NSEvent *)e
{
kr = [self convertRect: [self rectForPart: NSScrollerKnob]
toView: nil];
kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
if (horizontal)
kloc = ([e locationInWindow].x - NSMinX (kr));
else
kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
}
last_mouse_offset = kloc;
/* if knob, tell emacs a location offset by knob pos
(to indicate top of handle) */
if (part == NSScrollerKnob)
pos = (loc - last_mouse_offset) / NSHeight (sr);
else
/* else this is a slot click on GNUstep: go straight there */
pos = loc / NSHeight (sr);
if (part != NSScrollerKnob)
/* this is a slot click on GNUstep: go straight there */
pos = loc;
/* send a fake mouse-up to super to preempt modal -trackKnob: mode */
fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
@ -8435,6 +8438,19 @@ - (void)mouseDown: (NSEvent *)e
pressure: [e pressure]];
[super mouseUp: fake_event];
}
else
{
pos = 0; /* ignored */
/* set a timer to repeat, as we can't let superclass do this modally */
scroll_repeat_entry
= [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY
target: self
selector: @selector (repeatScroll:)
userInfo: 0
repeats: YES]
retain];
}
if (part != NSScrollerKnob)
[self sendScrollEventAtLoc: pos fromEvent: e];
@ -8446,23 +8462,34 @@ - (void)mouseDragged: (NSEvent *)e
{
NSRect sr;
double loc, pos;
int length;
NSTRACE ("[EmacsScroller mouseDragged:]");
sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
toView: nil];
loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
if (horizontal)
{
length = NSWidth (sr);
loc = ([e locationInWindow].x - NSMinX (sr));
}
else
{
length = NSHeight (sr);
loc = length - ([e locationInWindow].y - NSMinY (sr));
}
if (loc <= 0.0)
{
loc = 0.0;
}
else if (loc >= NSHeight (sr) + last_mouse_offset)
else if (loc >= length + last_mouse_offset)
{
loc = NSHeight (sr) + last_mouse_offset;
loc = length + last_mouse_offset;
}
pos = (loc - last_mouse_offset) / NSHeight (sr);
pos = (loc - last_mouse_offset);
[self sendScrollEventAtLoc: pos fromEvent: e];
}

View file

@ -793,7 +793,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
|| WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W))
#if (defined (HAVE_WINDOW_SYSTEM) \
&& ((defined (USE_TOOLKIT_SCROLL_BARS) && !defined (HAVE_NS)) \
&& ((defined (USE_TOOLKIT_SCROLL_BARS)) \
|| defined (HAVE_NTGUI)))
# define USE_HORIZONTAL_SCROLL_BARS true
#else