blob: 14672e2c71bd95500dba6e2fc3835e7959796a0d [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() {
138 fDirtyRgn.setRect(0, 0, this->width(), this->height());
139}
140
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
142 #include <windows.h>
143 #include <gx.h>
144 extern GXDisplayProperties gDisplayProps;
145#endif
146
147#ifdef SK_SIMULATE_FAILED_MALLOC
148extern bool gEnableControlledThrow;
149#endif
150
reed@android.comf2b98d62010-12-20 18:26:13 +0000151bool SkWindow::update(SkIRect* updateArea, SkCanvas* canvas)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152{
153 if (!fDirtyRgn.isEmpty())
154 {
155 SkBitmap bm = this->getBitmap();
156
157#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
158 char* buffer = (char*)GXBeginDraw();
159 SkASSERT(buffer);
160
161 RECT rect;
162 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
163 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
164
165 bm.setPixels(buffer);
166#endif
167
reed@android.comf2b98d62010-12-20 18:26:13 +0000168 SkCanvas rasterCanvas;
169 SkDevice* device;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170
reed@android.comf2b98d62010-12-20 18:26:13 +0000171 if (NULL == canvas) {
172 canvas = &rasterCanvas;
173 device = new SkDevice(canvas, bm, false);
174 canvas->setDevice(device)->unref();
175 } else {
176 canvas->setBitmapDevice(bm);
177 }
178
179 canvas->clipRegion(fDirtyRgn);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180 if (updateArea)
181 *updateArea = fDirtyRgn.getBounds();
182
reed@android.comf2b98d62010-12-20 18:26:13 +0000183 SkAutoCanvasRestore acr(canvas, true);
184 canvas->concat(fMatrix);
185
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 // empty this now, so we can correctly record any inval calls that
187 // might be made during the draw call.
188 fDirtyRgn.setEmpty();
189
190#ifdef TEST_BOUNDER
191 test_bounder b(bm);
reed@android.comf2b98d62010-12-20 18:26:13 +0000192 canvas->setBounder(&b);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000193#endif
194#ifdef SK_SIMULATE_FAILED_MALLOC
195 gEnableControlledThrow = true;
196#endif
197#ifdef SK_BUILD_FOR_WIN32
reed@android.comf2b98d62010-12-20 18:26:13 +0000198 //try {
199 this->draw(canvas);
200 //}
201 //catch (...) {
202 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203#else
reed@android.comf2b98d62010-12-20 18:26:13 +0000204 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205#endif
206#ifdef SK_SIMULATE_FAILED_MALLOC
207 gEnableControlledThrow = false;
208#endif
209#ifdef TEST_BOUNDER
reed@android.comf2b98d62010-12-20 18:26:13 +0000210 canvas->setBounder(NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211#endif
212
213#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
214 GXEndDraw();
215#endif
216
217 return true;
218 }
219 return false;
220}
221
222bool SkWindow::handleChar(SkUnichar uni)
223{
224 if (this->onHandleChar(uni))
225 return true;
226
227 SkView* focus = this->getFocusView();
228 if (focus == NULL)
229 focus = this;
230
231 SkEvent evt(SK_EventType_Unichar);
232 evt.setFast32(uni);
233 return focus->doEvent(evt);
234}
235
236bool SkWindow::handleKey(SkKey key)
237{
238 if (key == kNONE_SkKey)
239 return false;
240
241 if (this->onHandleKey(key))
242 return true;
243
244 // send an event to the focus-view
245 {
246 SkView* focus = this->getFocusView();
247 if (focus == NULL)
248 focus = this;
249
250 SkEvent evt(SK_EventType_Key);
251 evt.setFast32(key);
252 if (focus->doEvent(evt))
253 return true;
254 }
255
256 if (key == kUp_SkKey || key == kDown_SkKey)
257 {
258 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
259 this->onSetFocusView(NULL);
260 return true;
261 }
262 return false;
263}
264
265bool SkWindow::handleKeyUp(SkKey key)
266{
267 if (key == kNONE_SkKey)
268 return false;
269
270 if (this->onHandleKeyUp(key))
271 return true;
272
273 //send an event to the focus-view
274 {
275 SkView* focus = this->getFocusView();
276 if (focus == NULL)
277 focus = this;
278
279 //should this one be the same?
280 SkEvent evt(SK_EventType_KeyUp);
281 evt.setFast32(key);
282 if (focus->doEvent(evt))
283 return true;
284 }
285 return false;
286}
287
288void SkWindow::addMenu(SkOSMenu* menu)
289{
290 *fMenus.append() = menu;
291 this->onAddMenu(menu);
292}
293
reed@android.com0ae6b242008-12-23 16:49:54 +0000294void SkWindow::setTitle(const char title[]) {
295 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000297 }
298 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299 this->onSetTitle(title);
300}
301
302bool SkWindow::handleMenu(uint32_t cmd)
303{
304 for (int i = 0; i < fMenus.count(); i++)
305 {
306 SkEvent* evt = fMenus[i]->createEvent(cmd);
307 if (evt)
308 {
309 evt->post(this->getSinkID());
310 return true;
311 }
312 }
313 return false;
314}
315
316//////////////////////////////////////////////////////////////////////
317
318bool SkWindow::onEvent(const SkEvent& evt)
319{
320 if (evt.isType(SK_EventDelayInval))
321 {
322 SkRegion::Iterator iter(fDirtyRgn);
323
324 for (; !iter.done(); iter.next())
325 this->onHandleInval(iter.rect());
326 fWaitingOnInval = false;
327 return true;
328 }
329 return this->INHERITED::onEvent(evt);
330}
331
332bool SkWindow::onGetFocusView(SkView** focus) const
333{
334 if (focus)
335 *focus = fFocusView;
336 return true;
337}
338
339bool SkWindow::onSetFocusView(SkView* focus)
340{
341 if (fFocusView != focus)
342 {
343 if (fFocusView)
344 fFocusView->onFocusChange(false);
345 fFocusView = focus;
346 if (focus)
347 focus->onFocusChange(true);
348 }
349 return true;
350}
351
352//////////////////////////////////////////////////////////////////////
353
354void SkWindow::onHandleInval(const SkIRect&)
355{
356}
357
358bool SkWindow::onHandleChar(SkUnichar)
359{
360 return false;
361}
362
363bool SkWindow::onHandleKey(SkKey key)
364{
365 return false;
366}
367
368bool SkWindow::onHandleKeyUp(SkKey key)
369{
370 return false;
371}
372
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000373bool SkWindow::handleClick(int x, int y, Click::State state) {
374 return this->onDispatchClick(x, y, state);
375}
376
377bool SkWindow::onDispatchClick(int x, int y, Click::State state) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000378 bool handled = false;
379
380 switch (state) {
381 case Click::kDown_State:
382 if (fClick)
383 delete fClick;
384 fClick = this->findClickHandler(SkIntToScalar(x), SkIntToScalar(y));
385 if (fClick)
386 {
387 SkView::DoClickDown(fClick, x, y);
388 handled = true;
389 }
390 break;
391 case Click::kMoved_State:
392 if (fClick)
393 {
394 SkView::DoClickMoved(fClick, x, y);
395 handled = true;
396 }
397 break;
398 case Click::kUp_State:
399 if (fClick)
400 {
401 SkView::DoClickUp(fClick, x, y);
402 delete fClick;
403 fClick = NULL;
404 handled = true;
405 }
406 break;
407 }
408 return handled;
409}
410