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