blob: 481a1f9eb23ee490bd72f8bd8c340c30e3c23734 [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)
halcanary96fcdcc2015-08-27 07:41:13 -070019 , fFocusView(nullptr)
reed4302ae92014-10-06 12:29:56 -070020{
Scroggod3aed392011-06-22 13:26:56 +000021 fClicks.reset();
22 fWaitingOnInval = false;
reed@android.comf2b98d62010-12-20 18:26:13 +000023 fMatrix.reset();
reeda34be682016-02-15 07:48:35 -080024
25 fBitmap.allocN32Pixels(0, 0);
reed@android.com8a1c16f2008-12-17 15:59:43 +000026}
27
tfarina@chromium.org658650c2014-01-25 18:45:45 +000028SkWindow::~SkWindow() {
Scroggod3aed392011-06-22 13:26:56 +000029 fClicks.deleteAll();
30 fMenus.deleteAll();
reed@android.com8a1c16f2008-12-17 15:59:43 +000031}
32
reed0397e9f2014-09-18 11:29:01 -070033SkSurface* SkWindow::createSurface() {
34 const SkBitmap& bm = this->getBitmap();
reede8f30622016-03-23 18:59:25 -070035 return SkSurface::MakeRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(),
36 &fSurfaceProps).release();
reed@google.com5957f472012-10-01 20:31:56 +000037}
38
reed@android.comf2b98d62010-12-20 18:26:13 +000039void SkWindow::setMatrix(const SkMatrix& matrix) {
40 if (fMatrix != matrix) {
41 fMatrix = matrix;
halcanary96fcdcc2015-08-27 07:41:13 -070042 this->inval(nullptr);
reed@android.comf2b98d62010-12-20 18:26:13 +000043 }
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
reeda34be682016-02-15 07:48:35 -080058void SkWindow::resize(const SkImageInfo& info) {
59 if (fBitmap.info() != info) {
60 fBitmap.allocPixels(info);
halcanary96fcdcc2015-08-27 07:41:13 -070061 this->inval(nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +000062 }
reeda34be682016-02-15 07:48:35 -080063 this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
64}
65
66void SkWindow::resize(int width, int height) {
67 this->resize(fBitmap.info().makeWH(width, height));
68}
69
70void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) {
71 const SkImageInfo& info = fBitmap.info();
72 this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt));
reed@android.com8a1c16f2008-12-17 15:59:43 +000073}
74
tfarina@chromium.org658650c2014-01-25 18:45:45 +000075bool SkWindow::handleInval(const SkRect* localR) {
76 SkIRect ir;
reed@android.com8a1c16f2008-12-17 15:59:43 +000077
reed@android.comf2b98d62010-12-20 18:26:13 +000078 if (localR) {
79 SkRect devR;
80 SkMatrix inverse;
81 if (!fMatrix.invert(&inverse)) {
82 return false;
83 }
84 fMatrix.mapRect(&devR, *localR);
85 devR.round(&ir);
86 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +000087 ir.set(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000088 SkScalarRoundToInt(this->width()),
89 SkScalarRoundToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +000090 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000091 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +000092
rmistry@google.comd6176b02012-08-23 18:14:13 +000093 this->onHandleInval(ir);
94 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000095}
96
reed@android.comf2b98d62010-12-20 18:26:13 +000097void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +000098 fDirtyRgn.setRect(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000099 SkScalarCeilToInt(this->width()),
100 SkScalarCeilToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000101}
102
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103#ifdef SK_SIMULATE_FAILED_MALLOC
104extern bool gEnableControlledThrow;
105#endif
106
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000107bool SkWindow::update(SkIRect* updateArea) {
108 if (!fDirtyRgn.isEmpty()) {
reed0397e9f2014-09-18 11:29:01 -0700109 SkAutoTUnref<SkSurface> surface(this->createSurface());
110 SkCanvas* canvas = surface->getCanvas();
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000111
112 canvas->clipRegion(fDirtyRgn);
joshualitt030dc842015-06-12 12:51:44 -0700113 if (updateArea) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000114 *updateArea = fDirtyRgn.getBounds();
joshualitt030dc842015-06-12 12:51:44 -0700115 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000117 SkAutoCanvasRestore acr(canvas, true);
118 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000119
rmistry@google.comd6176b02012-08-23 18:14:13 +0000120 // empty this now, so we can correctly record any inval calls that
121 // might be made during the draw call.
122 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123
reed@android.com8a1c16f2008-12-17 15:59:43 +0000124#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000125 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126#endif
127#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000128 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000129 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000130 //}
131 //catch (...) {
132 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000134 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135#endif
136#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000137 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000139
rmistry@google.comd6176b02012-08-23 18:14:13 +0000140 return true;
141 }
142 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000143}
144
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000145bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000146 if (this->onHandleChar(uni))
147 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000148
rmistry@google.comd6176b02012-08-23 18:14:13 +0000149 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700150 if (focus == nullptr)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000151 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000152
rmistry@google.comd6176b02012-08-23 18:14:13 +0000153 SkEvent evt(SK_EventType_Unichar);
154 evt.setFast32(uni);
155 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000156}
157
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000158bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000159 if (key == kNONE_SkKey)
160 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000161
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162 if (this->onHandleKey(key))
163 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165 // send an event to the focus-view
166 {
167 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700168 if (focus == nullptr)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000169 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170
rmistry@google.comd6176b02012-08-23 18:14:13 +0000171 SkEvent evt(SK_EventType_Key);
172 evt.setFast32(key);
173 if (focus->doEvent(evt))
174 return true;
175 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000176
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000177 if (key == kUp_SkKey || key == kDown_SkKey) {
halcanary96fcdcc2015-08-27 07:41:13 -0700178 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr)
179 this->onSetFocusView(nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000180 return true;
181 }
182 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000183}
184
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000185bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186 if (key == kNONE_SkKey)
187 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000188
reed@android.com8a1c16f2008-12-17 15:59:43 +0000189 if (this->onHandleKeyUp(key))
190 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000191
reed@android.com8a1c16f2008-12-17 15:59:43 +0000192 //send an event to the focus-view
193 {
194 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700195 if (focus == nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000197
reed@android.com8a1c16f2008-12-17 15:59:43 +0000198 //should this one be the same?
199 SkEvent evt(SK_EventType_KeyUp);
200 evt.setFast32(key);
201 if (focus->doEvent(evt))
202 return true;
203 }
204 return false;
205}
206
yangsu@google.com654d72f2011-08-01 17:27:33 +0000207void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000208 *fMenus.append() = menu;
209 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210}
211
reed@android.com0ae6b242008-12-23 16:49:54 +0000212void SkWindow::setTitle(const char title[]) {
halcanary96fcdcc2015-08-27 07:41:13 -0700213 if (nullptr == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000215 }
216 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 this->onSetTitle(title);
218}
219
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000220bool SkWindow::onEvent(const SkEvent& evt) {
221 if (evt.isType(SK_EventDelayInval)) {
222 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000223 this->onHandleInval(iter.rect());
224 fWaitingOnInval = false;
225 return true;
226 }
227 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000228}
229
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000230bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000231 if (focus)
232 *focus = fFocusView;
233 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234}
235
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000236bool SkWindow::onSetFocusView(SkView* focus) {
237 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000238 if (fFocusView)
239 fFocusView->onFocusChange(false);
240 fFocusView = focus;
241 if (focus)
242 focus->onFocusChange(true);
243 }
244 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245}
246
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000247void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000248}
249
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000250bool SkWindow::onHandleChar(SkUnichar) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000251 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252}
253
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000254bool SkWindow::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000255 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000256}
257
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000258bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000259 return false;
260}
261
reed@google.com4d5c26d2013-01-08 16:17:50 +0000262bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
263 unsigned modifierKeys) {
264 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000265}
266
Scroggod3aed392011-06-22 13:26:56 +0000267bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000268 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000269 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270
Scroggod3aed392011-06-22 13:26:56 +0000271 // First, attempt to find an existing click with this owner.
272 int index = -1;
273 for (int i = 0; i < fClicks.count(); i++) {
274 if (owner == fClicks[i]->fOwner) {
275 index = i;
276 break;
277 }
278 }
279
rmistry@google.comd6176b02012-08-23 18:14:13 +0000280 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000281 case Click::kDown_State: {
282 if (index != -1) {
283 delete fClicks[index];
284 fClicks.remove(index);
285 }
286 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000287 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000288
289 if (click) {
290 click->fOwner = owner;
291 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000292 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000293 handled = true;
294 }
295 break;
296 }
297 case Click::kMoved_State:
298 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000299 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000300 handled = true;
301 }
302 break;
303 case Click::kUp_State:
304 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000305 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000306 delete fClicks[index];
307 fClicks.remove(index);
308 handled = true;
309 }
310 break;
311 default:
312 // Do nothing
313 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000314 }
315 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000316}
caryclarkc8fcafb2015-01-30 12:37:02 -0800317
318#if SK_SUPPORT_GPU
319
Brian Salomon8b3eca92015-10-09 16:54:48 -0400320#include "GrContext.h"
caryclarkc8fcafb2015-01-30 12:37:02 -0800321#include "gl/GrGLInterface.h"
322#include "gl/GrGLUtil.h"
323#include "SkGr.h"
324
325GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
326 const GrGLInterface* interface, GrContext* grContext) {
327 GrBackendRenderTargetDesc desc;
328 desc.fWidth = SkScalarRoundToInt(this->width());
329 desc.fHeight = SkScalarRoundToInt(this->height());
brianosman856cc172016-03-01 07:19:11 -0800330 // TODO: Query the actual framebuffer for sRGB capable. However, to
331 // preserve old (fake-linear) behavior, we don't do this. Instead, rely
332 // on the flag (currently driven via 'C' mode in SampleApp).
brianosmana6359362016-03-21 06:55:37 -0700333 //
334 // Also, we may not have real sRGB support (ANGLE, in particular), so check for
335 // that, and fall back to L32:
336 desc.fConfig = grContext->caps()->srgbSupport() &&
337 (info().profileType() == kSRGB_SkColorProfileType ||
brianosman856cc172016-03-01 07:19:11 -0800338 info().colorType() == kRGBA_F16_SkColorType)
brianosmana6359362016-03-21 06:55:37 -0700339 ? kSkiaGamma8888_GrPixelConfig
brianosman856cc172016-03-01 07:19:11 -0800340 : kSkia8888_GrPixelConfig;
caryclarkc8fcafb2015-01-30 12:37:02 -0800341 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
342 desc.fSampleCnt = attachmentInfo.fSampleCount;
343 desc.fStencilBits = attachmentInfo.fStencilBits;
344 GrGLint buffer;
345 GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
346 desc.fRenderTargetHandle = buffer;
bsalomond309e7a2015-04-30 14:18:54 -0700347 return grContext->textureProvider()->wrapBackendRenderTarget(desc);
caryclarkc8fcafb2015-01-30 12:37:02 -0800348}
349
350#endif