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