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