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