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