Home | History | Annotate | Download | only in views
      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