1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/views/SkWindow.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,377 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2011 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 +#include "SkWindow.h" 1.12 +#include "SkCanvas.h" 1.13 +#include "SkDevice.h" 1.14 +#include "SkOSMenu.h" 1.15 +#include "SkSystemEventTypes.h" 1.16 +#include "SkTime.h" 1.17 + 1.18 +#define SK_EventDelayInval "\xd" "n" "\xa" "l" 1.19 + 1.20 +#define TEST_BOUNDERx 1.21 + 1.22 +#include "SkBounder.h" 1.23 +class TestSkBounder : public SkBounder { 1.24 +public: 1.25 + explicit TestSkBounder(const SkBitmap& bm) : fCanvas(bm) {} 1.26 + 1.27 +protected: 1.28 + virtual bool onIRect(const SkIRect& r) SK_OVERRIDE { 1.29 + SkRect rr; 1.30 + 1.31 + rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop), 1.32 + SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom)); 1.33 + 1.34 + SkPaint p; 1.35 + 1.36 + p.setStyle(SkPaint::kStroke_Style); 1.37 + p.setColor(SK_ColorYELLOW); 1.38 + 1.39 +#if 0 1.40 + rr.inset(SK_ScalarHalf, SK_ScalarHalf); 1.41 +#else 1.42 + rr.inset(-SK_ScalarHalf, -SK_ScalarHalf); 1.43 +#endif 1.44 + 1.45 + fCanvas.drawRect(rr, p); 1.46 + return true; 1.47 + } 1.48 +private: 1.49 + SkCanvas fCanvas; 1.50 +}; 1.51 + 1.52 +SkWindow::SkWindow() : fFocusView(NULL) { 1.53 + fClicks.reset(); 1.54 + fWaitingOnInval = false; 1.55 + 1.56 +#ifdef SK_BUILD_FOR_WINCE 1.57 + fColorType = kRGB_565_SkColorType; 1.58 +#else 1.59 + fColorType = kPMColor_SkColorType; 1.60 +#endif 1.61 + 1.62 + fMatrix.reset(); 1.63 +} 1.64 + 1.65 +SkWindow::~SkWindow() { 1.66 + fClicks.deleteAll(); 1.67 + fMenus.deleteAll(); 1.68 +} 1.69 + 1.70 +SkCanvas* SkWindow::createCanvas() { 1.71 + return new SkCanvas(this->getBitmap()); 1.72 +} 1.73 + 1.74 +void SkWindow::setMatrix(const SkMatrix& matrix) { 1.75 + if (fMatrix != matrix) { 1.76 + fMatrix = matrix; 1.77 + this->inval(NULL); 1.78 + } 1.79 +} 1.80 + 1.81 +void SkWindow::preConcat(const SkMatrix& matrix) { 1.82 + SkMatrix m; 1.83 + m.setConcat(fMatrix, matrix); 1.84 + this->setMatrix(m); 1.85 +} 1.86 + 1.87 +void SkWindow::postConcat(const SkMatrix& matrix) { 1.88 + SkMatrix m; 1.89 + m.setConcat(matrix, fMatrix); 1.90 + this->setMatrix(m); 1.91 +} 1.92 + 1.93 +void SkWindow::setColorType(SkColorType ct) { 1.94 + this->resize(fBitmap.width(), fBitmap.height(), ct); 1.95 +} 1.96 + 1.97 +void SkWindow::resize(int width, int height, SkColorType ct) { 1.98 + if (ct == kUnknown_SkColorType) 1.99 + ct = fColorType; 1.100 + 1.101 + if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) { 1.102 + fColorType = ct; 1.103 + fBitmap.allocPixels(SkImageInfo::Make(width, height, 1.104 + ct, kPremul_SkAlphaType)); 1.105 + 1.106 + this->setSize(SkIntToScalar(width), SkIntToScalar(height)); 1.107 + this->inval(NULL); 1.108 + } 1.109 +} 1.110 + 1.111 +bool SkWindow::handleInval(const SkRect* localR) { 1.112 + SkIRect ir; 1.113 + 1.114 + if (localR) { 1.115 + SkRect devR; 1.116 + SkMatrix inverse; 1.117 + if (!fMatrix.invert(&inverse)) { 1.118 + return false; 1.119 + } 1.120 + fMatrix.mapRect(&devR, *localR); 1.121 + devR.round(&ir); 1.122 + } else { 1.123 + ir.set(0, 0, 1.124 + SkScalarRoundToInt(this->width()), 1.125 + SkScalarRoundToInt(this->height())); 1.126 + } 1.127 + fDirtyRgn.op(ir, SkRegion::kUnion_Op); 1.128 + 1.129 + this->onHandleInval(ir); 1.130 + return true; 1.131 +} 1.132 + 1.133 +void SkWindow::forceInvalAll() { 1.134 + fDirtyRgn.setRect(0, 0, 1.135 + SkScalarCeilToInt(this->width()), 1.136 + SkScalarCeilToInt(this->height())); 1.137 +} 1.138 + 1.139 +#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 1.140 + #include <windows.h> 1.141 + #include <gx.h> 1.142 + extern GXDisplayProperties gDisplayProps; 1.143 +#endif 1.144 + 1.145 +#ifdef SK_SIMULATE_FAILED_MALLOC 1.146 +extern bool gEnableControlledThrow; 1.147 +#endif 1.148 + 1.149 +bool SkWindow::update(SkIRect* updateArea) { 1.150 + if (!fDirtyRgn.isEmpty()) { 1.151 + SkBitmap bm = this->getBitmap(); 1.152 + 1.153 +#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 1.154 + char* buffer = (char*)GXBeginDraw(); 1.155 + SkASSERT(buffer); 1.156 + 1.157 + RECT rect; 1.158 + GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect); 1.159 + buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch; 1.160 + 1.161 + bm.setPixels(buffer); 1.162 +#endif 1.163 + 1.164 + SkAutoTUnref<SkCanvas> canvas(this->createCanvas()); 1.165 + 1.166 + canvas->clipRegion(fDirtyRgn); 1.167 + if (updateArea) 1.168 + *updateArea = fDirtyRgn.getBounds(); 1.169 + 1.170 + SkAutoCanvasRestore acr(canvas, true); 1.171 + canvas->concat(fMatrix); 1.172 + 1.173 + // empty this now, so we can correctly record any inval calls that 1.174 + // might be made during the draw call. 1.175 + fDirtyRgn.setEmpty(); 1.176 + 1.177 +#ifdef TEST_BOUNDER 1.178 + TestSkBounder bounder(bm); 1.179 + canvas->setBounder(&bounder); 1.180 +#endif 1.181 +#ifdef SK_SIMULATE_FAILED_MALLOC 1.182 + gEnableControlledThrow = true; 1.183 +#endif 1.184 +#ifdef SK_BUILD_FOR_WIN32 1.185 + //try { 1.186 + this->draw(canvas); 1.187 + //} 1.188 + //catch (...) { 1.189 + //} 1.190 +#else 1.191 + this->draw(canvas); 1.192 +#endif 1.193 +#ifdef SK_SIMULATE_FAILED_MALLOC 1.194 + gEnableControlledThrow = false; 1.195 +#endif 1.196 +#ifdef TEST_BOUNDER 1.197 + canvas->setBounder(NULL); 1.198 +#endif 1.199 + 1.200 +#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN) 1.201 + GXEndDraw(); 1.202 +#endif 1.203 + 1.204 + return true; 1.205 + } 1.206 + return false; 1.207 +} 1.208 + 1.209 +bool SkWindow::handleChar(SkUnichar uni) { 1.210 + if (this->onHandleChar(uni)) 1.211 + return true; 1.212 + 1.213 + SkView* focus = this->getFocusView(); 1.214 + if (focus == NULL) 1.215 + focus = this; 1.216 + 1.217 + SkEvent evt(SK_EventType_Unichar); 1.218 + evt.setFast32(uni); 1.219 + return focus->doEvent(evt); 1.220 +} 1.221 + 1.222 +bool SkWindow::handleKey(SkKey key) { 1.223 + if (key == kNONE_SkKey) 1.224 + return false; 1.225 + 1.226 + if (this->onHandleKey(key)) 1.227 + return true; 1.228 + 1.229 + // send an event to the focus-view 1.230 + { 1.231 + SkView* focus = this->getFocusView(); 1.232 + if (focus == NULL) 1.233 + focus = this; 1.234 + 1.235 + SkEvent evt(SK_EventType_Key); 1.236 + evt.setFast32(key); 1.237 + if (focus->doEvent(evt)) 1.238 + return true; 1.239 + } 1.240 + 1.241 + if (key == kUp_SkKey || key == kDown_SkKey) { 1.242 + if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL) 1.243 + this->onSetFocusView(NULL); 1.244 + return true; 1.245 + } 1.246 + return false; 1.247 +} 1.248 + 1.249 +bool SkWindow::handleKeyUp(SkKey key) { 1.250 + if (key == kNONE_SkKey) 1.251 + return false; 1.252 + 1.253 + if (this->onHandleKeyUp(key)) 1.254 + return true; 1.255 + 1.256 + //send an event to the focus-view 1.257 + { 1.258 + SkView* focus = this->getFocusView(); 1.259 + if (focus == NULL) 1.260 + focus = this; 1.261 + 1.262 + //should this one be the same? 1.263 + SkEvent evt(SK_EventType_KeyUp); 1.264 + evt.setFast32(key); 1.265 + if (focus->doEvent(evt)) 1.266 + return true; 1.267 + } 1.268 + return false; 1.269 +} 1.270 + 1.271 +void SkWindow::addMenu(SkOSMenu* menu) { 1.272 + *fMenus.append() = menu; 1.273 + this->onAddMenu(menu); 1.274 +} 1.275 + 1.276 +void SkWindow::setTitle(const char title[]) { 1.277 + if (NULL == title) { 1.278 + title = ""; 1.279 + } 1.280 + fTitle.set(title); 1.281 + this->onSetTitle(title); 1.282 +} 1.283 + 1.284 +bool SkWindow::onEvent(const SkEvent& evt) { 1.285 + if (evt.isType(SK_EventDelayInval)) { 1.286 + for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next()) 1.287 + this->onHandleInval(iter.rect()); 1.288 + fWaitingOnInval = false; 1.289 + return true; 1.290 + } 1.291 + return this->INHERITED::onEvent(evt); 1.292 +} 1.293 + 1.294 +bool SkWindow::onGetFocusView(SkView** focus) const { 1.295 + if (focus) 1.296 + *focus = fFocusView; 1.297 + return true; 1.298 +} 1.299 + 1.300 +bool SkWindow::onSetFocusView(SkView* focus) { 1.301 + if (fFocusView != focus) { 1.302 + if (fFocusView) 1.303 + fFocusView->onFocusChange(false); 1.304 + fFocusView = focus; 1.305 + if (focus) 1.306 + focus->onFocusChange(true); 1.307 + } 1.308 + return true; 1.309 +} 1.310 + 1.311 +void SkWindow::onHandleInval(const SkIRect&) { 1.312 +} 1.313 + 1.314 +bool SkWindow::onHandleChar(SkUnichar) { 1.315 + return false; 1.316 +} 1.317 + 1.318 +bool SkWindow::onHandleKey(SkKey) { 1.319 + return false; 1.320 +} 1.321 + 1.322 +bool SkWindow::onHandleKeyUp(SkKey) { 1.323 + return false; 1.324 +} 1.325 + 1.326 +bool SkWindow::handleClick(int x, int y, Click::State state, void *owner, 1.327 + unsigned modifierKeys) { 1.328 + return this->onDispatchClick(x, y, state, owner, modifierKeys); 1.329 +} 1.330 + 1.331 +bool SkWindow::onDispatchClick(int x, int y, Click::State state, 1.332 + void* owner, unsigned modifierKeys) { 1.333 + bool handled = false; 1.334 + 1.335 + // First, attempt to find an existing click with this owner. 1.336 + int index = -1; 1.337 + for (int i = 0; i < fClicks.count(); i++) { 1.338 + if (owner == fClicks[i]->fOwner) { 1.339 + index = i; 1.340 + break; 1.341 + } 1.342 + } 1.343 + 1.344 + switch (state) { 1.345 + case Click::kDown_State: { 1.346 + if (index != -1) { 1.347 + delete fClicks[index]; 1.348 + fClicks.remove(index); 1.349 + } 1.350 + Click* click = this->findClickHandler(SkIntToScalar(x), 1.351 + SkIntToScalar(y), modifierKeys); 1.352 + 1.353 + if (click) { 1.354 + click->fOwner = owner; 1.355 + *fClicks.append() = click; 1.356 + SkView::DoClickDown(click, x, y, modifierKeys); 1.357 + handled = true; 1.358 + } 1.359 + break; 1.360 + } 1.361 + case Click::kMoved_State: 1.362 + if (index != -1) { 1.363 + SkView::DoClickMoved(fClicks[index], x, y, modifierKeys); 1.364 + handled = true; 1.365 + } 1.366 + break; 1.367 + case Click::kUp_State: 1.368 + if (index != -1) { 1.369 + SkView::DoClickUp(fClicks[index], x, y, modifierKeys); 1.370 + delete fClicks[index]; 1.371 + fClicks.remove(index); 1.372 + handled = true; 1.373 + } 1.374 + break; 1.375 + default: 1.376 + // Do nothing 1.377 + break; 1.378 + } 1.379 + return handled; 1.380 +}