1
2 /*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8 #include "SkWindow.h"
9 #include "SkCanvas.h"
10 #include "SkDevice.h"
11 #include "SkOSMenu.h"
12 #include "SkSystemEventTypes.h"
13 #include "SkTime.h"
14
15 #define SK_EventDelayInval "\xd" "n" "\xa" "l"
16
SkWindow()17 SkWindow::SkWindow() : fFocusView(NULL) {
18 fClicks.reset();
19 fWaitingOnInval = false;
20
21 #ifdef SK_BUILD_FOR_WINCE
22 fColorType = kRGB_565_SkColorType;
23 #else
24 fColorType = kN32_SkColorType;
25 #endif
26
27 fMatrix.reset();
28 }
29
~SkWindow()30 SkWindow::~SkWindow() {
31 fClicks.deleteAll();
32 fMenus.deleteAll();
33 }
34
createCanvas()35 SkCanvas* SkWindow::createCanvas() {
36 return new SkCanvas(this->getBitmap());
37 }
38
setMatrix(const SkMatrix & matrix)39 void SkWindow::setMatrix(const SkMatrix& matrix) {
40 if (fMatrix != matrix) {
41 fMatrix = matrix;
42 this->inval(NULL);
43 }
44 }
45
preConcat(const SkMatrix & matrix)46 void SkWindow::preConcat(const SkMatrix& matrix) {
47 SkMatrix m;
48 m.setConcat(fMatrix, matrix);
49 this->setMatrix(m);
50 }
51
postConcat(const SkMatrix & matrix)52 void SkWindow::postConcat(const SkMatrix& matrix) {
53 SkMatrix m;
54 m.setConcat(matrix, fMatrix);
55 this->setMatrix(m);
56 }
57
setColorType(SkColorType ct)58 void SkWindow::setColorType(SkColorType ct) {
59 this->resize(fBitmap.width(), fBitmap.height(), ct);
60 }
61
resize(int width,int height,SkColorType ct)62 void SkWindow::resize(int width, int height, SkColorType ct) {
63 if (ct == kUnknown_SkColorType)
64 ct = fColorType;
65
66 if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
67 fColorType = ct;
68 fBitmap.allocPixels(SkImageInfo::Make(width, height,
69 ct, kPremul_SkAlphaType));
70
71 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
72 this->inval(NULL);
73 }
74 }
75
handleInval(const SkRect * localR)76 bool SkWindow::handleInval(const SkRect* localR) {
77 SkIRect ir;
78
79 if (localR) {
80 SkRect devR;
81 SkMatrix inverse;
82 if (!fMatrix.invert(&inverse)) {
83 return false;
84 }
85 fMatrix.mapRect(&devR, *localR);
86 devR.round(&ir);
87 } else {
88 ir.set(0, 0,
89 SkScalarRoundToInt(this->width()),
90 SkScalarRoundToInt(this->height()));
91 }
92 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
93
94 this->onHandleInval(ir);
95 return true;
96 }
97
forceInvalAll()98 void SkWindow::forceInvalAll() {
99 fDirtyRgn.setRect(0, 0,
100 SkScalarCeilToInt(this->width()),
101 SkScalarCeilToInt(this->height()));
102 }
103
104 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
105 #include <windows.h>
106 #include <gx.h>
107 extern GXDisplayProperties gDisplayProps;
108 #endif
109
110 #ifdef SK_SIMULATE_FAILED_MALLOC
111 extern bool gEnableControlledThrow;
112 #endif
113
update(SkIRect * updateArea)114 bool SkWindow::update(SkIRect* updateArea) {
115 if (!fDirtyRgn.isEmpty()) {
116 SkBitmap bm = this->getBitmap();
117
118 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
119 char* buffer = (char*)GXBeginDraw();
120 SkASSERT(buffer);
121
122 RECT rect;
123 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
124 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
125
126 bm.setPixels(buffer);
127 #endif
128
129 SkAutoTUnref<SkCanvas> canvas(this->createCanvas());
130
131 canvas->clipRegion(fDirtyRgn);
132 if (updateArea)
133 *updateArea = fDirtyRgn.getBounds();
134
135 SkAutoCanvasRestore acr(canvas, true);
136 canvas->concat(fMatrix);
137
138 // empty this now, so we can correctly record any inval calls that
139 // might be made during the draw call.
140 fDirtyRgn.setEmpty();
141
142 #ifdef SK_SIMULATE_FAILED_MALLOC
143 gEnableControlledThrow = true;
144 #endif
145 #ifdef SK_BUILD_FOR_WIN32
146 //try {
147 this->draw(canvas);
148 //}
149 //catch (...) {
150 //}
151 #else
152 this->draw(canvas);
153 #endif
154 #ifdef SK_SIMULATE_FAILED_MALLOC
155 gEnableControlledThrow = false;
156 #endif
157
158 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
159 GXEndDraw();
160 #endif
161
162 return true;
163 }
164 return false;
165 }
166
handleChar(SkUnichar uni)167 bool SkWindow::handleChar(SkUnichar uni) {
168 if (this->onHandleChar(uni))
169 return true;
170
171 SkView* focus = this->getFocusView();
172 if (focus == NULL)
173 focus = this;
174
175 SkEvent evt(SK_EventType_Unichar);
176 evt.setFast32(uni);
177 return focus->doEvent(evt);
178 }
179
handleKey(SkKey key)180 bool SkWindow::handleKey(SkKey key) {
181 if (key == kNONE_SkKey)
182 return false;
183
184 if (this->onHandleKey(key))
185 return true;
186
187 // send an event to the focus-view
188 {
189 SkView* focus = this->getFocusView();
190 if (focus == NULL)
191 focus = this;
192
193 SkEvent evt(SK_EventType_Key);
194 evt.setFast32(key);
195 if (focus->doEvent(evt))
196 return true;
197 }
198
199 if (key == kUp_SkKey || key == kDown_SkKey) {
200 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
201 this->onSetFocusView(NULL);
202 return true;
203 }
204 return false;
205 }
206
handleKeyUp(SkKey key)207 bool SkWindow::handleKeyUp(SkKey key) {
208 if (key == kNONE_SkKey)
209 return false;
210
211 if (this->onHandleKeyUp(key))
212 return true;
213
214 //send an event to the focus-view
215 {
216 SkView* focus = this->getFocusView();
217 if (focus == NULL)
218 focus = this;
219
220 //should this one be the same?
221 SkEvent evt(SK_EventType_KeyUp);
222 evt.setFast32(key);
223 if (focus->doEvent(evt))
224 return true;
225 }
226 return false;
227 }
228
addMenu(SkOSMenu * menu)229 void SkWindow::addMenu(SkOSMenu* menu) {
230 *fMenus.append() = menu;
231 this->onAddMenu(menu);
232 }
233
setTitle(const char title[])234 void SkWindow::setTitle(const char title[]) {
235 if (NULL == title) {
236 title = "";
237 }
238 fTitle.set(title);
239 this->onSetTitle(title);
240 }
241
onEvent(const SkEvent & evt)242 bool SkWindow::onEvent(const SkEvent& evt) {
243 if (evt.isType(SK_EventDelayInval)) {
244 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
245 this->onHandleInval(iter.rect());
246 fWaitingOnInval = false;
247 return true;
248 }
249 return this->INHERITED::onEvent(evt);
250 }
251
onGetFocusView(SkView ** focus) const252 bool SkWindow::onGetFocusView(SkView** focus) const {
253 if (focus)
254 *focus = fFocusView;
255 return true;
256 }
257
onSetFocusView(SkView * focus)258 bool SkWindow::onSetFocusView(SkView* focus) {
259 if (fFocusView != focus) {
260 if (fFocusView)
261 fFocusView->onFocusChange(false);
262 fFocusView = focus;
263 if (focus)
264 focus->onFocusChange(true);
265 }
266 return true;
267 }
268
onHandleInval(const SkIRect &)269 void SkWindow::onHandleInval(const SkIRect&) {
270 }
271
onHandleChar(SkUnichar)272 bool SkWindow::onHandleChar(SkUnichar) {
273 return false;
274 }
275
onHandleKey(SkKey)276 bool SkWindow::onHandleKey(SkKey) {
277 return false;
278 }
279
onHandleKeyUp(SkKey)280 bool SkWindow::onHandleKeyUp(SkKey) {
281 return false;
282 }
283
handleClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)284 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
285 unsigned modifierKeys) {
286 return this->onDispatchClick(x, y, state, owner, modifierKeys);
287 }
288
onDispatchClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)289 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
290 void* owner, unsigned modifierKeys) {
291 bool handled = false;
292
293 // First, attempt to find an existing click with this owner.
294 int index = -1;
295 for (int i = 0; i < fClicks.count(); i++) {
296 if (owner == fClicks[i]->fOwner) {
297 index = i;
298 break;
299 }
300 }
301
302 switch (state) {
303 case Click::kDown_State: {
304 if (index != -1) {
305 delete fClicks[index];
306 fClicks.remove(index);
307 }
308 Click* click = this->findClickHandler(SkIntToScalar(x),
309 SkIntToScalar(y), modifierKeys);
310
311 if (click) {
312 click->fOwner = owner;
313 *fClicks.append() = click;
314 SkView::DoClickDown(click, x, y, modifierKeys);
315 handled = true;
316 }
317 break;
318 }
319 case Click::kMoved_State:
320 if (index != -1) {
321 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
322 handled = true;
323 }
324 break;
325 case Click::kUp_State:
326 if (index != -1) {
327 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
328 delete fClicks[index];
329 fClicks.remove(index);
330 handled = true;
331 }
332 break;
333 default:
334 // Do nothing
335 break;
336 }
337 return handled;
338 }
339