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 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 30 SkWindow::~SkWindow() { 31 fClicks.deleteAll(); 32 fMenus.deleteAll(); 33 } 34 35 SkCanvas* SkWindow::createCanvas() { 36 return new SkCanvas(this->getBitmap()); 37 } 38 39 void SkWindow::setMatrix(const SkMatrix& matrix) { 40 if (fMatrix != matrix) { 41 fMatrix = matrix; 42 this->inval(NULL); 43 } 44 } 45 46 void SkWindow::preConcat(const SkMatrix& matrix) { 47 SkMatrix m; 48 m.setConcat(fMatrix, matrix); 49 this->setMatrix(m); 50 } 51 52 void SkWindow::postConcat(const SkMatrix& matrix) { 53 SkMatrix m; 54 m.setConcat(matrix, fMatrix); 55 this->setMatrix(m); 56 } 57 58 void SkWindow::setColorType(SkColorType ct) { 59 this->resize(fBitmap.width(), fBitmap.height(), ct); 60 } 61 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 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 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 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 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 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 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 229 void SkWindow::addMenu(SkOSMenu* menu) { 230 *fMenus.append() = menu; 231 this->onAddMenu(menu); 232 } 233 234 void SkWindow::setTitle(const char title[]) { 235 if (NULL == title) { 236 title = ""; 237 } 238 fTitle.set(title); 239 this->onSetTitle(title); 240 } 241 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 252 bool SkWindow::onGetFocusView(SkView** focus) const { 253 if (focus) 254 *focus = fFocusView; 255 return true; 256 } 257 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 269 void SkWindow::onHandleInval(const SkIRect&) { 270 } 271 272 bool SkWindow::onHandleChar(SkUnichar) { 273 return false; 274 } 275 276 bool SkWindow::onHandleKey(SkKey) { 277 return false; 278 } 279 280 bool SkWindow::onHandleKeyUp(SkKey) { 281 return false; 282 } 283 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 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