blob: 7ab729e1d28877b97b61baf13c0ad11435d8f9ae [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()) {
joshualitt030dc842015-06-12 12:51:44 -0700120#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000121 SkBitmap bm = this->getBitmap();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122
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);
joshualitt030dc842015-06-12 12:51:44 -0700137 if (updateArea) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000138 *updateArea = fDirtyRgn.getBounds();
joshualitt030dc842015-06-12 12:51:44 -0700139 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000140
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000141 SkAutoCanvasRestore acr(canvas, true);
142 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000143
rmistry@google.comd6176b02012-08-23 18:14:13 +0000144 // empty this now, so we can correctly record any inval calls that
145 // might be made during the draw call.
146 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000149 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000150#endif
151#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000152 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000153 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000154 //}
155 //catch (...) {
156 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000157#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000158 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000159#endif
160#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000161 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163
164#if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165 GXEndDraw();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000166#endif
167
rmistry@google.comd6176b02012-08-23 18:14:13 +0000168 return true;
169 }
170 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000171}
172
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000173bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000174 if (this->onHandleChar(uni))
175 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176
rmistry@google.comd6176b02012-08-23 18:14:13 +0000177 SkView* focus = this->getFocusView();
178 if (focus == NULL)
179 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000180
rmistry@google.comd6176b02012-08-23 18:14:13 +0000181 SkEvent evt(SK_EventType_Unichar);
182 evt.setFast32(uni);
183 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000184}
185
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000186bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000187 if (key == kNONE_SkKey)
188 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189
rmistry@google.comd6176b02012-08-23 18:14:13 +0000190 if (this->onHandleKey(key))
191 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192
rmistry@google.comd6176b02012-08-23 18:14:13 +0000193 // send an event to the focus-view
194 {
195 SkView* focus = this->getFocusView();
196 if (focus == NULL)
197 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198
rmistry@google.comd6176b02012-08-23 18:14:13 +0000199 SkEvent evt(SK_EventType_Key);
200 evt.setFast32(key);
201 if (focus->doEvent(evt))
202 return true;
203 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000204
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000205 if (key == kUp_SkKey || key == kDown_SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000206 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
207 this->onSetFocusView(NULL);
208 return true;
209 }
210 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000211}
212
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000213bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 if (key == kNONE_SkKey)
215 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000216
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 if (this->onHandleKeyUp(key))
218 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000219
reed@android.com8a1c16f2008-12-17 15:59:43 +0000220 //send an event to the focus-view
221 {
222 SkView* focus = this->getFocusView();
223 if (focus == NULL)
224 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000225
reed@android.com8a1c16f2008-12-17 15:59:43 +0000226 //should this one be the same?
227 SkEvent evt(SK_EventType_KeyUp);
228 evt.setFast32(key);
229 if (focus->doEvent(evt))
230 return true;
231 }
232 return false;
233}
234
yangsu@google.com654d72f2011-08-01 17:27:33 +0000235void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000236 *fMenus.append() = menu;
237 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238}
239
reed@android.com0ae6b242008-12-23 16:49:54 +0000240void SkWindow::setTitle(const char title[]) {
241 if (NULL == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000242 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000243 }
244 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245 this->onSetTitle(title);
246}
247
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000248bool SkWindow::onEvent(const SkEvent& evt) {
249 if (evt.isType(SK_EventDelayInval)) {
250 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000251 this->onHandleInval(iter.rect());
252 fWaitingOnInval = false;
253 return true;
254 }
255 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256}
257
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000258bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000259 if (focus)
260 *focus = fFocusView;
261 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262}
263
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000264bool SkWindow::onSetFocusView(SkView* focus) {
265 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000266 if (fFocusView)
267 fFocusView->onFocusChange(false);
268 fFocusView = focus;
269 if (focus)
270 focus->onFocusChange(true);
271 }
272 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000273}
274
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000275void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000276}
277
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000278bool SkWindow::onHandleChar(SkUnichar) {
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::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000283 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000284}
285
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000286bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287 return false;
288}
289
reed@google.com4d5c26d2013-01-08 16:17:50 +0000290bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
291 unsigned modifierKeys) {
292 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000293}
294
Scroggod3aed392011-06-22 13:26:56 +0000295bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000296 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000297 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000298
Scroggod3aed392011-06-22 13:26:56 +0000299 // First, attempt to find an existing click with this owner.
300 int index = -1;
301 for (int i = 0; i < fClicks.count(); i++) {
302 if (owner == fClicks[i]->fOwner) {
303 index = i;
304 break;
305 }
306 }
307
rmistry@google.comd6176b02012-08-23 18:14:13 +0000308 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000309 case Click::kDown_State: {
310 if (index != -1) {
311 delete fClicks[index];
312 fClicks.remove(index);
313 }
314 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000315 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000316
317 if (click) {
318 click->fOwner = owner;
319 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000320 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000321 handled = true;
322 }
323 break;
324 }
325 case Click::kMoved_State:
326 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000327 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000328 handled = true;
329 }
330 break;
331 case Click::kUp_State:
332 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000333 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000334 delete fClicks[index];
335 fClicks.remove(index);
336 handled = true;
337 }
338 break;
339 default:
340 // Do nothing
341 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000342 }
343 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000344}
caryclarkc8fcafb2015-01-30 12:37:02 -0800345
346#if SK_SUPPORT_GPU
347
348#include "gl/GrGLInterface.h"
349#include "gl/GrGLUtil.h"
350#include "SkGr.h"
351
352GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
353 const GrGLInterface* interface, GrContext* grContext) {
354 GrBackendRenderTargetDesc desc;
355 desc.fWidth = SkScalarRoundToInt(this->width());
356 desc.fHeight = SkScalarRoundToInt(this->height());
357 desc.fConfig = kSkia8888_GrPixelConfig;
358 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
359 desc.fSampleCnt = attachmentInfo.fSampleCount;
360 desc.fStencilBits = attachmentInfo.fStencilBits;
361 GrGLint buffer;
362 GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
363 desc.fRenderTargetHandle = buffer;
bsalomond309e7a2015-04-30 14:18:54 -0700364 return grContext->textureProvider()->wrapBackendRenderTarget(desc);
caryclarkc8fcafb2015-01-30 12:37:02 -0800365}
366
367#endif