Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / views / SkWindow.cpp
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkWindow.h"
9 #include "SkCanvas.h"
10 #include "SkOSMenu.h"
11 #include "SkSurface.h"
12 #include "SkSystemEventTypes.h"
13 #include "SkTime.h"
14
15 #define SK_EventDelayInval "\xd" "n" "\xa" "l"
16
17 SkWindow::SkWindow()
18     : fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
19     , fFocusView(NULL)
20 {
21     fClicks.reset();
22     fWaitingOnInval = false;
23
24 #ifdef SK_BUILD_FOR_WINCE
25     fColorType = kRGB_565_SkColorType;
26 #else
27     fColorType = kN32_SkColorType;
28 #endif
29
30     fMatrix.reset();
31 }
32
33 SkWindow::~SkWindow() {
34     fClicks.deleteAll();
35     fMenus.deleteAll();
36 }
37
38 SkSurface* SkWindow::createSurface() {
39     const SkBitmap& bm = this->getBitmap();
40     return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
41 }
42
43 void SkWindow::setMatrix(const SkMatrix& matrix) {
44     if (fMatrix != matrix) {
45         fMatrix = matrix;
46         this->inval(NULL);
47     }
48 }
49
50 void SkWindow::preConcat(const SkMatrix& matrix) {
51     SkMatrix m;
52     m.setConcat(fMatrix, matrix);
53     this->setMatrix(m);
54 }
55
56 void SkWindow::postConcat(const SkMatrix& matrix) {
57     SkMatrix m;
58     m.setConcat(matrix, fMatrix);
59     this->setMatrix(m);
60 }
61
62 void SkWindow::setColorType(SkColorType ct) {
63     this->resize(fBitmap.width(), fBitmap.height(), ct);
64 }
65
66 void SkWindow::resize(int width, int height, SkColorType ct) {
67     if (ct == kUnknown_SkColorType)
68         ct = fColorType;
69
70     if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
71         fColorType = ct;
72         fBitmap.allocPixels(SkImageInfo::Make(width, height,
73                                               ct, kPremul_SkAlphaType));
74
75         this->setSize(SkIntToScalar(width), SkIntToScalar(height));
76         this->inval(NULL);
77     }
78 }
79
80 bool SkWindow::handleInval(const SkRect* localR) {
81     SkIRect ir;
82
83     if (localR) {
84         SkRect devR;
85         SkMatrix inverse;
86         if (!fMatrix.invert(&inverse)) {
87             return false;
88         }
89         fMatrix.mapRect(&devR, *localR);
90         devR.round(&ir);
91     } else {
92         ir.set(0, 0,
93                SkScalarRoundToInt(this->width()),
94                SkScalarRoundToInt(this->height()));
95     }
96     fDirtyRgn.op(ir, SkRegion::kUnion_Op);
97
98     this->onHandleInval(ir);
99     return true;
100 }
101
102 void SkWindow::forceInvalAll() {
103     fDirtyRgn.setRect(0, 0,
104                       SkScalarCeilToInt(this->width()),
105                       SkScalarCeilToInt(this->height()));
106 }
107
108 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
109     #include <windows.h>
110     #include <gx.h>
111     extern GXDisplayProperties gDisplayProps;
112 #endif
113
114 #ifdef SK_SIMULATE_FAILED_MALLOC
115 extern bool gEnableControlledThrow;
116 #endif
117
118 bool SkWindow::update(SkIRect* updateArea) {
119     if (!fDirtyRgn.isEmpty()) {
120         SkBitmap bm = this->getBitmap();
121
122 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
123         char* buffer = (char*)GXBeginDraw();
124         SkASSERT(buffer);
125
126         RECT    rect;
127         GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
128         buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
129
130         bm.setPixels(buffer);
131 #endif
132
133         SkAutoTUnref<SkSurface> surface(this->createSurface());
134         SkCanvas* canvas = surface->getCanvas();
135
136         canvas->clipRegion(fDirtyRgn);
137         if (updateArea)
138             *updateArea = fDirtyRgn.getBounds();
139
140         SkAutoCanvasRestore acr(canvas, true);
141         canvas->concat(fMatrix);
142
143         // empty this now, so we can correctly record any inval calls that
144         // might be made during the draw call.
145         fDirtyRgn.setEmpty();
146
147 #ifdef SK_SIMULATE_FAILED_MALLOC
148         gEnableControlledThrow = true;
149 #endif
150 #ifdef SK_BUILD_FOR_WIN32
151         //try {
152             this->draw(canvas);
153         //}
154         //catch (...) {
155         //}
156 #else
157         this->draw(canvas);
158 #endif
159 #ifdef SK_SIMULATE_FAILED_MALLOC
160         gEnableControlledThrow = false;
161 #endif
162
163 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
164         GXEndDraw();
165 #endif
166
167         return true;
168     }
169     return false;
170 }
171
172 bool SkWindow::handleChar(SkUnichar uni) {
173     if (this->onHandleChar(uni))
174         return true;
175
176     SkView* focus = this->getFocusView();
177     if (focus == NULL)
178         focus = this;
179
180     SkEvent evt(SK_EventType_Unichar);
181     evt.setFast32(uni);
182     return focus->doEvent(evt);
183 }
184
185 bool SkWindow::handleKey(SkKey key) {
186     if (key == kNONE_SkKey)
187         return false;
188
189     if (this->onHandleKey(key))
190         return true;
191
192     // send an event to the focus-view
193     {
194         SkView* focus = this->getFocusView();
195         if (focus == NULL)
196             focus = this;
197
198         SkEvent evt(SK_EventType_Key);
199         evt.setFast32(key);
200         if (focus->doEvent(evt))
201             return true;
202     }
203
204     if (key == kUp_SkKey || key == kDown_SkKey) {
205         if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
206             this->onSetFocusView(NULL);
207         return true;
208     }
209     return false;
210 }
211
212 bool SkWindow::handleKeyUp(SkKey key) {
213     if (key == kNONE_SkKey)
214         return false;
215
216     if (this->onHandleKeyUp(key))
217         return true;
218
219     //send an event to the focus-view
220     {
221         SkView* focus = this->getFocusView();
222         if (focus == NULL)
223             focus = this;
224
225         //should this one be the same?
226         SkEvent evt(SK_EventType_KeyUp);
227         evt.setFast32(key);
228         if (focus->doEvent(evt))
229             return true;
230     }
231     return false;
232 }
233
234 void SkWindow::addMenu(SkOSMenu* menu) {
235     *fMenus.append() = menu;
236     this->onAddMenu(menu);
237 }
238
239 void SkWindow::setTitle(const char title[]) {
240     if (NULL == title) {
241         title = "";
242     }
243     fTitle.set(title);
244     this->onSetTitle(title);
245 }
246
247 bool SkWindow::onEvent(const SkEvent& evt) {
248     if (evt.isType(SK_EventDelayInval)) {
249         for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
250             this->onHandleInval(iter.rect());
251         fWaitingOnInval = false;
252         return true;
253     }
254     return this->INHERITED::onEvent(evt);
255 }
256
257 bool SkWindow::onGetFocusView(SkView** focus) const {
258     if (focus)
259         *focus = fFocusView;
260     return true;
261 }
262
263 bool SkWindow::onSetFocusView(SkView* focus) {
264     if (fFocusView != focus) {
265         if (fFocusView)
266             fFocusView->onFocusChange(false);
267         fFocusView = focus;
268         if (focus)
269             focus->onFocusChange(true);
270     }
271     return true;
272 }
273
274 void SkWindow::onHandleInval(const SkIRect&) {
275 }
276
277 bool SkWindow::onHandleChar(SkUnichar) {
278     return false;
279 }
280
281 bool SkWindow::onHandleKey(SkKey) {
282     return false;
283 }
284
285 bool SkWindow::onHandleKeyUp(SkKey) {
286     return false;
287 }
288
289 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
290                            unsigned modifierKeys) {
291     return this->onDispatchClick(x, y, state, owner, modifierKeys);
292 }
293
294 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
295                                void* owner, unsigned modifierKeys) {
296     bool handled = false;
297
298     // First, attempt to find an existing click with this owner.
299     int index = -1;
300     for (int i = 0; i < fClicks.count(); i++) {
301         if (owner == fClicks[i]->fOwner) {
302             index = i;
303             break;
304         }
305     }
306
307     switch (state) {
308         case Click::kDown_State: {
309             if (index != -1) {
310                 delete fClicks[index];
311                 fClicks.remove(index);
312             }
313             Click* click = this->findClickHandler(SkIntToScalar(x),
314                                                   SkIntToScalar(y), modifierKeys);
315
316             if (click) {
317                 click->fOwner = owner;
318                 *fClicks.append() = click;
319                 SkView::DoClickDown(click, x, y, modifierKeys);
320                 handled = true;
321             }
322             break;
323         }
324         case Click::kMoved_State:
325             if (index != -1) {
326                 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
327                 handled = true;
328             }
329             break;
330         case Click::kUp_State:
331             if (index != -1) {
332                 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
333                 delete fClicks[index];
334                 fClicks.remove(index);
335                 handled = true;
336             }
337             break;
338         default:
339             // Do nothing
340             break;
341     }
342     return handled;
343 }