blob: 90ef2804e672cb956a6c1ac2e0e9e141e00335ea [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
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
reed0397e9f2014-09-18 11:29:01 -070035SkSurface* SkWindow::createSurface() {
36 const SkBitmap& bm = this->getBitmap();
37 return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes());
reed@google.com5957f472012-10-01 20:31:56 +000038}
39
reed@android.comf2b98d62010-12-20 18:26:13 +000040void SkWindow::setMatrix(const SkMatrix& matrix) {
41 if (fMatrix != matrix) {
42 fMatrix = matrix;
43 this->inval(NULL);
44 }
45}
46
47void SkWindow::preConcat(const SkMatrix& matrix) {
48 SkMatrix m;
49 m.setConcat(fMatrix, matrix);
50 this->setMatrix(m);
51}
52
53void SkWindow::postConcat(const SkMatrix& matrix) {
54 SkMatrix m;
55 m.setConcat(matrix, fMatrix);
56 this->setMatrix(m);
57}
58
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000059void SkWindow::setColorType(SkColorType ct) {
60 this->resize(fBitmap.width(), fBitmap.height(), ct);
reed@android.com8a1c16f2008-12-17 15:59:43 +000061}
62
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000063void SkWindow::resize(int width, int height, SkColorType ct) {
64 if (ct == kUnknown_SkColorType)
65 ct = fColorType;
reed@android.com8a1c16f2008-12-17 15:59:43 +000066
commit-bot@chromium.orge24ad232014-02-16 22:03:38 +000067 if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
68 fColorType = ct;
69 fBitmap.allocPixels(SkImageInfo::Make(width, height,
70 ct, kPremul_SkAlphaType));
reed@android.com8a1c16f2008-12-17 15:59:43 +000071
rmistry@google.comd6176b02012-08-23 18:14:13 +000072 this->setSize(SkIntToScalar(width), SkIntToScalar(height));
73 this->inval(NULL);
74 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000075}
76
tfarina@chromium.org658650c2014-01-25 18:45:45 +000077bool SkWindow::handleInval(const SkRect* localR) {
78 SkIRect ir;
reed@android.com8a1c16f2008-12-17 15:59:43 +000079
reed@android.comf2b98d62010-12-20 18:26:13 +000080 if (localR) {
81 SkRect devR;
82 SkMatrix inverse;
83 if (!fMatrix.invert(&inverse)) {
84 return false;
85 }
86 fMatrix.mapRect(&devR, *localR);
87 devR.round(&ir);
88 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +000089 ir.set(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000090 SkScalarRoundToInt(this->width()),
91 SkScalarRoundToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +000092 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000093 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +000094
rmistry@google.comd6176b02012-08-23 18:14:13 +000095 this->onHandleInval(ir);
96 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000097}
98
reed@android.comf2b98d62010-12-20 18:26:13 +000099void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +0000100 fDirtyRgn.setRect(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +0000101 SkScalarCeilToInt(this->width()),
102 SkScalarCeilToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000103}
104
reed@android.com8a1c16f2008-12-17 15:59:43 +0000105#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000106 #include <windows.h>
107 #include <gx.h>
108 extern GXDisplayProperties gDisplayProps;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000109#endif
110
111#ifdef SK_SIMULATE_FAILED_MALLOC
112extern bool gEnableControlledThrow;
113#endif
114
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000115bool SkWindow::update(SkIRect* updateArea) {
116 if (!fDirtyRgn.isEmpty()) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000117 SkBitmap bm = this->getBitmap();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000118
119#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000120 char* buffer = (char*)GXBeginDraw();
121 SkASSERT(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122
rmistry@google.comd6176b02012-08-23 18:14:13 +0000123 RECT rect;
124 GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
125 buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126
rmistry@google.comd6176b02012-08-23 18:14:13 +0000127 bm.setPixels(buffer);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000128#endif
129
reed0397e9f2014-09-18 11:29:01 -0700130 SkAutoTUnref<SkSurface> surface(this->createSurface());
131 SkCanvas* canvas = surface->getCanvas();
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000132
133 canvas->clipRegion(fDirtyRgn);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000134 if (updateArea)
135 *updateArea = fDirtyRgn.getBounds();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000136
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000137 SkAutoCanvasRestore acr(canvas, true);
138 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000139
rmistry@google.comd6176b02012-08-23 18:14:13 +0000140 // empty this now, so we can correctly record any inval calls that
141 // might be made during the draw call.
142 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143
reed@android.com8a1c16f2008-12-17 15:59:43 +0000144#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000145 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000146#endif
147#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000149 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000150 //}
151 //catch (...) {
152 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000153#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000154 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155#endif
156#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000157 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000158#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159
160#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000161 GXEndDraw();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162#endif
163
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 return true;
165 }
166 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000167}
168
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000169bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000170 if (this->onHandleChar(uni))
171 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000172
rmistry@google.comd6176b02012-08-23 18:14:13 +0000173 SkView* focus = this->getFocusView();
174 if (focus == NULL)
175 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176
rmistry@google.comd6176b02012-08-23 18:14:13 +0000177 SkEvent evt(SK_EventType_Unichar);
178 evt.setFast32(uni);
179 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180}
181
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000182bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000183 if (key == kNONE_SkKey)
184 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185
rmistry@google.comd6176b02012-08-23 18:14:13 +0000186 if (this->onHandleKey(key))
187 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188
rmistry@google.comd6176b02012-08-23 18:14:13 +0000189 // send an event to the focus-view
190 {
191 SkView* focus = this->getFocusView();
192 if (focus == NULL)
193 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194
rmistry@google.comd6176b02012-08-23 18:14:13 +0000195 SkEvent evt(SK_EventType_Key);
196 evt.setFast32(key);
197 if (focus->doEvent(evt))
198 return true;
199 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000201 if (key == kUp_SkKey || key == kDown_SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000202 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
203 this->onSetFocusView(NULL);
204 return true;
205 }
206 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207}
208
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000209bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210 if (key == kNONE_SkKey)
211 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000212
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 if (this->onHandleKeyUp(key))
214 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000215
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 //send an event to the focus-view
217 {
218 SkView* focus = this->getFocusView();
219 if (focus == NULL)
220 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000221
reed@android.com8a1c16f2008-12-17 15:59:43 +0000222 //should this one be the same?
223 SkEvent evt(SK_EventType_KeyUp);
224 evt.setFast32(key);
225 if (focus->doEvent(evt))
226 return true;
227 }
228 return false;
229}
230
yangsu@google.com654d72f2011-08-01 17:27:33 +0000231void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000232 *fMenus.append() = menu;
233 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234}
235
reed@android.com0ae6b242008-12-23 16:49:54 +0000236void SkWindow::setTitle(const char title[]) {
237 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000239 }
240 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 this->onSetTitle(title);
242}
243
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000244bool SkWindow::onEvent(const SkEvent& evt) {
245 if (evt.isType(SK_EventDelayInval)) {
246 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000247 this->onHandleInval(iter.rect());
248 fWaitingOnInval = false;
249 return true;
250 }
251 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252}
253
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000254bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000255 if (focus)
256 *focus = fFocusView;
257 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258}
259
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000260bool SkWindow::onSetFocusView(SkView* focus) {
261 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000262 if (fFocusView)
263 fFocusView->onFocusChange(false);
264 fFocusView = focus;
265 if (focus)
266 focus->onFocusChange(true);
267 }
268 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269}
270
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000271void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000272}
273
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000274bool SkWindow::onHandleChar(SkUnichar) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000275 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000276}
277
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000278bool SkWindow::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000279 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000280}
281
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000282bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000283 return false;
284}
285
reed@google.com4d5c26d2013-01-08 16:17:50 +0000286bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
287 unsigned modifierKeys) {
288 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000289}
290
Scroggod3aed392011-06-22 13:26:56 +0000291bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000292 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000293 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000294
Scroggod3aed392011-06-22 13:26:56 +0000295 // First, attempt to find an existing click with this owner.
296 int index = -1;
297 for (int i = 0; i < fClicks.count(); i++) {
298 if (owner == fClicks[i]->fOwner) {
299 index = i;
300 break;
301 }
302 }
303
rmistry@google.comd6176b02012-08-23 18:14:13 +0000304 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000305 case Click::kDown_State: {
306 if (index != -1) {
307 delete fClicks[index];
308 fClicks.remove(index);
309 }
310 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000311 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000312
313 if (click) {
314 click->fOwner = owner;
315 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000316 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000317 handled = true;
318 }
319 break;
320 }
321 case Click::kMoved_State:
322 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000323 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000324 handled = true;
325 }
326 break;
327 case Click::kUp_State:
328 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000329 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000330 delete fClicks[index];
331 fClicks.remove(index);
332 handled = true;
333 }
334 break;
335 default:
336 // Do nothing
337 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000338 }
339 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000340}