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()
     18     : fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
     19     , fFocusView(nullptr)
     20 {
     21     fClicks.reset();
     22     fWaitingOnInval = false;
     23     fMatrix.reset();
     24 
     25     fBitmap.allocN32Pixels(0, 0);
     26 }
     27 
     28 SkWindow::~SkWindow() {
     29     fClicks.deleteAll();
     30     fMenus.deleteAll();
     31 }
     32 
     33 SkSurface* SkWindow::createSurface() {
     34     const SkBitmap& bm = this->getBitmap();
     35     return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
     36 }
     37 
     38 void SkWindow::setMatrix(const SkMatrix& matrix) {
     39     if (fMatrix != matrix) {
     40         fMatrix = matrix;
     41         this->inval(nullptr);
     42     }
     43 }
     44 
     45 void SkWindow::preConcat(const SkMatrix& matrix) {
     46     SkMatrix m;
     47     m.setConcat(fMatrix, matrix);
     48     this->setMatrix(m);
     49 }
     50 
     51 void SkWindow::postConcat(const SkMatrix& matrix) {
     52     SkMatrix m;
     53     m.setConcat(matrix, fMatrix);
     54     this->setMatrix(m);
     55 }
     56 
     57 void SkWindow::resize(const SkImageInfo& info) {
     58     if (fBitmap.info() != info) {
     59         fBitmap.allocPixels(info);
     60         this->inval(nullptr);
     61     }
     62     this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
     63 }
     64 
     65 void SkWindow::resize(int width, int height) {
     66     this->resize(fBitmap.info().makeWH(width, height));
     67 }
     68 
     69 void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) {
     70     const SkImageInfo& info = fBitmap.info();
     71     this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt));
     72 }
     73 
     74 bool SkWindow::handleInval(const SkRect* localR) {
     75     SkIRect ir;
     76 
     77     if (localR) {
     78         SkRect devR;
     79         SkMatrix inverse;
     80         if (!fMatrix.invert(&inverse)) {
     81             return false;
     82         }
     83         fMatrix.mapRect(&devR, *localR);
     84         devR.round(&ir);
     85     } else {
     86         ir.set(0, 0,
     87                SkScalarRoundToInt(this->width()),
     88                SkScalarRoundToInt(this->height()));
     89     }
     90     fDirtyRgn.op(ir, SkRegion::kUnion_Op);
     91 
     92     this->onHandleInval(ir);
     93     return true;
     94 }
     95 
     96 void SkWindow::forceInvalAll() {
     97     fDirtyRgn.setRect(0, 0,
     98                       SkScalarCeilToInt(this->width()),
     99                       SkScalarCeilToInt(this->height()));
    100 }
    101 
    102 #ifdef SK_SIMULATE_FAILED_MALLOC
    103 extern bool gEnableControlledThrow;
    104 #endif
    105 
    106 bool SkWindow::update(SkIRect* updateArea) {
    107     if (!fDirtyRgn.isEmpty()) {
    108         SkAutoTUnref<SkSurface> surface(this->createSurface());
    109         SkCanvas* canvas = surface->getCanvas();
    110 
    111         canvas->clipRegion(fDirtyRgn);
    112         if (updateArea) {
    113             *updateArea = fDirtyRgn.getBounds();
    114         }
    115 
    116         SkAutoCanvasRestore acr(canvas, true);
    117         canvas->concat(fMatrix);
    118 
    119         // empty this now, so we can correctly record any inval calls that
    120         // might be made during the draw call.
    121         fDirtyRgn.setEmpty();
    122 
    123 #ifdef SK_SIMULATE_FAILED_MALLOC
    124         gEnableControlledThrow = true;
    125 #endif
    126 #ifdef SK_BUILD_FOR_WIN32
    127         //try {
    128             this->draw(canvas);
    129         //}
    130         //catch (...) {
    131         //}
    132 #else
    133         this->draw(canvas);
    134 #endif
    135 #ifdef SK_SIMULATE_FAILED_MALLOC
    136         gEnableControlledThrow = false;
    137 #endif
    138 
    139         return true;
    140     }
    141     return false;
    142 }
    143 
    144 bool SkWindow::handleChar(SkUnichar uni) {
    145     if (this->onHandleChar(uni))
    146         return true;
    147 
    148     SkView* focus = this->getFocusView();
    149     if (focus == nullptr)
    150         focus = this;
    151 
    152     SkEvent evt(SK_EventType_Unichar);
    153     evt.setFast32(uni);
    154     return focus->doEvent(evt);
    155 }
    156 
    157 bool SkWindow::handleKey(SkKey key) {
    158     if (key == kNONE_SkKey)
    159         return false;
    160 
    161     if (this->onHandleKey(key))
    162         return true;
    163 
    164     // send an event to the focus-view
    165     {
    166         SkView* focus = this->getFocusView();
    167         if (focus == nullptr)
    168             focus = this;
    169 
    170         SkEvent evt(SK_EventType_Key);
    171         evt.setFast32(key);
    172         if (focus->doEvent(evt))
    173             return true;
    174     }
    175 
    176     if (key == kUp_SkKey || key == kDown_SkKey) {
    177         if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr)
    178             this->onSetFocusView(nullptr);
    179         return true;
    180     }
    181     return false;
    182 }
    183 
    184 bool SkWindow::handleKeyUp(SkKey key) {
    185     if (key == kNONE_SkKey)
    186         return false;
    187 
    188     if (this->onHandleKeyUp(key))
    189         return true;
    190 
    191     //send an event to the focus-view
    192     {
    193         SkView* focus = this->getFocusView();
    194         if (focus == nullptr)
    195             focus = this;
    196 
    197         //should this one be the same?
    198         SkEvent evt(SK_EventType_KeyUp);
    199         evt.setFast32(key);
    200         if (focus->doEvent(evt))
    201             return true;
    202     }
    203     return false;
    204 }
    205 
    206 void SkWindow::addMenu(SkOSMenu* menu) {
    207     *fMenus.append() = menu;
    208     this->onAddMenu(menu);
    209 }
    210 
    211 void SkWindow::setTitle(const char title[]) {
    212     if (nullptr == title) {
    213         title = "";
    214     }
    215     fTitle.set(title);
    216     this->onSetTitle(title);
    217 }
    218 
    219 bool SkWindow::onEvent(const SkEvent& evt) {
    220     if (evt.isType(SK_EventDelayInval)) {
    221         for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
    222             this->onHandleInval(iter.rect());
    223         fWaitingOnInval = false;
    224         return true;
    225     }
    226     return this->INHERITED::onEvent(evt);
    227 }
    228 
    229 bool SkWindow::onGetFocusView(SkView** focus) const {
    230     if (focus)
    231         *focus = fFocusView;
    232     return true;
    233 }
    234 
    235 bool SkWindow::onSetFocusView(SkView* focus) {
    236     if (fFocusView != focus) {
    237         if (fFocusView)
    238             fFocusView->onFocusChange(false);
    239         fFocusView = focus;
    240         if (focus)
    241             focus->onFocusChange(true);
    242     }
    243     return true;
    244 }
    245 
    246 void SkWindow::onHandleInval(const SkIRect&) {
    247 }
    248 
    249 bool SkWindow::onHandleChar(SkUnichar) {
    250     return false;
    251 }
    252 
    253 bool SkWindow::onHandleKey(SkKey) {
    254     return false;
    255 }
    256 
    257 bool SkWindow::onHandleKeyUp(SkKey) {
    258     return false;
    259 }
    260 
    261 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
    262                            unsigned modifierKeys) {
    263     return this->onDispatchClick(x, y, state, owner, modifierKeys);
    264 }
    265 
    266 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
    267                                void* owner, unsigned modifierKeys) {
    268     bool handled = false;
    269 
    270     // First, attempt to find an existing click with this owner.
    271     int index = -1;
    272     for (int i = 0; i < fClicks.count(); i++) {
    273         if (owner == fClicks[i]->fOwner) {
    274             index = i;
    275             break;
    276         }
    277     }
    278 
    279     switch (state) {
    280         case Click::kDown_State: {
    281             if (index != -1) {
    282                 delete fClicks[index];
    283                 fClicks.remove(index);
    284             }
    285             Click* click = this->findClickHandler(SkIntToScalar(x),
    286                                                   SkIntToScalar(y), modifierKeys);
    287 
    288             if (click) {
    289                 click->fOwner = owner;
    290                 *fClicks.append() = click;
    291                 SkView::DoClickDown(click, x, y, modifierKeys);
    292                 handled = true;
    293             }
    294             break;
    295         }
    296         case Click::kMoved_State:
    297             if (index != -1) {
    298                 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
    299                 handled = true;
    300             }
    301             break;
    302         case Click::kUp_State:
    303             if (index != -1) {
    304                 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
    305                 delete fClicks[index];
    306                 fClicks.remove(index);
    307                 handled = true;
    308             }
    309             break;
    310         default:
    311             // Do nothing
    312             break;
    313     }
    314     return handled;
    315 }
    316 
    317 #if SK_SUPPORT_GPU
    318 
    319 #include "GrContext.h"
    320 #include "gl/GrGLInterface.h"
    321 #include "gl/GrGLUtil.h"
    322 #include "SkGr.h"
    323 
    324 GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
    325         const GrGLInterface* interface, GrContext* grContext) {
    326     GrBackendRenderTargetDesc desc;
    327     desc.fWidth = SkScalarRoundToInt(this->width());
    328     desc.fHeight = SkScalarRoundToInt(this->height());
    329     desc.fConfig = kSkia8888_GrPixelConfig;
    330     desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
    331     desc.fSampleCnt = attachmentInfo.fSampleCount;
    332     desc.fStencilBits = attachmentInfo.fStencilBits;
    333     GrGLint buffer;
    334     GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
    335     desc.fRenderTargetHandle = buffer;
    336     return grContext->textureProvider()->wrapBackendRenderTarget(desc);
    337 }
    338 
    339 #endif
    340