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" 20class test_bounder : public SkBounder { 21public: 22 test_bounder(const SkBitmap& bm) : fCanvas(bm) {} 23protected: 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 } 45private: 46 SkCanvas fCanvas; 47}; 48 49SkWindow::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 63SkWindow::~SkWindow() 64{ 65 fClicks.deleteAll(); 66 fMenus.deleteAll(); 67} 68 69SkCanvas* SkWindow::createCanvas() { 70 return new SkCanvas(this->getBitmap()); 71} 72 73void SkWindow::setMatrix(const SkMatrix& matrix) { 74 if (fMatrix != matrix) { 75 fMatrix = matrix; 76 this->inval(NULL); 77 } 78} 79 80void SkWindow::preConcat(const SkMatrix& matrix) { 81 SkMatrix m; 82 m.setConcat(fMatrix, matrix); 83 this->setMatrix(m); 84} 85 86void SkWindow::postConcat(const SkMatrix& matrix) { 87 SkMatrix m; 88 m.setConcat(matrix, fMatrix); 89 this->setMatrix(m); 90} 91 92void SkWindow::setConfig(SkBitmap::Config config) 93{ 94 this->resize(fBitmap.width(), fBitmap.height(), config); 95} 96 97void 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 113void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b) 114{ 115 fBitmap.eraseARGB(a, r, g, b); 116} 117 118void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b) 119{ 120 fBitmap.eraseARGB(0xFF, r, g, b); 121} 122 123bool 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 146void 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 159extern bool gEnableControlledThrow; 160#endif 161 162bool 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 224bool 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 238bool 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 267bool 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 290void SkWindow::addMenu(SkOSMenu* menu) { 291 *fMenus.append() = menu; 292 this->onAddMenu(menu); 293} 294 295void SkWindow::setTitle(const char title[]) { 296 if (NULL == title) { 297 title = ""; 298 } 299 fTitle.set(title); 300 this->onSetTitle(title); 301} 302 303////////////////////////////////////////////////////////////////////// 304 305bool 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 319bool SkWindow::onGetFocusView(SkView** focus) const 320{ 321 if (focus) 322 *focus = fFocusView; 323 return true; 324} 325 326bool 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 341void SkWindow::onHandleInval(const SkIRect&) 342{ 343} 344 345bool SkWindow::onHandleChar(SkUnichar) 346{ 347 return false; 348} 349 350bool SkWindow::onHandleKey(SkKey) 351{ 352 return false; 353} 354 355bool SkWindow::onHandleKeyUp(SkKey) 356{ 357 return false; 358} 359 360bool 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 365bool 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