blob: dc833ec0b174b9fb43154260c9b902da67407150 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkWindow.h"
2#include "SkCanvas.h"
reed@android.comf2b98d62010-12-20 18:26:13 +00003#include "SkDevice.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +00004#include "SkOSMenu.h"
5#include "SkSystemEventTypes.h"
6#include "SkTime.h"
7
8#define SK_EventDelayInval "\xd" "n" "\xa" "l"
9
10#define TEST_BOUNDERx
11
12#include "SkBounder.h"
13class test_bounder : public SkBounder {
14public:
15 test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
16protected:
17 virtual bool onIRect(const SkIRect& r)
18 {
19 SkRect rr;
20
21 rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
22 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));
23
24 SkPaint p;
25
26 p.setStyle(SkPaint::kStroke_Style);
27 p.setColor(SK_ColorYELLOW);
28
29#if 0
30 rr.inset(SK_ScalarHalf, SK_ScalarHalf);
31#else
32 rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
33#endif
34
35 fCanvas.drawRect(rr, p);
36 return true;
37 }
38private:
39 SkCanvas fCanvas;
40};
41
42SkWindow::SkWindow() : fFocusView(NULL)
43{
44 fClick = NULL;
45 fWaitingOnInval = false;
46
47#ifdef SK_BUILD_FOR_WINCE
48 fConfig = SkBitmap::kRGB_565_Config;
49#else
50 fConfig = SkBitmap::kARGB_8888_Config;
51#endif
reed@android.comf2b98d62010-12-20 18:26:13 +000052
53 fMatrix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +000054}
55
56SkWindow::~SkWindow()
57{
58 delete fClick;
59
60 fMenus.deleteAll();
61}
62
reed@android.comf2b98d62010-12-20 18:26:13 +000063void SkWindow::setMatrix(const SkMatrix& matrix) {
64 if (fMatrix != matrix) {
65 fMatrix = matrix;
66 this->inval(NULL);
67 }
68}
69
70void SkWindow::preConcat(const SkMatrix& matrix) {
71 SkMatrix m;
72 m.setConcat(fMatrix, matrix);
73 this->setMatrix(m);
74}
75
76void SkWindow::postConcat(const SkMatrix& matrix) {
77 SkMatrix m;
78 m.setConcat(matrix, fMatrix);
79 this->setMatrix(m);
80}
81
reed@android.com8a1c16f2008-12-17 15:59:43 +000082void SkWindow::setConfig(SkBitmap::Config config)
83{
84 this->resize(fBitmap.width(), fBitmap.height(), config);
85}
86
reed@android.com8a1c16f2008-12-17 15:59:43 +000087void SkWindow::resize(int width, int height, SkBitmap::Config config)
88{
89 if (config == SkBitmap::kNo_Config)
90 config = fConfig;
91
92 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
93 {
94 fConfig = config;
95 fBitmap.setConfig(config, width, height);
96 fBitmap.allocPixels();
reed@android.comf2b98d62010-12-20 18:26:13 +000097 fBitmap.setIsOpaque(true);
reed@android.com8a1c16f2008-12-17 15:59:43 +000098
99 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
100 this->inval(NULL);
101 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102}
103
104void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
105{
106 fBitmap.eraseARGB(a, r, g, b);
107}
108
109void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
110{
111 fBitmap.eraseRGB(r, g, b);
112}
113
reed@android.comf2b98d62010-12-20 18:26:13 +0000114bool SkWindow::handleInval(const SkRect* localR)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115{
116 SkIRect ir;
117
reed@android.comf2b98d62010-12-20 18:26:13 +0000118 if (localR) {
119 SkRect devR;
120 SkMatrix inverse;
121 if (!fMatrix.invert(&inverse)) {
122 return false;
123 }
124 fMatrix.mapRect(&devR, *localR);
125 devR.round(&ir);
126 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +0000127 ir.set(0, 0,
128 SkScalarRound(this->width()),
129 SkScalarRound(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000130 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
132
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 this->onHandleInval(ir);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134 return true;
135}
136
reed@android.comf2b98d62010-12-20 18:26:13 +0000137void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +0000138 fDirtyRgn.setRect(0, 0,
139 SkScalarCeil(this->width()),
140 SkScalarCeil(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000141}
142
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
144 #include <windows.h>
145 #include <gx.h>
146 extern GXDisplayProperties gDisplayProps;
147#endif
148
149#ifdef SK_SIMULATE_FAILED_MALLOC
150extern bool gEnableControlledThrow;
151#endif
152
reed@android.comf2b98d62010-12-20 18:26:13 +0000153bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000154{
155 if (!fDirtyRgn.isEmpty())
156 {
157 SkBitmap bm = this->getBitmap();
158
159#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
160 char* buffer = (char*)GXBeginDraw();
161 SkASSERT(buffer);
162
163 RECT rect;
164 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
165 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
166
167 bm.setPixels(buffer);
168#endif
169
reed@android.comf2b98d62010-12-20 18:26:13 +0000170 SkCanvas rasterCanvas;
171 SkDevice* device;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172
reed@android.comf2b98d62010-12-20 18:26:13 +0000173 if (NULL == canvas) {
174 canvas = &rasterCanvas;
reed@android.comf2b98d62010-12-20 18:26:13 +0000175 }
reed@google.comaf951c92011-06-16 19:10:39 +0000176 canvas->setBitmapDevice(bm);
reed@android.comf2b98d62010-12-20 18:26:13 +0000177
178 canvas->clipRegion(fDirtyRgn);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179 if (updateArea)
180 *updateArea = fDirtyRgn.getBounds();
181
reed@android.comf2b98d62010-12-20 18:26:13 +0000182 SkAutoCanvasRestore acr(canvas, true);
183 canvas->concat(fMatrix);
184
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185 // empty this now, so we can correctly record any inval calls that
186 // might be made during the draw call.
187 fDirtyRgn.setEmpty();
188
189#ifdef TEST_BOUNDER
190 test_bounder b(bm);
reed@android.comf2b98d62010-12-20 18:26:13 +0000191 canvas->setBounder(&b);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192#endif
193#ifdef SK_SIMULATE_FAILED_MALLOC
194 gEnableControlledThrow = true;
195#endif
196#ifdef SK_BUILD_FOR_WIN32
reed@android.comf2b98d62010-12-20 18:26:13 +0000197 //try {
198 this->draw(canvas);
199 //}
200 //catch (...) {
201 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000202#else
reed@android.comf2b98d62010-12-20 18:26:13 +0000203 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204#endif
205#ifdef SK_SIMULATE_FAILED_MALLOC
206 gEnableControlledThrow = false;
207#endif
208#ifdef TEST_BOUNDER
reed@android.comf2b98d62010-12-20 18:26:13 +0000209 canvas->setBounder(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210#endif
211
212#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
213 GXEndDraw();
214#endif
215
216 return true;
217 }
218 return false;
219}
220
221bool SkWindow::handleChar(SkUnichar uni)
222{
223 if (this->onHandleChar(uni))
224 return true;
225
226 SkView* focus = this->getFocusView();
227 if (focus == NULL)
228 focus = this;
229
230 SkEvent evt(SK_EventType_Unichar);
231 evt.setFast32(uni);
232 return focus->doEvent(evt);
233}
234
235bool SkWindow::handleKey(SkKey key)
236{
237 if (key == kNONE_SkKey)
238 return false;
239
240 if (this->onHandleKey(key))
241 return true;
242
243 // send an event to the focus-view
244 {
245 SkView* focus = this->getFocusView();
246 if (focus == NULL)
247 focus = this;
248
249 SkEvent evt(SK_EventType_Key);
250 evt.setFast32(key);
251 if (focus->doEvent(evt))
252 return true;
253 }
254
255 if (key == kUp_SkKey || key == kDown_SkKey)
256 {
257 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
258 this->onSetFocusView(NULL);
259 return true;
260 }
261 return false;
262}
263
264bool SkWindow::handleKeyUp(SkKey key)
265{
266 if (key == kNONE_SkKey)
267 return false;
268
269 if (this->onHandleKeyUp(key))
270 return true;
271
272 //send an event to the focus-view
273 {
274 SkView* focus = this->getFocusView();
275 if (focus == NULL)
276 focus = this;
277
278 //should this one be the same?
279 SkEvent evt(SK_EventType_KeyUp);
280 evt.setFast32(key);
281 if (focus->doEvent(evt))
282 return true;
283 }
284 return false;
285}
286
287void SkWindow::addMenu(SkOSMenu* menu)
288{
289 *fMenus.append() = menu;
290 this->onAddMenu(menu);
291}
292
reed@android.com0ae6b242008-12-23 16:49:54 +0000293void SkWindow::setTitle(const char title[]) {
294 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000296 }
297 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298 this->onSetTitle(title);
299}
300
301bool SkWindow::handleMenu(uint32_t cmd)
302{
303 for (int i = 0; i < fMenus.count(); i++)
304 {
305 SkEvent* evt = fMenus[i]->createEvent(cmd);
306 if (evt)
307 {
308 evt->post(this->getSinkID());
309 return true;
310 }
311 }
312 return false;
313}
314
315//////////////////////////////////////////////////////////////////////
316
317bool SkWindow::onEvent(const SkEvent& evt)
318{
319 if (evt.isType(SK_EventDelayInval))
320 {
321 SkRegion::Iterator iter(fDirtyRgn);
322
323 for (; !iter.done(); iter.next())
324 this->onHandleInval(iter.rect());
325 fWaitingOnInval = false;
326 return true;
327 }
328 return this->INHERITED::onEvent(evt);
329}
330
331bool SkWindow::onGetFocusView(SkView** focus) const
332{
333 if (focus)
334 *focus = fFocusView;
335 return true;
336}
337
338bool SkWindow::onSetFocusView(SkView* focus)
339{
340 if (fFocusView != focus)
341 {
342 if (fFocusView)
343 fFocusView->onFocusChange(false);
344 fFocusView = focus;
345 if (focus)
346 focus->onFocusChange(true);
347 }
348 return true;
349}
350
351//////////////////////////////////////////////////////////////////////
352
353void SkWindow::onHandleInval(const SkIRect&)
354{
355}
356
357bool SkWindow::onHandleChar(SkUnichar)
358{
359 return false;
360}
361
362bool SkWindow::onHandleKey(SkKey key)
363{
364 return false;
365}
366
367bool SkWindow::onHandleKeyUp(SkKey key)
368{
369 return false;
370}
371
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000372bool SkWindow::handleClick(int x, int y, Click::State state) {
373 return this->onDispatchClick(x, y, state);
374}
375
376bool SkWindow::onDispatchClick(int x, int y, Click::State state) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000377 bool handled = false;
378
379 switch (state) {
380 case Click::kDown_State:
381 if (fClick)
382 delete fClick;
383 fClick = this->findClickHandler(SkIntToScalar(x), SkIntToScalar(y));
384 if (fClick)
385 {
386 SkView::DoClickDown(fClick, x, y);
387 handled = true;
388 }
389 break;
390 case Click::kMoved_State:
391 if (fClick)
392 {
393 SkView::DoClickMoved(fClick, x, y);
394 handled = true;
395 }
396 break;
397 case Click::kUp_State:
398 if (fClick)
399 {
400 SkView::DoClickUp(fClick, x, y);
401 delete fClick;
402 fClick = NULL;
403 handled = true;
404 }
405 break;
406 }
407 return handled;
408}
409