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 #define TEST_BOUNDERx
18
19 #include "SkBounder.h"
20 class test_bounder : public SkBounder {
21 public:
test_bounder(const SkBitmap & bm)22 test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
23 protected:
onIRect(const SkIRect & r)24 virtual bool onIRect(const SkIRect& r)
25 {
26 SkRect rr;
27
28 rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
29 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));
30
31 SkPaint p;
32
33 p.setStyle(SkPaint::kStroke_Style);
34 p.setColor(SK_ColorYELLOW);
35
36 #if 0
37 rr.inset(SK_ScalarHalf, SK_ScalarHalf);
38 #else
39 rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
40 #endif
41
42 fCanvas.drawRect(rr, p);
43 return true;
44 }
45 private:
46 SkCanvas fCanvas;
47 };
48
SkWindow()49 SkWindow::SkWindow() : fFocusView(NULL)
50 {
51 fClicks.reset();
52 fWaitingOnInval = false;
53
54 #ifdef SK_BUILD_FOR_WINCE
55 fConfig = SkBitmap::kRGB_565_Config;
56 #else
57 fConfig = SkBitmap::kARGB_8888_Config;
58 #endif
59
60 fMatrix.reset();
61 }
62
~SkWindow()63 SkWindow::~SkWindow()
64 {
65 fClicks.deleteAll();
66 fMenus.deleteAll();
67 }
68
createCanvas()69 SkCanvas* SkWindow::createCanvas() {
70 return new SkCanvas(this->getBitmap());
71 }
72
setMatrix(const SkMatrix & matrix)73 void SkWindow::setMatrix(const SkMatrix& matrix) {
74 if (fMatrix != matrix) {
75 fMatrix = matrix;
76 this->inval(NULL);
77 }
78 }
79
preConcat(const SkMatrix & matrix)80 void SkWindow::preConcat(const SkMatrix& matrix) {
81 SkMatrix m;
82 m.setConcat(fMatrix, matrix);
83 this->setMatrix(m);
84 }
85
postConcat(const SkMatrix & matrix)86 void SkWindow::postConcat(const SkMatrix& matrix) {
87 SkMatrix m;
88 m.setConcat(matrix, fMatrix);
89 this->setMatrix(m);
90 }
91
setConfig(SkBitmap::Config config)92 void SkWindow::setConfig(SkBitmap::Config config)
93 {
94 this->resize(fBitmap.width(), fBitmap.height(), config);
95 }
96
resize(int width,int height,SkBitmap::Config config)97 void SkWindow::resize(int width, int height, SkBitmap::Config config)
98 {
99 if (config == SkBitmap::kNo_Config)
100 config = fConfig;
101
102 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
103 {
104 fConfig = config;
105 fBitmap.setConfig(config, width, height, 0, kOpaque_SkAlphaType);
106 fBitmap.allocPixels();
107
108 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
109 this->inval(NULL);
110 }
111 }
112
eraseARGB(U8CPU a,U8CPU r,U8CPU g,U8CPU b)113 void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
114 {
115 fBitmap.eraseARGB(a, r, g, b);
116 }
117
eraseRGB(U8CPU r,U8CPU g,U8CPU b)118 void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
119 {
120 fBitmap.eraseARGB(0xFF, r, g, b);
121 }
122
handleInval(const SkRect * localR)123 bool SkWindow::handleInval(const SkRect* localR)
124 {
125 SkIRect ir;
126
127 if (localR) {
128 SkRect devR;
129 SkMatrix inverse;
130 if (!fMatrix.invert(&inverse)) {
131 return false;
132 }
133 fMatrix.mapRect(&devR, *localR);
134 devR.round(&ir);
135 } else {
136 ir.set(0, 0,
137 SkScalarRound(this->width()),
138 SkScalarRound(this->height()));
139 }
140 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
141
142 this->onHandleInval(ir);
143 return true;
144 }
145
forceInvalAll()146 void SkWindow::forceInvalAll() {
147 fDirtyRgn.setRect(0, 0,
148 SkScalarCeil(this->width()),
149 SkScalarCeil(this->height()));
150 }
151
152 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
153 #include <windows.h>
154 #include <gx.h>
155 extern GXDisplayProperties gDisplayProps;
156 #endif
157
158 #ifdef SK_SIMULATE_FAILED_MALLOC
159 extern bool gEnableControlledThrow;
160 #endif
161
update(SkIRect * updateArea)162 bool SkWindow::update(SkIRect* updateArea)
163 {
164 if (!fDirtyRgn.isEmpty())
165 {
166 SkBitmap bm = this->getBitmap();
167
168 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
169 char* buffer = (char*)GXBeginDraw();
170 SkASSERT(buffer);
171
172 RECT rect;
173 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
174 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
175
176 bm.setPixels(buffer);
177 #endif
178
179 SkAutoTUnref<SkCanvas> canvas(this->createCanvas());
180
181 canvas->clipRegion(fDirtyRgn);
182 if (updateArea)
183 *updateArea = fDirtyRgn.getBounds();
184
185 SkAutoCanvasRestore acr(canvas, true);
186 canvas->concat(fMatrix);
187
188 // empty this now, so we can correctly record any inval calls that
189 // might be made during the draw call.
190 fDirtyRgn.setEmpty();
191
192 #ifdef TEST_BOUNDER
193 test_bounder b(bm);
194 canvas->setBounder(&b);
195 #endif
196 #ifdef SK_SIMULATE_FAILED_MALLOC
197 gEnableControlledThrow = true;
198 #endif
199 #ifdef SK_BUILD_FOR_WIN32
200 //try {
201 this->draw(canvas);
202 //}
203 //catch (...) {
204 //}
205 #else
206 this->draw(canvas);
207 #endif
208 #ifdef SK_SIMULATE_FAILED_MALLOC
209 gEnableControlledThrow = false;
210 #endif
211 #ifdef TEST_BOUNDER
212 canvas->setBounder(NULL);
213 #endif
214
215 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
216 GXEndDraw();
217 #endif
218
219 return true;
220 }
221 return false;
222 }
223
handleChar(SkUnichar uni)224 bool SkWindow::handleChar(SkUnichar uni)
225 {
226 if (this->onHandleChar(uni))
227 return true;
228
229 SkView* focus = this->getFocusView();
230 if (focus == NULL)
231 focus = this;
232
233 SkEvent evt(SK_EventType_Unichar);
234 evt.setFast32(uni);
235 return focus->doEvent(evt);
236 }
237
handleKey(SkKey key)238 bool SkWindow::handleKey(SkKey key)
239 {
240 if (key == kNONE_SkKey)
241 return false;
242
243 if (this->onHandleKey(key))
244 return true;
245
246 // send an event to the focus-view
247 {
248 SkView* focus = this->getFocusView();
249 if (focus == NULL)
250 focus = this;
251
252 SkEvent evt(SK_EventType_Key);
253 evt.setFast32(key);
254 if (focus->doEvent(evt))
255 return true;
256 }
257
258 if (key == kUp_SkKey || key == kDown_SkKey)
259 {
260 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
261 this->onSetFocusView(NULL);
262 return true;
263 }
264 return false;
265 }
266
handleKeyUp(SkKey key)267 bool SkWindow::handleKeyUp(SkKey key)
268 {
269 if (key == kNONE_SkKey)
270 return false;
271
272 if (this->onHandleKeyUp(key))
273 return true;
274
275 //send an event to the focus-view
276 {
277 SkView* focus = this->getFocusView();
278 if (focus == NULL)
279 focus = this;
280
281 //should this one be the same?
282 SkEvent evt(SK_EventType_KeyUp);
283 evt.setFast32(key);
284 if (focus->doEvent(evt))
285 return true;
286 }
287 return false;
288 }
289
addMenu(SkOSMenu * menu)290 void SkWindow::addMenu(SkOSMenu* menu) {
291 *fMenus.append() = menu;
292 this->onAddMenu(menu);
293 }
294
setTitle(const char title[])295 void SkWindow::setTitle(const char title[]) {
296 if (NULL == title) {
297 title = "";
298 }
299 fTitle.set(title);
300 this->onSetTitle(title);
301 }
302
303 //////////////////////////////////////////////////////////////////////
304
onEvent(const SkEvent & evt)305 bool SkWindow::onEvent(const SkEvent& evt)
306 {
307 if (evt.isType(SK_EventDelayInval))
308 {
309 SkRegion::Iterator iter(fDirtyRgn);
310
311 for (; !iter.done(); iter.next())
312 this->onHandleInval(iter.rect());
313 fWaitingOnInval = false;
314 return true;
315 }
316 return this->INHERITED::onEvent(evt);
317 }
318
onGetFocusView(SkView ** focus) const319 bool SkWindow::onGetFocusView(SkView** focus) const
320 {
321 if (focus)
322 *focus = fFocusView;
323 return true;
324 }
325
onSetFocusView(SkView * focus)326 bool SkWindow::onSetFocusView(SkView* focus)
327 {
328 if (fFocusView != focus)
329 {
330 if (fFocusView)
331 fFocusView->onFocusChange(false);
332 fFocusView = focus;
333 if (focus)
334 focus->onFocusChange(true);
335 }
336 return true;
337 }
338
339 //////////////////////////////////////////////////////////////////////
340
onHandleInval(const SkIRect &)341 void SkWindow::onHandleInval(const SkIRect&)
342 {
343 }
344
onHandleChar(SkUnichar)345 bool SkWindow::onHandleChar(SkUnichar)
346 {
347 return false;
348 }
349
onHandleKey(SkKey)350 bool SkWindow::onHandleKey(SkKey)
351 {
352 return false;
353 }
354
onHandleKeyUp(SkKey)355 bool SkWindow::onHandleKeyUp(SkKey)
356 {
357 return false;
358 }
359
handleClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)360 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
361 unsigned modifierKeys) {
362 return this->onDispatchClick(x, y, state, owner, modifierKeys);
363 }
364
onDispatchClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)365 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
366 void* owner, unsigned modifierKeys) {
367 bool handled = false;
368
369 // First, attempt to find an existing click with this owner.
370 int index = -1;
371 for (int i = 0; i < fClicks.count(); i++) {
372 if (owner == fClicks[i]->fOwner) {
373 index = i;
374 break;
375 }
376 }
377
378 switch (state) {
379 case Click::kDown_State: {
380 if (index != -1) {
381 delete fClicks[index];
382 fClicks.remove(index);
383 }
384 Click* click = this->findClickHandler(SkIntToScalar(x),
385 SkIntToScalar(y), modifierKeys);
386
387 if (click) {
388 click->fOwner = owner;
389 *fClicks.append() = click;
390 SkView::DoClickDown(click, x, y, modifierKeys);
391 handled = true;
392 }
393 break;
394 }
395 case Click::kMoved_State:
396 if (index != -1) {
397 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
398 handled = true;
399 }
400 break;
401 case Click::kUp_State:
402 if (index != -1) {
403 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
404 delete fClicks[index];
405 fClicks.remove(index);
406 handled = true;
407 }
408 break;
409 default:
410 // Do nothing
411 break;
412 }
413 return handled;
414 }
415