Make it possible to test rubber-banding in overflow scroll
[WebKit-https.git] / Source / WebKitLegacy / mac / DOM / DOMHTML.mm
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3  * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27
28 #import "DOMDocumentFragmentInternal.h"
29 #import "DOMExtensions.h"
30 #import "DOMHTMLCollectionInternal.h"
31 #import "DOMHTMLDocumentInternal.h"
32 #import "DOMHTMLInputElementInternal.h"
33 #import "DOMHTMLSelectElementInternal.h"
34 #import "DOMHTMLTextAreaElementInternal.h"
35 #import "DOMNodeInternal.h"
36 #import "DOMPrivate.h"
37 #import <WebCore/DocumentFragment.h>
38 #import <WebCore/FrameView.h>
39 #import <WebCore/HTMLCollection.h>
40 #import <WebCore/HTMLDocument.h>
41 #import <WebCore/HTMLInputElement.h>
42 #import <WebCore/HTMLParserIdioms.h>
43 #import <WebCore/HTMLSelectElement.h>
44 #import <WebCore/HTMLTextAreaElement.h>
45 #import <WebCore/Range.h>
46 #import <WebCore/RenderTextControl.h>
47 #import <WebCore/Settings.h>
48 #import <WebCore/markup.h>
49
50 #if PLATFORM(IOS)
51 #import "DOMHTMLElementInternal.h"
52 #import <WebCore/Autocapitalize.h>
53 #import <WebCore/HTMLTextFormControlElement.h>
54 #import <WebCore/JSMainThreadExecState.h>
55 #import <WebCore/RenderLayer.h>
56 #import <WebCore/WAKWindow.h>
57 #import <WebCore/WebCoreThreadMessage.h>
58 #endif
59
60 // FIXME: We should move all these into the various specific element source files.
61 // These were originally here because they were hand written and the rest generated,
62 // but that is no longer true.
63
64 #if PLATFORM(IOS)
65
66 using namespace WebCore;
67
68 @implementation DOMHTMLElement (DOMHTMLElementExtensions)
69
70 - (int)scrollXOffset
71 {
72     RenderObject *renderer = core(self)->renderer();
73     if (!renderer)
74         return 0;
75
76     if (!is<RenderBlockFlow>(*renderer))
77         renderer = renderer->containingBlock();
78
79     if (!is<RenderBox>(*renderer) || !renderer->hasOverflowClip())
80         return 0;
81
82     return downcast<RenderBox>(*renderer).layer()->scrollOffset().x();
83 }
84
85 - (int)scrollYOffset
86 {
87     RenderObject* renderer = core(self)->renderer();
88     if (!renderer)
89         return 0;
90
91     if (!is<RenderBlockFlow>(*renderer))
92         renderer = renderer->containingBlock();
93     if (!is<RenderBox>(*renderer) || !renderer->hasOverflowClip())
94         return 0;
95
96     return downcast<RenderBox>(*renderer).layer()->scrollOffset().y();
97 }
98
99 - (void)setScrollXOffset:(int)x scrollYOffset:(int)y
100 {
101     [self setScrollXOffset:x scrollYOffset:y adjustForIOSCaret:NO];
102 }
103
104 - (void)setScrollXOffset:(int)x scrollYOffset:(int)y adjustForIOSCaret:(BOOL)adjustForIOSCaret
105 {
106     RenderObject* renderer = core(self)->renderer();
107     if (!renderer)
108         return;
109
110     if (!is<RenderBlockFlow>(*renderer))
111         renderer = renderer->containingBlock();
112     if (!renderer->hasOverflowClip() || !is<RenderBox>(*renderer))
113         return;
114
115     RenderLayer* layer = downcast<RenderBox>(*renderer).layer();
116     if (adjustForIOSCaret)
117         layer->setAdjustForIOSCaretWhenScrolling(true);
118     layer->scrollToOffset(ScrollOffset(x, y), ScrollClamping::Unclamped);
119     if (adjustForIOSCaret)
120         layer->setAdjustForIOSCaretWhenScrolling(false);
121 }
122
123 - (void)absolutePosition:(int *)x :(int *)y :(int *)w :(int *)h
124 {
125     RenderBox *renderer = core(self)->renderBox();
126     if (renderer) {
127         if (w)
128             *w = renderer->width();
129         if (h)
130             *h = renderer->width();
131         if (x && y) {
132             FloatPoint floatPoint(*x, *y);
133             renderer->localToAbsolute(floatPoint);
134             IntPoint point = roundedIntPoint(floatPoint);
135             *x = point.x();
136             *y = point.y();
137         }
138     }
139 }
140
141 @end
142
143 #endif // PLATFORM(IOS)
144
145 //------------------------------------------------------------------------------------------
146 // DOMHTMLDocument
147
148 @implementation DOMHTMLDocument (DOMHTMLDocumentExtensions)
149
150 - (DOMDocumentFragment *)createDocumentFragmentWithMarkupString:(NSString *)markupString baseURL:(NSURL *)baseURL
151 {
152     return kit(createFragmentFromMarkup(*core(self), markupString, [baseURL absoluteString]).ptr());
153 }
154
155 - (DOMDocumentFragment *)createDocumentFragmentWithText:(NSString *)text
156 {
157     // FIXME: Since this is not a contextual fragment, it won't handle whitespace properly.
158     return kit(createFragmentFromText(core(self)->createRange(), text).ptr());
159 }
160
161 @end
162
163 @implementation DOMHTMLDocument (WebPrivate)
164
165 - (DOMDocumentFragment *)_createDocumentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
166 {
167     NSURL *baseURL = core(self)->completeURL(WebCore::stripLeadingAndTrailingHTMLSpaces(baseURLString));
168     return [self createDocumentFragmentWithMarkupString:markupString baseURL:baseURL];
169 }
170
171 - (DOMDocumentFragment *)_createDocumentFragmentWithText:(NSString *)text
172 {
173     return [self createDocumentFragmentWithText:text];
174 }
175
176 @end
177
178 @implementation DOMHTMLInputElement (FormAutoFillTransition)
179
180 - (BOOL)_isTextField
181 {
182     return core(self)->isTextField();
183 }
184
185 @end
186
187 @implementation DOMHTMLSelectElement (FormAutoFillTransition)
188
189 - (void)_activateItemAtIndex:(int)index
190 {
191     // Use the setSelectedIndexByUser function so a change event will be fired. <rdar://problem/6760590>
192     if (WebCore::HTMLSelectElement* select = core(self))
193         select->optionSelectedByUser(index, true);
194 }
195
196 - (void)_activateItemAtIndex:(int)index allowMultipleSelection:(BOOL)allowMultipleSelection
197 {
198     // Use the setSelectedIndexByUser function so a change event will be fired. <rdar://problem/6760590>
199     // If this is a <select multiple> the allowMultipleSelection flag will allow setting multiple
200     // selections without clearing the other selections.
201     if (WebCore::HTMLSelectElement* select = core(self))
202         select->optionSelectedByUser(index, true, allowMultipleSelection);
203 }
204
205 @end
206
207 #if PLATFORM(IOS)
208
209 @implementation DOMHTMLInputElement (FormPromptAdditions)
210
211 - (BOOL)_isEdited
212 {
213     return core(self)->lastChangeWasUserEdit();
214 }
215
216 @end
217
218 @implementation DOMHTMLTextAreaElement (FormPromptAdditions)
219
220 - (BOOL)_isEdited
221 {
222     return core(self)->lastChangeWasUserEdit();
223 }
224
225 @end
226
227 static WebAutocapitalizeType webAutocapitalizeType(AutocapitalizeType type)
228 {
229     switch (type) {
230     case AutocapitalizeTypeDefault:
231         return WebAutocapitalizeTypeDefault;
232     case AutocapitalizeTypeNone:
233         return WebAutocapitalizeTypeNone;
234     case AutocapitalizeTypeWords:
235         return WebAutocapitalizeTypeWords;
236     case AutocapitalizeTypeSentences:
237         return WebAutocapitalizeTypeSentences;
238     case AutocapitalizeTypeAllCharacters:
239         return WebAutocapitalizeTypeAllCharacters;
240     }
241 }
242
243 @implementation DOMHTMLInputElement (AutocapitalizeAdditions)
244
245 - (WebAutocapitalizeType)_autocapitalizeType
246 {
247     WebCore::HTMLInputElement* inputElement = core(self);
248     return webAutocapitalizeType(inputElement->autocapitalizeType());
249 }
250
251 @end
252
253 @implementation DOMHTMLTextAreaElement (AutocapitalizeAdditions)
254
255 - (WebAutocapitalizeType)_autocapitalizeType
256 {
257     WebCore::HTMLTextAreaElement* textareaElement = core(self);
258     return webAutocapitalizeType(textareaElement->autocapitalizeType());
259 }
260
261 @end
262
263 @implementation DOMHTMLInputElement (WebInputChangeEventAdditions)
264
265 - (void)setValueWithChangeEvent:(NSString *)newValue
266 {
267     WebCore::JSMainThreadNullState state;
268     core(self)->setValue(newValue, DispatchInputAndChangeEvent);
269 }
270
271 - (void)setValueAsNumberWithChangeEvent:(double)newValueAsNumber
272 {
273     WebCore::JSMainThreadNullState state;
274     core(self)->setValueAsNumber(newValueAsNumber, DispatchInputAndChangeEvent);
275 }
276
277 @end
278
279 #endif
280
281 Class kitClass(WebCore::HTMLCollection* collection)
282 {
283     if (collection->type() == WebCore::SelectOptions)
284         return [DOMHTMLOptionsCollection class];
285     return [DOMHTMLCollection class];
286 }