Fix for 3841186, scrollbar shows up disabled when it should not appear at all. ...
[WebKit-https.git] / WebKit / WebView.subproj / WebDynamicScrollBarsView.m
1 //
2 //  WebDynamicScrollBarsView.m
3 //  WebKit
4 //
5 //  Created by John Sullivan on Tue Jan 22 2002.
6 //  Copyright (c) 2001, 2002 Apple Computer, Inc. All rights reserved.
7 //
8
9 #import <WebKit/WebDynamicScrollBarsView.h>
10
11 #import <WebKit/WebDocument.h>
12
13 @implementation WebDynamicScrollBarsView
14
15 - (void)setSuppressLayout: (BOOL)flag;
16 {
17     suppressLayout = flag;
18 }
19
20 - (void)setScrollBarsSuppressed:(BOOL)suppressed repaintOnUnsuppress:(BOOL)repaint
21 {
22     suppressScrollers = suppressed;
23     if (suppressed || repaint) {
24         [[self verticalScroller] setNeedsDisplay: !suppressed];
25         [[self horizontalScroller] setNeedsDisplay: !suppressed];
26     }
27 }
28
29 - (void)updateScrollers
30 {
31     // We need to do the work below twice in the case where a scroll bar disappears,
32     // making the second layout have a wider width than the first. Doing it more than
33     // twice would indicate some kind of infinite loop, so we do it at most twice.
34     // It's quite efficient to do this work twice in the normal case, so we don't bother
35     // trying to figure out of the second pass is needed or not.
36     if (inUpdateScrollers)
37         return;
38     
39     inUpdateScrollers = true;
40
41     int pass;
42     BOOL hasVerticalScroller = [self hasVerticalScroller];
43     BOOL hasHorizontalScroller = [self hasHorizontalScroller];
44     BOOL oldHasVertical = hasVerticalScroller;
45     BOOL oldHasHorizontal = hasHorizontalScroller;
46
47     for (pass = 0; pass < 2; pass++) {
48         BOOL scrollsVertically;
49         BOOL scrollsHorizontally;
50
51         if (!suppressLayout && !suppressScrollers &&
52             (hScroll == WebCoreScrollBarAuto || vScroll == WebCoreScrollBarAuto))
53         {
54             // Do a layout if pending, before checking if scrollbars are needed.
55             // This fixes 2969367, although may introduce a slowdown in live resize performance.
56             NSView *documentView = [self documentView];
57             if ((hasVerticalScroller != oldHasVertical ||
58                 hasHorizontalScroller != oldHasHorizontal || [documentView inLiveResize]) && [documentView conformsToProtocol:@protocol(WebDocumentView)]) {
59                 [(id <WebDocumentView>)documentView setNeedsLayout: YES];
60                 [(id <WebDocumentView>)documentView layout];
61             }
62             
63             NSSize documentSize = [documentView frame].size;
64             NSSize frameSize = [self frame].size;
65             
66             scrollsVertically = (vScroll == WebCoreScrollBarAlwaysOn) ||
67                 (vScroll == WebCoreScrollBarAuto && documentSize.height > frameSize.height);
68             if (scrollsVertically)
69                 scrollsHorizontally = (hScroll == WebCoreScrollBarAlwaysOn) ||
70                     (hScroll == WebCoreScrollBarAuto && documentSize.width + [NSScroller scrollerWidth] > frameSize.width);
71             else {
72                 scrollsHorizontally = (hScroll == WebCoreScrollBarAlwaysOn) ||
73                     (hScroll == WebCoreScrollBarAuto && documentSize.width > frameSize.width);
74                 if (scrollsHorizontally)
75                     scrollsVertically = (vScroll == WebCoreScrollBarAlwaysOn) ||
76                         (vScroll == WebCoreScrollBarAuto && documentSize.height + [NSScroller scrollerWidth] > frameSize.height);
77             }
78         }
79         else {
80             scrollsHorizontally = (hScroll == WebCoreScrollBarAuto) ? hasHorizontalScroller : (hScroll == WebCoreScrollBarAlwaysOn);
81             scrollsVertically = (vScroll == WebCoreScrollBarAuto) ? hasVerticalScroller : (vScroll == WebCoreScrollBarAlwaysOn);
82         }
83         
84         if (hasVerticalScroller != scrollsVertically) {
85             [self setHasVerticalScroller:scrollsVertically];
86             hasVerticalScroller = scrollsVertically;
87         }
88
89         if (hasHorizontalScroller != scrollsHorizontally) {
90             [self setHasHorizontalScroller:scrollsHorizontally];
91             hasHorizontalScroller = scrollsHorizontally;
92         }
93     }
94
95     if (suppressScrollers) {
96         [[self verticalScroller] setNeedsDisplay: NO];
97         [[self horizontalScroller] setNeedsDisplay: NO];
98     }
99     
100     inUpdateScrollers = false;
101 }
102
103 // Make the horizontal and vertical scroll bars come and go as needed.
104 - (void)reflectScrolledClipView:(NSClipView *)clipView
105 {
106     if (clipView == [self contentView]) {
107         // FIXME: This hack here prevents infinite recursion that takes place when we
108         // gyrate between having a vertical scroller and not having one. A reproducible
109         // case is clicking on the "the Policy Routing text" link at
110         // http://www.linuxpowered.com/archive/howto/Net-HOWTO-8.html.
111         // The underlying cause is some problem in the NSText machinery, but I was not
112         // able to pin it down.
113         if (!inUpdateScrollers && [[NSGraphicsContext currentContext] isDrawingToScreen])
114             [self updateScrollers];
115     }
116     [super reflectScrolledClipView:clipView];
117
118     // Validate the scrollers if they're being suppressed.
119     if (suppressScrollers) {
120         [[self verticalScroller] setNeedsDisplay: NO];
121         [[self horizontalScroller] setNeedsDisplay: NO];
122     }
123 }
124
125 - (void)setAllowsScrolling:(BOOL)flag
126 {
127     hScroll = vScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
128     [self updateScrollers];
129 }
130
131 - (BOOL)allowsScrolling
132 {
133     return hScroll != WebCoreScrollBarAlwaysOff && vScroll != WebCoreScrollBarAlwaysOff;
134 }
135
136 - (void)setAllowsHorizontalScrolling:(BOOL)flag
137 {
138     hScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
139     [self updateScrollers];
140 }
141
142 - (void)setAllowsVerticalScrolling:(BOOL)flag
143 {
144     vScroll = (flag ? WebCoreScrollBarAuto : WebCoreScrollBarAlwaysOff);
145     [self updateScrollers];
146 }
147
148 - (BOOL)allowsHorizontalScrolling
149 {
150     return hScroll != WebCoreScrollBarAlwaysOff;
151 }
152
153 - (BOOL)allowsVerticalScrolling
154 {
155     return vScroll != WebCoreScrollBarAlwaysOff;
156 }
157
158 -(WebCoreScrollBarMode)horizontalScrollingMode
159 {
160     return hScroll;
161 }
162
163 -(WebCoreScrollBarMode)verticalScrollingMode
164 {
165     return vScroll;
166 }
167
168 - (void)setHorizontalScrollingMode:(WebCoreScrollBarMode)mode
169 {
170     if (mode == hScroll)
171         return;
172     hScroll = mode;
173     [self updateScrollers];
174 }
175
176 - (void)setVerticalScrollingMode:(WebCoreScrollBarMode)mode
177 {
178     if (mode == vScroll)
179         return;
180     vScroll = mode;
181     [self updateScrollers];
182 }
183
184 - (void)setScrollingMode:(WebCoreScrollBarMode)mode
185 {
186     if (mode == vScroll && mode == hScroll)
187         return;
188     vScroll = hScroll = mode;
189     [self updateScrollers];
190 }
191 @end