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 17 #define TEST_BOUNDERx 18 19 #include "SkBounder.h" 20 class test_bounder : public SkBounder { 21 public: 22 test_bounder(const SkBitmap& bm) : fCanvas(bm) {} 23 protected: 24 virtual bool onIRect(const SkIRect& r) 25 { 26 SkRect rr; 27 28 rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop), 29 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom)); 30 31 SkPaint p; 32 33 p.setStyle(SkPaint::kStroke_Style); 34 p.setColor(SK_ColorYELLOW); 35 36 #if 0 37 rr.inset(SK_ScalarHalf, SK_ScalarHalf); 38 #else 39 rr.inset(-SK_ScalarHalf, -SK_ScalarHalf); 40 #endif 41 42 fCanvas.drawRect(rr, p); 43 return true; 44 } 45 private: 46 SkCanvas fCanvas; 47 }; 48 49 SkWindow::SkWindow() : fFocusView(NULL) 50 { 51 fClicks.reset(); 52 fWaitingOnInval = false; 53 54 #ifdef SK_BUILD_FOR_WINCE 55 fConfig = SkBitmap::kRGB_565_Config; 56 #else 57 fConfig = SkBitmap::kARGB_8888_Config; 58 #endif 59 60 fMatrix.reset(); 61 } 62 63 SkWindow::~SkWindow() 64 { 65 fClicks.deleteAll(); 66 fMenus.deleteAll(); 67 } 68 69 SkCanvas* SkWindow::createCanvas() { 70 return new SkCanvas(this->getBitmap()); 71 } 72 73 void SkWindow::setMatrix(const SkMatrix& matrix) { 74 if (fMatrix != matrix) { 75 fMatrix = matrix; 76 this->inval(NULL); 77 } 78 } 79 80 void SkWindow::preConcat(const SkMatrix& matrix) { 81 SkMatrix m; 82 m.setConcat(fMatrix, matrix); 83 this->setMatrix(m); 84 } 85 86 void SkWindow::postConcat(const SkMatrix& matrix) { 87 SkMatrix m; 88 m.setConcat(matrix, fMatrix); 89 this->setMatrix(m); 90 } 91 92 void SkWindow::setConfig(SkBitmap::Config config) 93 { 94 this->resize(fBitmap.width(), fBitmap.height(), config); 95 } 96 97 void SkWindow::resize(int width, int height, SkBitmap::Config config) 98 { 99 if (config == SkBitmap::kNo_Config) 100 config = fConfig; 101 102 if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig) 103 { 104 fConfig = config; 105 fBitmap.setConfig(config, width, height, 0, kOpaque_SkAlphaType); 106 fBitmap.allocPixels(); 107 108 this->setSize(SkIntToScalar(width), SkIntToScalar(height)); 109 this->inval(NULL); 110 } 111 } 112 113 void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 114 { 115 fBitmap.eraseARGB(a, r, g, b); 116 } 117 118 void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b) 119 { 120 fBitmap.eraseARGB(0xFF, r, g, b); 121 } 122 123 bool SkWindow::handleInval(const SkRect* localR) 124 { 125 SkIRect ir; 126 127 if (localR) { 128 SkRect devR; 129 SkMatrix inverse; 130 if (!fMatrix.invert(&inverse)) { 131 return false; 132 } 133 fMatrix.mapRect(&devR, *localR); 134 devR.round(&ir); 135 } else { 136 ir.set(0, 0, 137 SkScalarRound(this->width()), 138 SkScalarRound(this->height())); 139 } 140 fDirtyRgn.op(ir, SkRegion::kUnion_Op); 141 142 this->onHandleInval(ir); 143 return true; 144 } 145 146 void SkWindow::forceInvalAll() { 147 fDirtyRgn.setRect(0, 0, 148 SkScalarCeil(this->width()), 149 SkScalarCeil(this->height())); 150 } 151 152 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 153 #include <windows.h> 154 #include <gx.h> 155 extern GXDisplayProperties gDisplayProps; 156 #endif 157 158 #ifdef SK_SIMULATE_FAILED_MALLOC 159 extern bool gEnableControlledThrow; 160 #endif 161 162 bool SkWindow::update(SkIRect* updateArea) 163 { 164 if (!fDirtyRgn.isEmpty()) 165 { 166 SkBitmap bm = this->getBitmap(); 167 168 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 169 char* buffer = (char*)GXBeginDraw(); 170 SkASSERT(buffer); 171 172 RECT rect; 173 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect); 174 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch; 175 176 bm.setPixels(buffer); 177 #endif 178 179 SkAutoTUnref<SkCanvas> canvas(this->createCanvas()); 180 181 canvas->clipRegion(fDirtyRgn); 182 if (updateArea) 183 *updateArea = fDirtyRgn.getBounds(); 184 185 SkAutoCanvasRestore acr(canvas, true); 186 canvas->concat(fMatrix); 187 188 // empty this now, so we can correctly record any inval calls that 189 // might be made during the draw call. 190 fDirtyRgn.setEmpty(); 191 192 #ifdef TEST_BOUNDER 193 test_bounder b(bm); 194 canvas->setBounder(&b); 195 #endif 196 #ifdef SK_SIMULATE_FAILED_MALLOC 197 gEnableControlledThrow = true; 198 #endif 199 #ifdef SK_BUILD_FOR_WIN32 200 //try { 201 this->draw(canvas); 202 //} 203 //catch (...) { 204 //} 205 #else 206 this->draw(canvas); 207 #endif 208 #ifdef SK_SIMULATE_FAILED_MALLOC 209 gEnableControlledThrow = false; 210 #endif 211 #ifdef TEST_BOUNDER 212 canvas->setBounder(NULL); 213 #endif 214 215 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 216 GXEndDraw(); 217 #endif 218 219 return true; 220 } 221 return false; 222 } 223 224 bool SkWindow::handleChar(SkUnichar uni) 225 { 226 if (this->onHandleChar(uni)) 227 return true; 228 229 SkView* focus = this->getFocusView(); 230 if (focus == NULL) 231 focus = this; 232 233 SkEvent evt(SK_EventType_Unichar); 234 evt.setFast32(uni); 235 return focus->doEvent(evt); 236 } 237 238 bool SkWindow::handleKey(SkKey key) 239 { 240 if (key == kNONE_SkKey) 241 return false; 242 243 if (this->onHandleKey(key)) 244 return true; 245 246 // send an event to the focus-view 247 { 248 SkView* focus = this->getFocusView(); 249 if (focus == NULL) 250 focus = this; 251 252 SkEvent evt(SK_EventType_Key); 253 evt.setFast32(key); 254 if (focus->doEvent(evt)) 255 return true; 256 } 257 258 if (key == kUp_SkKey || key == kDown_SkKey) 259 { 260 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL) 261 this->onSetFocusView(NULL); 262 return true; 263 } 264 return false; 265 } 266 267 bool SkWindow::handleKeyUp(SkKey key) 268 { 269 if (key == kNONE_SkKey) 270 return false; 271 272 if (this->onHandleKeyUp(key)) 273 return true; 274 275 //send an event to the focus-view 276 { 277 SkView* focus = this->getFocusView(); 278 if (focus == NULL) 279 focus = this; 280 281 //should this one be the same? 282 SkEvent evt(SK_EventType_KeyUp); 283 evt.setFast32(key); 284 if (focus->doEvent(evt)) 285 return true; 286 } 287 return false; 288 } 289 290 void SkWindow::addMenu(SkOSMenu* menu) { 291 *fMenus.append() = menu; 292 this->onAddMenu(menu); 293 } 294 295 void SkWindow::setTitle(const char title[]) { 296 if (NULL == title) { 297 title = ""; 298 } 299 fTitle.set(title); 300 this->onSetTitle(title); 301 } 302 303 ////////////////////////////////////////////////////////////////////// 304 305 bool SkWindow::onEvent(const SkEvent& evt) 306 { 307 if (evt.isType(SK_EventDelayInval)) 308 { 309 SkRegion::Iterator iter(fDirtyRgn); 310 311 for (; !iter.done(); iter.next()) 312 this->onHandleInval(iter.rect()); 313 fWaitingOnInval = false; 314 return true; 315 } 316 return this->INHERITED::onEvent(evt); 317 } 318 319 bool SkWindow::onGetFocusView(SkView** focus) const 320 { 321 if (focus) 322 *focus = fFocusView; 323 return true; 324 } 325 326 bool SkWindow::onSetFocusView(SkView* focus) 327 { 328 if (fFocusView != focus) 329 { 330 if (fFocusView) 331 fFocusView->onFocusChange(false); 332 fFocusView = focus; 333 if (focus) 334 focus->onFocusChange(true); 335 } 336 return true; 337 } 338 339 ////////////////////////////////////////////////////////////////////// 340 341 void SkWindow::onHandleInval(const SkIRect&) 342 { 343 } 344 345 bool SkWindow::onHandleChar(SkUnichar) 346 { 347 return false; 348 } 349 350 bool SkWindow::onHandleKey(SkKey) 351 { 352 return false; 353 } 354 355 bool SkWindow::onHandleKeyUp(SkKey) 356 { 357 return false; 358 } 359 360 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner, 361 unsigned modifierKeys) { 362 return this->onDispatchClick(x, y, state, owner, modifierKeys); 363 } 364 365 bool SkWindow::onDispatchClick(int x, int y, Click::State state, 366 void* owner, unsigned modifierKeys) { 367 bool handled = false; 368 369 // First, attempt to find an existing click with this owner. 370 int index = -1; 371 for (int i = 0; i < fClicks.count(); i++) { 372 if (owner == fClicks[i]->fOwner) { 373 index = i; 374 break; 375 } 376 } 377 378 switch (state) { 379 case Click::kDown_State: { 380 if (index != -1) { 381 delete fClicks[index]; 382 fClicks.remove(index); 383 } 384 Click* click = this->findClickHandler(SkIntToScalar(x), 385 SkIntToScalar(y), modifierKeys); 386 387 if (click) { 388 click->fOwner = owner; 389 *fClicks.append() = click; 390 SkView::DoClickDown(click, x, y, modifierKeys); 391 handled = true; 392 } 393 break; 394 } 395 case Click::kMoved_State: 396 if (index != -1) { 397 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys); 398 handled = true; 399 } 400 break; 401 case Click::kUp_State: 402 if (index != -1) { 403 SkView::DoClickUp(fClicks[index], x, y, modifierKeys); 404 delete fClicks[index]; 405 fClicks.remove(index); 406 handled = true; 407 } 408 break; 409 default: 410 // Do nothing 411 break; 412 } 413 return handled; 414 } 415