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