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