summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Third <alan@idiocy.org>2016-05-01 13:04:07 +0200
committerMartin Rudalics <rudalics@gmx.at>2016-05-01 13:04:07 +0200
commite683a2570be6f2e4f8defa4e7ee35a7d87f18918 (patch)
tree0b749572bb70a6222d333d932bda7a29b18e5729
parent80a1e3b9b58aaeb71913737e07bb305d9eb54437 (diff)
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.
-rw-r--r--lisp/scroll-bar.el3
-rw-r--r--lisp/term/ns-win.el56
-rw-r--r--src/nsterm.h4
-rw-r--r--src/nsterm.m201
-rw-r--r--src/window.h2
5 files changed, 123 insertions, 143 deletions
diff --git a/lisp/scroll-bar.el b/lisp/scroll-bar.el
index 5cfa2c4353..838f9bf80c 100644
--- a/lisp/scroll-bar.el
+++ b/lisp/scroll-bar.el
@@ -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).
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index 452c68d017..5080ed0a8f 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -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.
diff --git a/src/nsterm.h b/src/nsterm.h
index 0aea9cca11..6cad337f3f 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -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;
diff --git a/src/nsterm.m b/src/nsterm.m
index 34c5395b63..1d48c041ba 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -1801,23 +1801,6 @@ x_set_window_size (struct frame *f,
[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 @@ ns_set_vertical_scroll_bar (struct window *window,
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 @@ ns_set_horizontal_scroll_bar (struct window *window,
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 @@ ns_set_horizontal_scroll_bar (struct window *window,
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 @@ ns_redeem_scroll_bar (struct window *window)
{
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
{
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
{
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
{
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 @@ not_in_argv (NSString *arg)
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 @@ not_in_argv (NSString *arg)
{
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];
}
diff --git a/src/window.h b/src/window.h
index 84180c96a7..1fd19369c3 100644
--- a/src/window.h
+++ b/src/window.h
@@ -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