blob: c8403d46ae0347f827a53a55c69049a98ae51c88 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001#include "SkWindow.h"
2#include "SkCanvas.h"
3#include "SkOSMenu.h"
4#include "SkSystemEventTypes.h"
5#include "SkTime.h"
6
7#define SK_EventDelayInval "\xd" "n" "\xa" "l"
8
9#define TEST_BOUNDERx
10
11#include "SkBounder.h"
12class test_bounder : public SkBounder {
13public:
14 test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
15protected:
16 virtual bool onIRect(const SkIRect& r)
17 {
18 SkRect rr;
19
20 rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
21 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));
22
23 SkPaint p;
24
25 p.setStyle(SkPaint::kStroke_Style);
26 p.setColor(SK_ColorYELLOW);
27
28#if 0
29 rr.inset(SK_ScalarHalf, SK_ScalarHalf);
30#else
31 rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
32#endif
33
34 fCanvas.drawRect(rr, p);
35 return true;
36 }
37private:
38 SkCanvas fCanvas;
39};
40
41SkWindow::SkWindow() : fFocusView(NULL)
42{
43 fClick = NULL;
44 fWaitingOnInval = false;
45
46#ifdef SK_BUILD_FOR_WINCE
47 fConfig = SkBitmap::kRGB_565_Config;
48#else
49 fConfig = SkBitmap::kARGB_8888_Config;
50#endif
51}
52
53SkWindow::~SkWindow()
54{
55 delete fClick;
56
57 fMenus.deleteAll();
58}
59
60void SkWindow::setConfig(SkBitmap::Config config)
61{
62 this->resize(fBitmap.width(), fBitmap.height(), config);
63}
64
reed@android.com8a1c16f2008-12-17 15:59:43 +000065void SkWindow::resize(int width, int height, SkBitmap::Config config)
66{
67 if (config == SkBitmap::kNo_Config)
68 config = fConfig;
69
70 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
71 {
72 fConfig = config;
73 fBitmap.setConfig(config, width, height);
74 fBitmap.allocPixels();
75
76 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
77 this->inval(NULL);
78 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000079}
80
81void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
82{
83 fBitmap.eraseARGB(a, r, g, b);
84}
85
86void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
87{
88 fBitmap.eraseRGB(r, g, b);
89}
90
91bool SkWindow::handleInval(const SkRect& r)
92{
93 SkIRect ir;
94
95 r.round(&ir);
96 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
97
98#ifdef SK_BUILD_FOR_WIN32
99 if (!fWaitingOnInval)
100 {
101 fWaitingOnInval = true;
102 (new SkEvent(SK_EventDelayInval))->post(this->getSinkID(), 10);
103 }
104#else
105 this->onHandleInval(ir);
106#endif
107 return true;
108}
109
110#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
111 #include <windows.h>
112 #include <gx.h>
113 extern GXDisplayProperties gDisplayProps;
114#endif
115
116#ifdef SK_SIMULATE_FAILED_MALLOC
117extern bool gEnableControlledThrow;
118#endif
119
120bool SkWindow::update(SkIRect* updateArea)
121{
122 if (!fDirtyRgn.isEmpty())
123 {
124 SkBitmap bm = this->getBitmap();
125
126#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
127 char* buffer = (char*)GXBeginDraw();
128 SkASSERT(buffer);
129
130 RECT rect;
131 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
132 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
133
134 bm.setPixels(buffer);
135#endif
136
137 SkCanvas canvas(bm);
138
139 canvas.clipRegion(fDirtyRgn);
140 if (updateArea)
141 *updateArea = fDirtyRgn.getBounds();
142
143 // empty this now, so we can correctly record any inval calls that
144 // might be made during the draw call.
145 fDirtyRgn.setEmpty();
146
147#ifdef TEST_BOUNDER
148 test_bounder b(bm);
149 canvas.setBounder(&b);
150#endif
151#ifdef SK_SIMULATE_FAILED_MALLOC
152 gEnableControlledThrow = true;
153#endif
154#ifdef SK_BUILD_FOR_WIN32
155 try {
156 this->draw(&canvas);
157 }
158 catch (...) {
159 }
160#else
161 this->draw(&canvas);
162#endif
163#ifdef SK_SIMULATE_FAILED_MALLOC
164 gEnableControlledThrow = false;
165#endif
166#ifdef TEST_BOUNDER
167 canvas.setBounder(NULL);
168#endif
169
170#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
171 GXEndDraw();
172#endif
173
174 return true;
175 }
176 return false;
177}
178
179bool SkWindow::handleChar(SkUnichar uni)
180{
181 if (this->onHandleChar(uni))
182 return true;
183
184 SkView* focus = this->getFocusView();
185 if (focus == NULL)
186 focus = this;
187
188 SkEvent evt(SK_EventType_Unichar);
189 evt.setFast32(uni);
190 return focus->doEvent(evt);
191}
192
193bool SkWindow::handleKey(SkKey key)
194{
195 if (key == kNONE_SkKey)
196 return false;
197
198 if (this->onHandleKey(key))
199 return true;
200
201 // send an event to the focus-view
202 {
203 SkView* focus = this->getFocusView();
204 if (focus == NULL)
205 focus = this;
206
207 SkEvent evt(SK_EventType_Key);
208 evt.setFast32(key);
209 if (focus->doEvent(evt))
210 return true;
211 }
212
213 if (key == kUp_SkKey || key == kDown_SkKey)
214 {
215 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
216 this->onSetFocusView(NULL);
217 return true;
218 }
219 return false;
220}
221
222bool SkWindow::handleKeyUp(SkKey key)
223{
224 if (key == kNONE_SkKey)
225 return false;
226
227 if (this->onHandleKeyUp(key))
228 return true;
229
230 //send an event to the focus-view
231 {
232 SkView* focus = this->getFocusView();
233 if (focus == NULL)
234 focus = this;
235
236 //should this one be the same?
237 SkEvent evt(SK_EventType_KeyUp);
238 evt.setFast32(key);
239 if (focus->doEvent(evt))
240 return true;
241 }
242 return false;
243}
244
245void SkWindow::addMenu(SkOSMenu* menu)
246{
247 *fMenus.append() = menu;
248 this->onAddMenu(menu);
249}
250
reed@android.com0ae6b242008-12-23 16:49:54 +0000251void SkWindow::setTitle(const char title[]) {
252 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000253 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000254 }
255 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256 this->onSetTitle(title);
257}
258
259bool SkWindow::handleMenu(uint32_t cmd)
260{
261 for (int i = 0; i < fMenus.count(); i++)
262 {
263 SkEvent* evt = fMenus[i]->createEvent(cmd);
264 if (evt)
265 {
266 evt->post(this->getSinkID());
267 return true;
268 }
269 }
270 return false;
271}
272
273//////////////////////////////////////////////////////////////////////
274
275bool SkWindow::onEvent(const SkEvent& evt)
276{
277 if (evt.isType(SK_EventDelayInval))
278 {
279 SkRegion::Iterator iter(fDirtyRgn);
280
281 for (; !iter.done(); iter.next())
282 this->onHandleInval(iter.rect());
283 fWaitingOnInval = false;
284 return true;
285 }
286 return this->INHERITED::onEvent(evt);
287}
288
289bool SkWindow::onGetFocusView(SkView** focus) const
290{
291 if (focus)
292 *focus = fFocusView;
293 return true;
294}
295
296bool SkWindow::onSetFocusView(SkView* focus)
297{
298 if (fFocusView != focus)
299 {
300 if (fFocusView)
301 fFocusView->onFocusChange(false);
302 fFocusView = focus;
303 if (focus)
304 focus->onFocusChange(true);
305 }
306 return true;
307}
308
309//////////////////////////////////////////////////////////////////////
310
311void SkWindow::onHandleInval(const SkIRect&)
312{
313}
314
315bool SkWindow::onHandleChar(SkUnichar)
316{
317 return false;
318}
319
320bool SkWindow::onHandleKey(SkKey key)
321{
322 return false;
323}
324
325bool SkWindow::onHandleKeyUp(SkKey key)
326{
327 return false;
328}
329
330bool SkWindow::handleClick(int x, int y, Click::State state)
331{
332 bool handled = false;
333
334 switch (state) {
335 case Click::kDown_State:
336 if (fClick)
337 delete fClick;
338 fClick = this->findClickHandler(SkIntToScalar(x), SkIntToScalar(y));
339 if (fClick)
340 {
341 SkView::DoClickDown(fClick, x, y);
342 handled = true;
343 }
344 break;
345 case Click::kMoved_State:
346 if (fClick)
347 {
348 SkView::DoClickMoved(fClick, x, y);
349 handled = true;
350 }
351 break;
352 case Click::kUp_State:
353 if (fClick)
354 {
355 SkView::DoClickUp(fClick, x, y);
356 delete fClick;
357 fClick = NULL;
358 handled = true;
359 }
360 break;
361 }
362 return handled;
363}
364