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 #define TEST_BOUNDERx
     18 
     19 #include "SkBounder.h"
     20 class test_bounder : public SkBounder {
     21 public:
     22     test_bounder(const SkBitmap& bm) : fCanvas(bm) {}
     23 protected:
     24     virtual bool onIRect(const SkIRect& r)
     25     {
     26         SkRect    rr;
     27 
     28         rr.set(SkIntToScalar(r.fLeft), SkIntToScalar(r.fTop),
     29                 SkIntToScalar(r.fRight), SkIntToScalar(r.fBottom));
     30 
     31         SkPaint    p;
     32 
     33         p.setStyle(SkPaint::kStroke_Style);
     34         p.setColor(SK_ColorYELLOW);
     35 
     36 #if 0
     37         rr.inset(SK_ScalarHalf, SK_ScalarHalf);
     38 #else
     39         rr.inset(-SK_ScalarHalf, -SK_ScalarHalf);
     40 #endif
     41 
     42         fCanvas.drawRect(rr, p);
     43         return true;
     44     }
     45 private:
     46     SkCanvas    fCanvas;
     47 };
     48 
     49 SkWindow::SkWindow() : fFocusView(NULL)
     50 {
     51     fClicks.reset();
     52     fWaitingOnInval = false;
     53 
     54 #ifdef SK_BUILD_FOR_WINCE
     55     fConfig = SkBitmap::kRGB_565_Config;
     56 #else
     57     fConfig = SkBitmap::kARGB_8888_Config;
     58 #endif
     59 
     60     fMatrix.reset();
     61 }
     62 
     63 SkWindow::~SkWindow()
     64 {
     65     fClicks.deleteAll();
     66     fMenus.deleteAll();
     67 }
     68 
     69 SkCanvas* SkWindow::createCanvas() {
     70     return new SkCanvas(this->getBitmap());
     71 }
     72 
     73 void SkWindow::setMatrix(const SkMatrix& matrix) {
     74     if (fMatrix != matrix) {
     75         fMatrix = matrix;
     76         this->inval(NULL);
     77     }
     78 }
     79 
     80 void SkWindow::preConcat(const SkMatrix& matrix) {
     81     SkMatrix m;
     82     m.setConcat(fMatrix, matrix);
     83     this->setMatrix(m);
     84 }
     85 
     86 void SkWindow::postConcat(const SkMatrix& matrix) {
     87     SkMatrix m;
     88     m.setConcat(matrix, fMatrix);
     89     this->setMatrix(m);
     90 }
     91 
     92 void SkWindow::setConfig(SkBitmap::Config config)
     93 {
     94     this->resize(fBitmap.width(), fBitmap.height(), config);
     95 }
     96 
     97 void SkWindow::resize(int width, int height, SkBitmap::Config config)
     98 {
     99     if (config == SkBitmap::kNo_Config)
    100         config = fConfig;
    101 
    102     if (width != fBitmap.width() || height != fBitmap.height() || config != fConfig)
    103     {
    104         fConfig = config;
    105         fBitmap.setConfig(config, width, height);
    106         fBitmap.allocPixels();
    107         fBitmap.setIsOpaque(true);
    108 
    109         this->setSize(SkIntToScalar(width), SkIntToScalar(height));
    110         this->inval(NULL);
    111     }
    112 }
    113 
    114 void SkWindow::eraseARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
    115 {
    116     fBitmap.eraseARGB(a, r, g, b);
    117 }
    118 
    119 void SkWindow::eraseRGB(U8CPU r, U8CPU g, U8CPU b)
    120 {
    121     fBitmap.eraseRGB(r, g, b);
    122 }
    123 
    124 bool SkWindow::handleInval(const SkRect* localR)
    125 {
    126     SkIRect    ir;
    127 
    128     if (localR) {
    129         SkRect devR;
    130         SkMatrix inverse;
    131         if (!fMatrix.invert(&inverse)) {
    132             return false;
    133         }
    134         fMatrix.mapRect(&devR, *localR);
    135         devR.round(&ir);
    136     } else {
    137         ir.set(0, 0,
    138                SkScalarRound(this->width()),
    139                SkScalarRound(this->height()));
    140     }
    141     fDirtyRgn.op(ir, SkRegion::kUnion_Op);
    142 
    143     this->onHandleInval(ir);
    144     return true;
    145 }
    146 
    147 void SkWindow::forceInvalAll() {
    148     fDirtyRgn.setRect(0, 0,
    149                       SkScalarCeil(this->width()),
    150                       SkScalarCeil(this->height()));
    151 }
    152 
    153 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
    154     #include <windows.h>
    155     #include <gx.h>
    156     extern GXDisplayProperties gDisplayProps;
    157 #endif
    158 
    159 #ifdef SK_SIMULATE_FAILED_MALLOC
    160 extern bool gEnableControlledThrow;
    161 #endif
    162 
    163 bool SkWindow::update(SkIRect* updateArea)
    164 {
    165     if (!fDirtyRgn.isEmpty())
    166     {
    167         SkBitmap bm = this->getBitmap();
    168 
    169 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
    170         char* buffer = (char*)GXBeginDraw();
    171         SkASSERT(buffer);
    172 
    173         RECT    rect;
    174         GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
    175         buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
    176 
    177         bm.setPixels(buffer);
    178 #endif
    179 
    180         SkAutoTUnref<SkCanvas> canvas(this->createCanvas());
    181 
    182         canvas->clipRegion(fDirtyRgn);
    183         if (updateArea)
    184             *updateArea = fDirtyRgn.getBounds();
    185 
    186         SkAutoCanvasRestore acr(canvas, true);
    187         canvas->concat(fMatrix);
    188 
    189         // empty this now, so we can correctly record any inval calls that
    190         // might be made during the draw call.
    191         fDirtyRgn.setEmpty();
    192 
    193 #ifdef TEST_BOUNDER
    194         test_bounder    b(bm);
    195         canvas->setBounder(&b);
    196 #endif
    197 #ifdef SK_SIMULATE_FAILED_MALLOC
    198         gEnableControlledThrow = true;
    199 #endif
    200 #ifdef SK_BUILD_FOR_WIN32
    201         //try {
    202             this->draw(canvas);
    203         //}
    204         //catch (...) {
    205         //}
    206 #else
    207         this->draw(canvas);
    208 #endif
    209 #ifdef SK_SIMULATE_FAILED_MALLOC
    210         gEnableControlledThrow = false;
    211 #endif
    212 #ifdef TEST_BOUNDER
    213         canvas->setBounder(NULL);
    214 #endif
    215 
    216 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
    217         GXEndDraw();
    218 #endif
    219 
    220         return true;
    221     }
    222     return false;
    223 }
    224 
    225 bool SkWindow::handleChar(SkUnichar uni)
    226 {
    227     if (this->onHandleChar(uni))
    228         return true;
    229 
    230     SkView* focus = this->getFocusView();
    231     if (focus == NULL)
    232         focus = this;
    233 
    234     SkEvent evt(SK_EventType_Unichar);
    235     evt.setFast32(uni);
    236     return focus->doEvent(evt);
    237 }
    238 
    239 bool SkWindow::handleKey(SkKey key)
    240 {
    241     if (key == kNONE_SkKey)
    242         return false;
    243 
    244     if (this->onHandleKey(key))
    245         return true;
    246 
    247     // send an event to the focus-view
    248     {
    249         SkView* focus = this->getFocusView();
    250         if (focus == NULL)
    251             focus = this;
    252 
    253         SkEvent evt(SK_EventType_Key);
    254         evt.setFast32(key);
    255         if (focus->doEvent(evt))
    256             return true;
    257     }
    258 
    259     if (key == kUp_SkKey || key == kDown_SkKey)
    260     {
    261         if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
    262             this->onSetFocusView(NULL);
    263         return true;
    264     }
    265     return false;
    266 }
    267 
    268 bool SkWindow::handleKeyUp(SkKey key)
    269 {
    270     if (key == kNONE_SkKey)
    271         return false;
    272 
    273     if (this->onHandleKeyUp(key))
    274         return true;
    275 
    276     //send an event to the focus-view
    277     {
    278         SkView* focus = this->getFocusView();
    279         if (focus == NULL)
    280             focus = this;
    281 
    282         //should this one be the same?
    283         SkEvent evt(SK_EventType_KeyUp);
    284         evt.setFast32(key);
    285         if (focus->doEvent(evt))
    286             return true;
    287     }
    288     return false;
    289 }
    290 
    291 void SkWindow::addMenu(SkOSMenu* menu) {
    292     *fMenus.append() = menu;
    293     this->onAddMenu(menu);
    294 }
    295 
    296 void SkWindow::setTitle(const char title[]) {
    297     if (NULL == title) {
    298         title = "";
    299     }
    300     fTitle.set(title);
    301     this->onSetTitle(title);
    302 }
    303 
    304 //////////////////////////////////////////////////////////////////////
    305 
    306 bool SkWindow::onEvent(const SkEvent& evt)
    307 {
    308     if (evt.isType(SK_EventDelayInval))
    309     {
    310         SkRegion::Iterator    iter(fDirtyRgn);
    311 
    312         for (; !iter.done(); iter.next())
    313             this->onHandleInval(iter.rect());
    314         fWaitingOnInval = false;
    315         return true;
    316     }
    317     return this->INHERITED::onEvent(evt);
    318 }
    319 
    320 bool SkWindow::onGetFocusView(SkView** focus) const
    321 {
    322     if (focus)
    323         *focus = fFocusView;
    324     return true;
    325 }
    326 
    327 bool SkWindow::onSetFocusView(SkView* focus)
    328 {
    329     if (fFocusView != focus)
    330     {
    331         if (fFocusView)
    332             fFocusView->onFocusChange(false);
    333         fFocusView = focus;
    334         if (focus)
    335             focus->onFocusChange(true);
    336     }
    337     return true;
    338 }
    339 
    340 //////////////////////////////////////////////////////////////////////
    341 
    342 void SkWindow::onHandleInval(const SkIRect&)
    343 {
    344 }
    345 
    346 bool SkWindow::onHandleChar(SkUnichar)
    347 {
    348     return false;
    349 }
    350 
    351 bool SkWindow::onHandleKey(SkKey)
    352 {
    353     return false;
    354 }
    355 
    356 bool SkWindow::onHandleKeyUp(SkKey)
    357 {
    358     return false;
    359 }
    360 
    361 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
    362                            unsigned modifierKeys) {
    363     return this->onDispatchClick(x, y, state, owner, modifierKeys);
    364 }
    365 
    366 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
    367                                void* owner, unsigned modifierKeys) {
    368     bool handled = false;
    369 
    370     // First, attempt to find an existing click with this owner.
    371     int index = -1;
    372     for (int i = 0; i < fClicks.count(); i++) {
    373         if (owner == fClicks[i]->fOwner) {
    374             index = i;
    375             break;
    376         }
    377     }
    378 
    379     switch (state) {
    380         case Click::kDown_State: {
    381             if (index != -1) {
    382                 delete fClicks[index];
    383                 fClicks.remove(index);
    384             }
    385             Click* click = this->findClickHandler(SkIntToScalar(x),
    386                                                   SkIntToScalar(y), modifierKeys);
    387 
    388             if (click) {
    389                 click->fOwner = owner;
    390                 *fClicks.append() = click;
    391                 SkView::DoClickDown(click, x, y, modifierKeys);
    392                 handled = true;
    393             }
    394             break;
    395         }
    396         case Click::kMoved_State:
    397             if (index != -1) {
    398                 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
    399                 handled = true;
    400             }
    401             break;
    402         case Click::kUp_State:
    403             if (index != -1) {
    404                 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
    405                 delete fClicks[index];
    406                 fClicks.remove(index);
    407                 handled = true;
    408             }
    409             break;
    410         default:
    411             // Do nothing
    412             break;
    413     }
    414     return handled;
    415 }
    416