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