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:
parent
80a1e3b9b5
commit
e683a2570b
5 changed files with 123 additions and 143 deletions
|
@ -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).
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
201
src/nsterm.m
201
src/nsterm.m
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue