blob: 7870d06bfe969a2105e2d379a53aee0ec63db7ce [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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 */
reed0397e9f2014-09-18 11:29:01 -07007
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkWindow.h"
9#include "SkCanvas.h"
10#include "SkOSMenu.h"
reed0397e9f2014-09-18 11:29:01 -070011#include "SkSurface.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012#include "SkSystemEventTypes.h"
13#include "SkTime.h"
14
15#define SK_EventDelayInval "\xd" "n" "\xa" "l"
16
reed4302ae92014-10-06 12:29:56 -070017SkWindow::SkWindow()
18 : fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
19 , fFocusView(NULL)
20{
Scroggod3aed392011-06-22 13:26:56 +000021 fClicks.reset();
22 fWaitingOnInval = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000023
24#ifdef SK_BUILD_FOR_WINCE
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000025 fColorType = kRGB_565_SkColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000026#else
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000027 fColorType = kN32_SkColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000028#endif
reed@android.comf2b98d62010-12-20 18:26:13 +000029
30 fMatrix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
tfarina@chromium.org658650c2014-01-25 18:45:45 +000033SkWindow::~SkWindow() {
Scroggod3aed392011-06-22 13:26:56 +000034 fClicks.deleteAll();
35 fMenus.deleteAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000036}
37
reed0397e9f2014-09-18 11:29:01 -070038SkSurface* SkWindow::createSurface() {
39 const SkBitmap& bm = this->getBitmap();
reed4302ae92014-10-06 12:29:56 -070040 return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
reed@google.com5957f472012-10-01 20:31:56 +000041}
42
reed@android.comf2b98d62010-12-20 18:26:13 +000043void SkWindow::setMatrix(const SkMatrix& matrix) {
44 if (fMatrix != matrix) {
45 fMatrix = matrix;
46 this->inval(NULL);
47 }
48}
49
50void SkWindow::preConcat(const SkMatrix& matrix) {
51 SkMatrix m;
52 m.setConcat(fMatrix, matrix);
53 this->setMatrix(m);
54}
55
56void SkWindow::postConcat(const SkMatrix& matrix) {
57 SkMatrix m;
58 m.setConcat(matrix, fMatrix);
59 this->setMatrix(m);
60}
61
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000062void SkWindow::setColorType(SkColorType ct) {
63 this->resize(fBitmap.width(), fBitmap.height(), ct);
reed@android.com8a1c16f2008-12-17 15:59:43 +000064}
65
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000066void SkWindow::resize(int width, int height, SkColorType ct) {
67 if (ct == kUnknown_SkColorType)
68 ct = fColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000069
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000070 if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
71 fColorType = ct;
72 fBitmap.allocPixels(SkImageInfo::Make(width, height,
73 ct, kPremul_SkAlphaType));
reed@android.com8a1c16f2008-12-17 15:59:43 +000074
rmistry@google.comd6176b02012-08-23 18:14:13 +000075 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
76 this->inval(NULL);
77 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000078}
79
tfarina@chromium.org658650c2014-01-25 18:45:45 +000080bool SkWindow::handleInval(const SkRect* localR) {
81 SkIRect ir;
reed@android.com8a1c16f2008-12-17 15:59:43 +000082
reed@android.comf2b98d62010-12-20 18:26:13 +000083 if (localR) {
84 SkRect devR;
85 SkMatrix inverse;
86 if (!fMatrix.invert(&inverse)) {
87 return false;
88 }
89 fMatrix.mapRect(&devR, *localR);
90 devR.round(&ir);
91 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +000092 ir.set(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000093 SkScalarRoundToInt(this->width()),
94 SkScalarRoundToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +000095 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000096 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +000097
rmistry@google.comd6176b02012-08-23 18:14:13 +000098 this->onHandleInval(ir);
99 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100}
101
reed@android.comf2b98d62010-12-20 18:26:13 +0000102void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +0000103 fDirtyRgn.setRect(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +0000104 SkScalarCeilToInt(this->width()),
105 SkScalarCeilToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000106}
107
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000109 #include <windows.h>
110 #include <gx.h>
111 extern GXDisplayProperties gDisplayProps;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000112#endif
113
114#ifdef SK_SIMULATE_FAILED_MALLOC
115extern bool gEnableControlledThrow;
116#endif
117
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000118bool SkWindow::update(SkIRect* updateArea) {
119 if (!fDirtyRgn.isEmpty()) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000120 SkBitmap bm = this->getBitmap();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121
122#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000123 char* buffer = (char*)GXBeginDraw();
124 SkASSERT(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125
rmistry@google.comd6176b02012-08-23 18:14:13 +0000126 RECT rect;
127 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
128 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129
rmistry@google.comd6176b02012-08-23 18:14:13 +0000130 bm.setPixels(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000131#endif
132
reed0397e9f2014-09-18 11:29:01 -0700133 SkAutoTUnref<SkSurface> surface(this->createSurface());
134 SkCanvas* canvas = surface->getCanvas();
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000135
136 canvas->clipRegion(fDirtyRgn);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000137 if (updateArea)
138 *updateArea = fDirtyRgn.getBounds();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000140 SkAutoCanvasRestore acr(canvas, true);
141 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000142
rmistry@google.comd6176b02012-08-23 18:14:13 +0000143 // empty this now, so we can correctly record any inval calls that
144 // might be made during the draw call.
145 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000149#endif
150#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000152 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000153 //}
154 //catch (...) {
155 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000157 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158#endif
159#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000160 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162
163#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 GXEndDraw();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165#endif
166
rmistry@google.comd6176b02012-08-23 18:14:13 +0000167 return true;
168 }
169 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170}
171
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000172bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173 if (this->onHandleChar(uni))
174 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175
rmistry@google.comd6176b02012-08-23 18:14:13 +0000176 SkView* focus = this->getFocusView();
177 if (focus == NULL)
178 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000179
rmistry@google.comd6176b02012-08-23 18:14:13 +0000180 SkEvent evt(SK_EventType_Unichar);
181 evt.setFast32(uni);
182 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183}
184
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000185bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000186 if (key == kNONE_SkKey)
187 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188
rmistry@google.comd6176b02012-08-23 18:14:13 +0000189 if (this->onHandleKey(key))
190 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191
rmistry@google.comd6176b02012-08-23 18:14:13 +0000192 // send an event to the focus-view
193 {
194 SkView* focus = this->getFocusView();
195 if (focus == NULL)
196 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197
rmistry@google.comd6176b02012-08-23 18:14:13 +0000198 SkEvent evt(SK_EventType_Key);
199 evt.setFast32(key);
200 if (focus->doEvent(evt))
201 return true;
202 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000203
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000204 if (key == kUp_SkKey || key == kDown_SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000205 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
206 this->onSetFocusView(NULL);
207 return true;
208 }
209 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210}
211
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000212bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 if (key == kNONE_SkKey)
214 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000215
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 if (this->onHandleKeyUp(key))
217 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000218
reed@android.com8a1c16f2008-12-17 15:59:43 +0000219 //send an event to the focus-view
220 {
221 SkView* focus = this->getFocusView();
222 if (focus == NULL)
223 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000224
reed@android.com8a1c16f2008-12-17 15:59:43 +0000225 //should this one be the same?
226 SkEvent evt(SK_EventType_KeyUp);
227 evt.setFast32(key);
228 if (focus->doEvent(evt))
229 return true;
230 }
231 return false;
232}
233
yangsu@google.com654d72f2011-08-01 17:27:33 +0000234void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000235 *fMenus.append() = menu;
236 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237}
238
reed@android.com0ae6b242008-12-23 16:49:54 +0000239void SkWindow::setTitle(const char title[]) {
240 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000242 }
243 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244 this->onSetTitle(title);
245}
246
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000247bool SkWindow::onEvent(const SkEvent& evt) {
248 if (evt.isType(SK_EventDelayInval)) {
249 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000250 this->onHandleInval(iter.rect());
251 fWaitingOnInval = false;
252 return true;
253 }
254 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255}
256
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000257bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000258 if (focus)
259 *focus = fFocusView;
260 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000261}
262
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000263bool SkWindow::onSetFocusView(SkView* focus) {
264 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000265 if (fFocusView)
266 fFocusView->onFocusChange(false);
267 fFocusView = focus;
268 if (focus)
269 focus->onFocusChange(true);
270 }
271 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000272}
273
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000274void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275}
276
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000277bool SkWindow::onHandleChar(SkUnichar) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000278 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000279}
280
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000281bool SkWindow::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000282 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000283}
284
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000285bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000286 return false;
287}
288
reed@google.com4d5c26d2013-01-08 16:17:50 +0000289bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
290 unsigned modifierKeys) {
291 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000292}
293
Scroggod3aed392011-06-22 13:26:56 +0000294bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000295 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000296 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000297
Scroggod3aed392011-06-22 13:26:56 +0000298 // First, attempt to find an existing click with this owner.
299 int index = -1;
300 for (int i = 0; i < fClicks.count(); i++) {
301 if (owner == fClicks[i]->fOwner) {
302 index = i;
303 break;
304 }
305 }
306
rmistry@google.comd6176b02012-08-23 18:14:13 +0000307 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000308 case Click::kDown_State: {
309 if (index != -1) {
310 delete fClicks[index];
311 fClicks.remove(index);
312 }
313 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000314 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000315
316 if (click) {
317 click->fOwner = owner;
318 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000319 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000320 handled = true;
321 }
322 break;
323 }
324 case Click::kMoved_State:
325 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000326 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000327 handled = true;
328 }
329 break;
330 case Click::kUp_State:
331 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000332 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000333 delete fClicks[index];
334 fClicks.remove(index);
335 handled = true;
336 }
337 break;
338 default:
339 // Do nothing
340 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000341 }
342 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000343}