blob: 99c2d30e8a6afe44c6fcb8c9950df1e046f9614a [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
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 */
reed@android.com8a1c16f2008-12-17 15:59:43 +00008#include "SkWindow.h"
9#include "SkCanvas.h"
reed@android.comf2b98d62010-12-20 18:26:13 +000010#include "SkDevice.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000011#include "SkOSMenu.h"
12#include "SkSystemEventTypes.h"
13#include "SkTime.h"
14
15#define SK_EventDelayInval "\xd" "n" "\xa" "l"
16
tfarina@chromium.org658650c2014-01-25 18:45:45 +000017SkWindow::SkWindow() : fFocusView(NULL) {
Scroggod3aed392011-06-22 13:26:56 +000018 fClicks.reset();
19 fWaitingOnInval = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +000020
21#ifdef SK_BUILD_FOR_WINCE
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000022 fColorType = kRGB_565_SkColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000023#else
commit-bot@chromium.org28fcae22014-04-11 17:15:40 +000024 fColorType = kN32_SkColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000025#endif
reed@android.comf2b98d62010-12-20 18:26:13 +000026
27 fMatrix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +000028}
29
tfarina@chromium.org658650c2014-01-25 18:45:45 +000030SkWindow::~SkWindow() {
Scroggod3aed392011-06-22 13:26:56 +000031 fClicks.deleteAll();
32 fMenus.deleteAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000033}
34
reed@google.com5957f472012-10-01 20:31:56 +000035SkCanvas* SkWindow::createCanvas() {
36 return new SkCanvas(this->getBitmap());
37}
38
reed@android.comf2b98d62010-12-20 18:26:13 +000039void SkWindow::setMatrix(const SkMatrix& matrix) {
40 if (fMatrix != matrix) {
41 fMatrix = matrix;
42 this->inval(NULL);
43 }
44}
45
46void SkWindow::preConcat(const SkMatrix& matrix) {
47 SkMatrix m;
48 m.setConcat(fMatrix, matrix);
49 this->setMatrix(m);
50}
51
52void SkWindow::postConcat(const SkMatrix& matrix) {
53 SkMatrix m;
54 m.setConcat(matrix, fMatrix);
55 this->setMatrix(m);
56}
57
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000058void SkWindow::setColorType(SkColorType ct) {
59 this->resize(fBitmap.width(), fBitmap.height(), ct);
reed@android.com8a1c16f2008-12-17 15:59:43 +000060}
61
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000062void SkWindow::resize(int width, int height, SkColorType ct) {
63 if (ct == kUnknown_SkColorType)
64 ct = fColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000065
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000066 if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
67 fColorType = ct;
68 fBitmap.allocPixels(SkImageInfo::Make(width, height,
69 ct, kPremul_SkAlphaType));
reed@android.com8a1c16f2008-12-17 15:59:43 +000070
rmistry@google.comd6176b02012-08-23 18:14:13 +000071 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
72 this->inval(NULL);
73 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000074}
75
tfarina@chromium.org658650c2014-01-25 18:45:45 +000076bool SkWindow::handleInval(const SkRect* localR) {
77 SkIRect ir;
reed@android.com8a1c16f2008-12-17 15:59:43 +000078
reed@android.comf2b98d62010-12-20 18:26:13 +000079 if (localR) {
80 SkRect devR;
81 SkMatrix inverse;
82 if (!fMatrix.invert(&inverse)) {
83 return false;
84 }
85 fMatrix.mapRect(&devR, *localR);
86 devR.round(&ir);
87 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +000088 ir.set(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000089 SkScalarRoundToInt(this->width()),
90 SkScalarRoundToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +000091 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000092 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +000093
rmistry@google.comd6176b02012-08-23 18:14:13 +000094 this->onHandleInval(ir);
95 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000096}
97
reed@android.comf2b98d62010-12-20 18:26:13 +000098void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +000099 fDirtyRgn.setRect(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +0000100 SkScalarCeilToInt(this->width()),
101 SkScalarCeilToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000102}
103
reed@android.com8a1c16f2008-12-17 15:59:43 +0000104#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000105 #include <windows.h>
106 #include <gx.h>
107 extern GXDisplayProperties gDisplayProps;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108#endif
109
110#ifdef SK_SIMULATE_FAILED_MALLOC
111extern bool gEnableControlledThrow;
112#endif
113
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000114bool SkWindow::update(SkIRect* updateArea) {
115 if (!fDirtyRgn.isEmpty()) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000116 SkBitmap bm = this->getBitmap();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117
118#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000119 char* buffer = (char*)GXBeginDraw();
120 SkASSERT(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000121
rmistry@google.comd6176b02012-08-23 18:14:13 +0000122 RECT rect;
123 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
124 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125
rmistry@google.comd6176b02012-08-23 18:14:13 +0000126 bm.setPixels(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127#endif
128
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000129 SkAutoTUnref<SkCanvas> canvas(this->createCanvas());
130
131 canvas->clipRegion(fDirtyRgn);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000132 if (updateArea)
133 *updateArea = fDirtyRgn.getBounds();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000135 SkAutoCanvasRestore acr(canvas, true);
136 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000137
rmistry@google.comd6176b02012-08-23 18:14:13 +0000138 // empty this now, so we can correctly record any inval calls that
139 // might be made during the draw call.
140 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000141
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000143 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144#endif
145#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000146 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000147 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 //}
149 //catch (...) {
150 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000152 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153#endif
154#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000155 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157
158#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000159 GXEndDraw();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160#endif
161
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162 return true;
163 }
164 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165}
166
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000167bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000168 if (this->onHandleChar(uni))
169 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171 SkView* focus = this->getFocusView();
172 if (focus == NULL)
173 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000174
rmistry@google.comd6176b02012-08-23 18:14:13 +0000175 SkEvent evt(SK_EventType_Unichar);
176 evt.setFast32(uni);
177 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000178}
179
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000180bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181 if (key == kNONE_SkKey)
182 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183
rmistry@google.comd6176b02012-08-23 18:14:13 +0000184 if (this->onHandleKey(key))
185 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186
rmistry@google.comd6176b02012-08-23 18:14:13 +0000187 // send an event to the focus-view
188 {
189 SkView* focus = this->getFocusView();
190 if (focus == NULL)
191 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192
rmistry@google.comd6176b02012-08-23 18:14:13 +0000193 SkEvent evt(SK_EventType_Key);
194 evt.setFast32(key);
195 if (focus->doEvent(evt))
196 return true;
197 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000199 if (key == kUp_SkKey || key == kDown_SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000200 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
201 this->onSetFocusView(NULL);
202 return true;
203 }
204 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000205}
206
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000207bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000208 if (key == kNONE_SkKey)
209 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000210
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211 if (this->onHandleKeyUp(key))
212 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000213
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 //send an event to the focus-view
215 {
216 SkView* focus = this->getFocusView();
217 if (focus == NULL)
218 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000219
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 //should this one be the same?
221 SkEvent evt(SK_EventType_KeyUp);
222 evt.setFast32(key);
223 if (focus->doEvent(evt))
224 return true;
225 }
226 return false;
227}
228
yangsu@google.com654d72f2011-08-01 17:27:33 +0000229void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000230 *fMenus.append() = menu;
231 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232}
233
reed@android.com0ae6b242008-12-23 16:49:54 +0000234void SkWindow::setTitle(const char title[]) {
235 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000237 }
238 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000239 this->onSetTitle(title);
240}
241
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000242bool SkWindow::onEvent(const SkEvent& evt) {
243 if (evt.isType(SK_EventDelayInval)) {
244 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000245 this->onHandleInval(iter.rect());
246 fWaitingOnInval = false;
247 return true;
248 }
249 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250}
251
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000252bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000253 if (focus)
254 *focus = fFocusView;
255 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256}
257
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000258bool SkWindow::onSetFocusView(SkView* focus) {
259 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000260 if (fFocusView)
261 fFocusView->onFocusChange(false);
262 fFocusView = focus;
263 if (focus)
264 focus->onFocusChange(true);
265 }
266 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000267}
268
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000269void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270}
271
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000272bool SkWindow::onHandleChar(SkUnichar) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000273 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274}
275
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000276bool SkWindow::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000277 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000278}
279
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000280bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000281 return false;
282}
283
reed@google.com4d5c26d2013-01-08 16:17:50 +0000284bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
285 unsigned modifierKeys) {
286 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000287}
288
Scroggod3aed392011-06-22 13:26:56 +0000289bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000290 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000291 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292
Scroggod3aed392011-06-22 13:26:56 +0000293 // First, attempt to find an existing click with this owner.
294 int index = -1;
295 for (int i = 0; i < fClicks.count(); i++) {
296 if (owner == fClicks[i]->fOwner) {
297 index = i;
298 break;
299 }
300 }
301
rmistry@google.comd6176b02012-08-23 18:14:13 +0000302 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000303 case Click::kDown_State: {
304 if (index != -1) {
305 delete fClicks[index];
306 fClicks.remove(index);
307 }
308 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000309 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000310
311 if (click) {
312 click->fOwner = owner;
313 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000314 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000315 handled = true;
316 }
317 break;
318 }
319 case Click::kMoved_State:
320 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000321 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000322 handled = true;
323 }
324 break;
325 case Click::kUp_State:
326 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000327 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000328 delete fClicks[index];
329 fClicks.remove(index);
330 handled = true;
331 }
332 break;
333 default:
334 // Do nothing
335 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000336 }
337 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000338}