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