Fix deployment build bustage
[WebKit-https.git] / WebCore / kwq / KWQScrollView.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #import "KWQScrollView.h"
27
28 #import "KWQExceptions.h"
29 #import "KWQLogging.h"
30 #import "KWQNSViewExtras.h"
31 #import "WebCoreFrameView.h"
32
33 /*
34     This class implementation does NOT actually emulate the Qt QScrollView.
35     It does provide an implementation that khtml will use to interact with
36     WebKit's WebFrameView documentView and our NSScrollView subclass.
37
38     QScrollView's view is a NSScrollView (or subclass of NSScrollView)
39     in most cases. That scrollview is a subview of an
40     WebCoreFrameView. The WebCoreFrameView's documentView will also be
41     the scroll view's documentView.
42     
43     The WebCoreFrameView's size is the frame size.  The WebCoreFrameView's documentView
44     corresponds to the frame content size.  The scrollview itself is autosized to the
45     WebCoreFrameView's size (see QWidget::resize).
46 */
47
48 @interface NSView (KWQExtensions)
49 - (BOOL)_KWQ_isScrollView;
50 @end
51
52 @implementation NSView (KWQExtensions)
53
54 - (BOOL)_KWQ_isScrollView
55 {
56     return [self isKindOfClass:[NSScrollView class]];
57 }
58
59 @end
60
61 QWidget* QScrollView::viewport() const
62 {
63     return const_cast<QScrollView *>(this);
64 }
65
66 int QScrollView::visibleWidth() const
67 {
68     NSScrollView *view = (NSScrollView *)getView();
69
70     KWQ_BLOCK_EXCEPTIONS;
71     if ([view _KWQ_isScrollView]) {
72         return (int)[view documentVisibleRect].size.width;
73     } else {
74         return (int)[view bounds].size.width;
75     }
76     KWQ_UNBLOCK_EXCEPTIONS;
77
78     return 0;
79 }
80
81 int QScrollView::visibleHeight() const
82 {
83     NSScrollView *view = (NSScrollView *)getView();
84     
85     KWQ_BLOCK_EXCEPTIONS;
86     if ([view _KWQ_isScrollView]) {
87         return (int)[view documentVisibleRect].size.height;
88     } else {
89         return (int)[view bounds].size.height;
90     }
91     KWQ_UNBLOCK_EXCEPTIONS;
92     
93     return 0;
94 }
95
96 int QScrollView::contentsWidth() const
97 {
98     NSView *docView, *view = getView();
99     docView = getDocumentView();
100
101     KWQ_BLOCK_EXCEPTIONS;
102     if (docView) {
103         return (int)[docView bounds].size.width;
104     } else {
105         return (int)[view bounds].size.width;
106     }
107     KWQ_UNBLOCK_EXCEPTIONS;
108
109     return 0;
110 }
111
112 int QScrollView::contentsHeight() const
113 {
114     NSView *docView, *view = getView();
115     docView = getDocumentView();
116
117     KWQ_BLOCK_EXCEPTIONS;
118     if (docView) {
119         return (int)[docView bounds].size.height;
120     } else {
121         return (int)[view bounds].size.height;
122     }
123     KWQ_UNBLOCK_EXCEPTIONS;
124
125     return 0;
126 }
127
128 int QScrollView::contentsX() const
129 {
130     NSView *view = getView();
131
132     KWQ_BLOCK_EXCEPTIONS;
133     if ([view _KWQ_isScrollView]) {
134         NSScrollView *sview = view;
135         return (int)[sview documentVisibleRect].origin.x;
136     } else {
137         return (int)[view visibleRect].origin.x;
138     }
139     KWQ_UNBLOCK_EXCEPTIONS;
140
141     return 0;
142 }
143
144 int QScrollView::contentsY() const
145 {
146     NSView *view = getView();
147
148     KWQ_BLOCK_EXCEPTIONS;
149     if ([view _KWQ_isScrollView]) {
150         NSScrollView *sview = view;
151         return (int)[sview documentVisibleRect].origin.y;
152     } else {
153         return (int)[view visibleRect].origin.y;
154     }
155     KWQ_UNBLOCK_EXCEPTIONS;
156
157     return 0;
158 }
159
160 int QScrollView::childX(QWidget* w)
161 {
162     return w->x();
163 }
164
165 int QScrollView::childY(QWidget* w)
166 {
167     return w->y();
168 }
169
170 void QScrollView::scrollBy(int dx, int dy)
171 {
172     setContentsPos(contentsX() + dx, contentsY() + dy);
173 }
174
175 void QScrollView::setContentsPos(int x, int y)
176 {
177     x = (x < 0) ? 0 : x;
178     y = (y < 0) ? 0 : y;
179     NSPoint p =  NSMakePoint(x,y);
180
181     KWQ_BLOCK_EXCEPTIONS;
182     NSView *docView;
183     NSView *view = getView();    
184     docView = getDocumentView();
185     if (docView)
186         view = docView;
187         
188     [view scrollPoint:p];
189     KWQ_UNBLOCK_EXCEPTIONS;
190 }
191
192 void QScrollView::setVScrollBarMode(ScrollBarMode vMode)
193 {
194     NSView* view = getView();
195
196     KWQ_BLOCK_EXCEPTIONS;
197     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
198         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
199         [frameView setVerticalScrollingMode: (WebCoreScrollBarMode)vMode];
200     }
201     KWQ_UNBLOCK_EXCEPTIONS;
202 }
203
204 void QScrollView::setHScrollBarMode(ScrollBarMode hMode)
205 {
206     NSView* view = getView();
207
208     KWQ_BLOCK_EXCEPTIONS;
209     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
210         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
211         [frameView setHorizontalScrollingMode: (WebCoreScrollBarMode)hMode];
212     }
213     KWQ_UNBLOCK_EXCEPTIONS;
214 }
215
216 void QScrollView::setScrollBarsMode(ScrollBarMode mode)
217 {
218     NSView* view = getView();
219
220     KWQ_BLOCK_EXCEPTIONS;
221     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
222         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
223         [frameView setScrollingMode: (WebCoreScrollBarMode)mode];
224     }
225     KWQ_UNBLOCK_EXCEPTIONS;
226 }
227
228 QScrollView::ScrollBarMode
229 QScrollView::vScrollBarMode() const
230 {
231     NSView* view = getView();
232
233     KWQ_BLOCK_EXCEPTIONS;
234     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
235         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
236         return (ScrollBarMode)[frameView verticalScrollingMode];
237     }
238     KWQ_UNBLOCK_EXCEPTIONS;
239
240     return Auto;
241 }
242
243 QScrollView::ScrollBarMode
244 QScrollView::hScrollBarMode() const
245 {
246     NSView* view = getView();
247
248     KWQ_BLOCK_EXCEPTIONS;
249     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
250         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
251         return (ScrollBarMode)[frameView horizontalScrollingMode];
252     }
253     KWQ_UNBLOCK_EXCEPTIONS;
254
255     return Auto;
256 }
257
258 bool QScrollView::hasVerticalScrollBar() const
259 {
260     NSScrollView *view = (NSScrollView *)getView();
261     
262     KWQ_BLOCK_EXCEPTIONS;
263     if ([view _KWQ_isScrollView])
264         return  [view hasVerticalScroller];
265     KWQ_UNBLOCK_EXCEPTIONS;
266
267     return false;
268 }
269
270 bool QScrollView::hasHorizontalScrollBar() const
271 {
272     NSScrollView *view = (NSScrollView *)getView();
273     
274     KWQ_BLOCK_EXCEPTIONS;
275     if ([view _KWQ_isScrollView])
276         return [view hasHorizontalScroller];
277     KWQ_UNBLOCK_EXCEPTIONS;
278
279     return false;
280 }
281
282 void QScrollView::suppressScrollBars(bool suppressed,  bool repaintOnUnsuppress)
283 {
284     NSView* view = getView();
285
286     KWQ_BLOCK_EXCEPTIONS;
287     if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) {
288         NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
289         [frameView setScrollBarsSuppressed: suppressed
290                        repaintOnUnsuppress: repaintOnUnsuppress];
291     }
292     KWQ_UNBLOCK_EXCEPTIONS;
293 }
294
295 void QScrollView::addChild(QWidget* child, int x, int y)
296 {
297     ASSERT(child != this);
298     
299     // we don't need to do the offscreen position initialization that KDE needs
300     if (x != -500000)
301         child->move(x, y);
302
303     NSView *thisView = getView();
304     NSView *thisDocView = getDocumentView();
305     if (thisDocView)
306         thisView = thisDocView;
307
308 #ifndef NDEBUG
309     NSView *subview = child->getOuterView();
310
311     LOG(Frames, "Adding %p %@ at (%d,%d) w %d h %d\n", subview,
312         [(id)[subview class] className], x, y, (int)[subview frame].size.width, (int)[subview frame].size.height);
313 #endif
314     child->addToSuperview(thisView);
315 }
316
317 void QScrollView::removeChild(QWidget* child)
318 {
319     child->removeFromSuperview();
320 }
321
322 void QScrollView::resizeContents(int w, int h)
323 {
324     KWQ_BLOCK_EXCEPTIONS;
325     int _w = w;
326     int _h = h;
327
328     LOG(Frames, "%p %@ at w %d h %d\n", getView(), [(id)[getView() class] className], w, h);
329     NSView *view = getView();
330     if ([view _KWQ_isScrollView]){
331         view = getDocumentView();
332         
333         LOG(Frames, "%p %@ at w %d h %d\n", view, [(id)[view class] className], w, h);
334         if (_w < 0)
335             _w = 0;
336         if (_h < 0)
337             _h = 0;
338
339         [view setFrameSize: NSMakeSize (_w,_h)];
340     } else {
341         resize (_w, _h);
342     }
343     KWQ_UNBLOCK_EXCEPTIONS;
344 }
345
346 void QScrollView::updateContents(int x, int y, int w, int h, bool now)
347 {
348     updateContents(QRect(x, y, w, h), now);
349 }
350
351 void QScrollView::updateContents(const QRect &rect, bool now)
352 {
353     KWQ_BLOCK_EXCEPTIONS;
354     NSView * view = getView();
355
356     if ([view _KWQ_isScrollView])
357         view = getDocumentView();
358
359     if (now)
360         [view displayRect: rect];
361     else
362         [view setNeedsDisplayInRect:rect];
363     KWQ_UNBLOCK_EXCEPTIONS;
364 }
365
366 void QScrollView::repaintContents(int x, int y, int w, int h, bool erase)
367 {
368     LOG(Frames, "%p %@ at (%d,%d) w %d h %d\n", getView(), [(id)[getView() class] className], x, y, w, h);
369 }
370
371 QPoint QScrollView::contentsToViewport(const QPoint &p)
372 {
373     int vx, vy;
374     contentsToViewport(p.x(), p.y(), vx, vy);
375     return QPoint(vx, vy);
376 }
377
378 // NB, for us "viewport" means the NSWindow's coord system, which is origin lower left
379
380 void QScrollView::contentsToViewport(int x, int y, int& vx, int& vy)
381 {
382     KWQ_BLOCK_EXCEPTIONS;
383
384     NSView *docView;
385     NSView *view = getView();    
386      
387     docView = getDocumentView();
388     if (docView)
389         view = docView;
390     
391     NSPoint np = [view convertPoint: NSMakePoint (x, y) toView: nil];
392     vx = (int)np.x;
393     vy = (int)np.y;
394     
395     return;
396
397     KWQ_UNBLOCK_EXCEPTIONS;
398     
399     vx = 0;
400     vy = 0;
401 }
402
403 void QScrollView::viewportToContents(int vx, int vy, int& x, int& y)
404 {
405     KWQ_BLOCK_EXCEPTIONS;
406
407     NSView *docView;
408     NSView *view = getView();    
409
410     docView = getDocumentView();
411     if (docView)
412         view = docView;
413         
414     NSPoint np = [view convertPoint: NSMakePoint (vx, vy) fromView: nil];
415     x = (int)np.x;
416     y = (int)np.y;
417
418     return;
419
420     KWQ_UNBLOCK_EXCEPTIONS;
421
422     x = 0;
423     y = 0;
424 }
425
426 void QScrollView::setStaticBackground(bool b)
427 {
428     NSScrollView *view = (NSScrollView *)getView();
429     KWQ_BLOCK_EXCEPTIONS;
430     if ([view _KWQ_isScrollView])
431         [[view contentView] setCopiesOnScroll: !b];
432     KWQ_UNBLOCK_EXCEPTIONS;
433 }
434
435 void QScrollView::resizeEvent(QResizeEvent *)
436 {
437 }
438
439 void QScrollView::setContentsPosRecursive(int x, int y)
440 {
441     KWQ_BLOCK_EXCEPTIONS;
442     [getDocumentView() _KWQ_scrollPointRecursive:NSMakePoint(x, y)];
443     KWQ_UNBLOCK_EXCEPTIONS;
444 }
445
446 void QScrollView::ensureVisible(int x, int y)
447 {
448     // Note that the definition of ensureVisible in trolltech documentation says:
449     // "Scrolls the content so that the point (x, y) is visible with at least 
450     // 50-pixel margins (if possible, otherwise centered).", which is
451     // not what we're doing here.
452     KWQ_BLOCK_EXCEPTIONS;
453     [getDocumentView() scrollRectToVisible:NSMakeRect(x, y, 0, 0)];
454     KWQ_UNBLOCK_EXCEPTIONS;
455 }
456
457 void QScrollView::ensureVisible(int x, int y, int xmargin, int ymargin)
458 {
459     // Note that the definition of ensureVisible in trolltech documentation says:
460     // "Scrolls the content so that the point (x, y) is visible with at least the 
461     // xmargin and ymargin margins (if possible, otherwise centered).", which is
462     // not what we're doing here.
463     KWQ_BLOCK_EXCEPTIONS;
464     [getDocumentView() scrollRectToVisible:NSMakeRect(x, y, xmargin, ymargin)];
465     KWQ_UNBLOCK_EXCEPTIONS;
466 }
467
468 void QScrollView::ensureRectVisibleCentered(const QRect &rect, bool forceCentering)
469 {
470     KWQ_BLOCK_EXCEPTIONS;
471     [getDocumentView() _KWQ_scrollRectToVisible:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()) forceCentering:forceCentering];
472     KWQ_UNBLOCK_EXCEPTIONS;
473 }
474
475 NSView *QScrollView::getDocumentView() const
476 {
477     id view = getView();
478
479     KWQ_BLOCK_EXCEPTIONS;
480     if ([view respondsToSelector:@selector(documentView)]) 
481         return [view documentView];
482     KWQ_UNBLOCK_EXCEPTIONS;
483     
484     return nil;
485 }