blob: 82c1a43c0a5599475a7747ebfe5bce28e54d2296 [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();
reed4302ae92014-10-06 12:29:56 -070035 return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
reed@google.com5957f472012-10-01 20:31:56 +000036}
37
reed@android.comf2b98d62010-12-20 18:26:13 +000038void SkWindow::setMatrix(const SkMatrix& matrix) {
39 if (fMatrix != matrix) {
40 fMatrix = matrix;
halcanary96fcdcc2015-08-27 07:41:13 -070041 this->inval(nullptr);
reed@android.comf2b98d62010-12-20 18:26:13 +000042 }
43}
44
45void SkWindow::preConcat(const SkMatrix& matrix) {
46 SkMatrix m;
47 m.setConcat(fMatrix, matrix);
48 this->setMatrix(m);
49}
50
51void SkWindow::postConcat(const SkMatrix& matrix) {
52 SkMatrix m;
53 m.setConcat(matrix, fMatrix);
54 this->setMatrix(m);
55}
56
reeda34be682016-02-15 07:48:35 -080057void SkWindow::resize(const SkImageInfo& info) {
58 if (fBitmap.info() != info) {
59 fBitmap.allocPixels(info);
halcanary96fcdcc2015-08-27 07:41:13 -070060 this->inval(nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +000061 }
reeda34be682016-02-15 07:48:35 -080062 this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
63}
64
65void SkWindow::resize(int width, int height) {
66 this->resize(fBitmap.info().makeWH(width, height));
67}
68
69void SkWindow::setColorType(SkColorType ct, SkColorProfileType pt) {
70 const SkImageInfo& info = fBitmap.info();
71 this->resize(SkImageInfo::Make(info.width(), info.height(), ct, kPremul_SkAlphaType, pt));
reed@android.com8a1c16f2008-12-17 15:59:43 +000072}
73
tfarina@chromium.org658650c2014-01-25 18:45:45 +000074bool SkWindow::handleInval(const SkRect* localR) {
75 SkIRect ir;
reed@android.com8a1c16f2008-12-17 15:59:43 +000076
reed@android.comf2b98d62010-12-20 18:26:13 +000077 if (localR) {
78 SkRect devR;
79 SkMatrix inverse;
80 if (!fMatrix.invert(&inverse)) {
81 return false;
82 }
83 fMatrix.mapRect(&devR, *localR);
84 devR.round(&ir);
85 } else {
reed@google.comf9bb7a82011-03-01 15:15:13 +000086 ir.set(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000087 SkScalarRoundToInt(this->width()),
88 SkScalarRoundToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +000089 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000090 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
reed@android.com8a1c16f2008-12-17 15:59:43 +000091
rmistry@google.comd6176b02012-08-23 18:14:13 +000092 this->onHandleInval(ir);
93 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +000094}
95
reed@android.comf2b98d62010-12-20 18:26:13 +000096void SkWindow::forceInvalAll() {
reed@google.com261b8e22011-04-14 17:53:24 +000097 fDirtyRgn.setRect(0, 0,
reed@google.come1ca7052013-12-17 19:22:07 +000098 SkScalarCeilToInt(this->width()),
99 SkScalarCeilToInt(this->height()));
reed@android.comf2b98d62010-12-20 18:26:13 +0000100}
101
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102#ifdef SK_SIMULATE_FAILED_MALLOC
103extern bool gEnableControlledThrow;
104#endif
105
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000106bool SkWindow::update(SkIRect* updateArea) {
107 if (!fDirtyRgn.isEmpty()) {
reed0397e9f2014-09-18 11:29:01 -0700108 SkAutoTUnref<SkSurface> surface(this->createSurface());
109 SkCanvas* canvas = surface->getCanvas();
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000110
111 canvas->clipRegion(fDirtyRgn);
joshualitt030dc842015-06-12 12:51:44 -0700112 if (updateArea) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000113 *updateArea = fDirtyRgn.getBounds();
joshualitt030dc842015-06-12 12:51:44 -0700114 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000116 SkAutoCanvasRestore acr(canvas, true);
117 canvas->concat(fMatrix);
reed@android.comf2b98d62010-12-20 18:26:13 +0000118
rmistry@google.comd6176b02012-08-23 18:14:13 +0000119 // empty this now, so we can correctly record any inval calls that
120 // might be made during the draw call.
121 fDirtyRgn.setEmpty();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122
reed@android.com8a1c16f2008-12-17 15:59:43 +0000123#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000124 gEnableControlledThrow = true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125#endif
126#ifdef SK_BUILD_FOR_WIN32
rmistry@google.comd6176b02012-08-23 18:14:13 +0000127 //try {
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000128 this->draw(canvas);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000129 //}
130 //catch (...) {
131 //}
reed@android.com8a1c16f2008-12-17 15:59:43 +0000132#else
robertphillips@google.comce9dce02012-10-02 12:32:22 +0000133 this->draw(canvas);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000134#endif
135#ifdef SK_SIMULATE_FAILED_MALLOC
rmistry@google.comd6176b02012-08-23 18:14:13 +0000136 gEnableControlledThrow = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000138
rmistry@google.comd6176b02012-08-23 18:14:13 +0000139 return true;
140 }
141 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000142}
143
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000144bool SkWindow::handleChar(SkUnichar uni) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000145 if (this->onHandleChar(uni))
146 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000147
rmistry@google.comd6176b02012-08-23 18:14:13 +0000148 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700149 if (focus == nullptr)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000150 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000151
rmistry@google.comd6176b02012-08-23 18:14:13 +0000152 SkEvent evt(SK_EventType_Unichar);
153 evt.setFast32(uni);
154 return focus->doEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000155}
156
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000157bool SkWindow::handleKey(SkKey key) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000158 if (key == kNONE_SkKey)
159 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000160
rmistry@google.comd6176b02012-08-23 18:14:13 +0000161 if (this->onHandleKey(key))
162 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000163
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 // send an event to the focus-view
165 {
166 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700167 if (focus == nullptr)
rmistry@google.comd6176b02012-08-23 18:14:13 +0000168 focus = this;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000169
rmistry@google.comd6176b02012-08-23 18:14:13 +0000170 SkEvent evt(SK_EventType_Key);
171 evt.setFast32(key);
172 if (focus->doEvent(evt))
173 return true;
174 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000175
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000176 if (key == kUp_SkKey || key == kDown_SkKey) {
halcanary96fcdcc2015-08-27 07:41:13 -0700177 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr)
178 this->onSetFocusView(nullptr);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000179 return true;
180 }
181 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000182}
183
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000184bool SkWindow::handleKeyUp(SkKey key) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000185 if (key == kNONE_SkKey)
186 return false;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000187
reed@android.com8a1c16f2008-12-17 15:59:43 +0000188 if (this->onHandleKeyUp(key))
189 return true;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000190
reed@android.com8a1c16f2008-12-17 15:59:43 +0000191 //send an event to the focus-view
192 {
193 SkView* focus = this->getFocusView();
halcanary96fcdcc2015-08-27 07:41:13 -0700194 if (focus == nullptr)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000195 focus = this;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000196
reed@android.com8a1c16f2008-12-17 15:59:43 +0000197 //should this one be the same?
198 SkEvent evt(SK_EventType_KeyUp);
199 evt.setFast32(key);
200 if (focus->doEvent(evt))
201 return true;
202 }
203 return false;
204}
205
yangsu@google.com654d72f2011-08-01 17:27:33 +0000206void SkWindow::addMenu(SkOSMenu* menu) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000207 *fMenus.append() = menu;
208 this->onAddMenu(menu);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209}
210
reed@android.com0ae6b242008-12-23 16:49:54 +0000211void SkWindow::setTitle(const char title[]) {
halcanary96fcdcc2015-08-27 07:41:13 -0700212 if (nullptr == title) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000213 title = "";
reed@android.com0ae6b242008-12-23 16:49:54 +0000214 }
215 fTitle.set(title);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000216 this->onSetTitle(title);
217}
218
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000219bool SkWindow::onEvent(const SkEvent& evt) {
220 if (evt.isType(SK_EventDelayInval)) {
221 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
rmistry@google.comd6176b02012-08-23 18:14:13 +0000222 this->onHandleInval(iter.rect());
223 fWaitingOnInval = false;
224 return true;
225 }
226 return this->INHERITED::onEvent(evt);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000227}
228
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000229bool SkWindow::onGetFocusView(SkView** focus) const {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000230 if (focus)
231 *focus = fFocusView;
232 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233}
234
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000235bool SkWindow::onSetFocusView(SkView* focus) {
236 if (fFocusView != focus) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000237 if (fFocusView)
238 fFocusView->onFocusChange(false);
239 fFocusView = focus;
240 if (focus)
241 focus->onFocusChange(true);
242 }
243 return true;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000244}
245
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000246void SkWindow::onHandleInval(const SkIRect&) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000247}
248
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000249bool SkWindow::onHandleChar(SkUnichar) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000250 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251}
252
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000253bool SkWindow::onHandleKey(SkKey) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000254 return false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000255}
256
tfarina@chromium.org658650c2014-01-25 18:45:45 +0000257bool SkWindow::onHandleKeyUp(SkKey) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000258 return false;
259}
260
reed@google.com4d5c26d2013-01-08 16:17:50 +0000261bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
262 unsigned modifierKeys) {
263 return this->onDispatchClick(x, y, state, owner, modifierKeys);
mike@reedtribe.orgdd0cd342011-03-21 00:53:39 +0000264}
265
Scroggod3aed392011-06-22 13:26:56 +0000266bool SkWindow::onDispatchClick(int x, int y, Click::State state,
reed@google.com4d5c26d2013-01-08 16:17:50 +0000267 void* owner, unsigned modifierKeys) {
rmistry@google.comd6176b02012-08-23 18:14:13 +0000268 bool handled = false;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000269
Scroggod3aed392011-06-22 13:26:56 +0000270 // First, attempt to find an existing click with this owner.
271 int index = -1;
272 for (int i = 0; i < fClicks.count(); i++) {
273 if (owner == fClicks[i]->fOwner) {
274 index = i;
275 break;
276 }
277 }
278
rmistry@google.comd6176b02012-08-23 18:14:13 +0000279 switch (state) {
Scroggod3aed392011-06-22 13:26:56 +0000280 case Click::kDown_State: {
281 if (index != -1) {
282 delete fClicks[index];
283 fClicks.remove(index);
284 }
285 Click* click = this->findClickHandler(SkIntToScalar(x),
reed@google.com4d5c26d2013-01-08 16:17:50 +0000286 SkIntToScalar(y), modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000287
288 if (click) {
289 click->fOwner = owner;
290 *fClicks.append() = click;
reed@google.com4d5c26d2013-01-08 16:17:50 +0000291 SkView::DoClickDown(click, x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000292 handled = true;
293 }
294 break;
295 }
296 case Click::kMoved_State:
297 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000298 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000299 handled = true;
300 }
301 break;
302 case Click::kUp_State:
303 if (index != -1) {
reed@google.com4d5c26d2013-01-08 16:17:50 +0000304 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
Scroggod3aed392011-06-22 13:26:56 +0000305 delete fClicks[index];
306 fClicks.remove(index);
307 handled = true;
308 }
309 break;
310 default:
311 // Do nothing
312 break;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000313 }
314 return handled;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000315}
caryclarkc8fcafb2015-01-30 12:37:02 -0800316
317#if SK_SUPPORT_GPU
318
Brian Salomon8b3eca92015-10-09 16:54:48 -0400319#include "GrContext.h"
caryclarkc8fcafb2015-01-30 12:37:02 -0800320#include "gl/GrGLInterface.h"
321#include "gl/GrGLUtil.h"
322#include "SkGr.h"
323
324GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
325 const GrGLInterface* interface, GrContext* grContext) {
326 GrBackendRenderTargetDesc desc;
327 desc.fWidth = SkScalarRoundToInt(this->width());
328 desc.fHeight = SkScalarRoundToInt(this->height());
brianosman856cc172016-03-01 07:19:11 -0800329 // TODO: Query the actual framebuffer for sRGB capable. However, to
330 // preserve old (fake-linear) behavior, we don't do this. Instead, rely
331 // on the flag (currently driven via 'C' mode in SampleApp).
brianosmanc571c002016-03-17 13:01:26 -0700332 desc.fConfig = (info().profileType() == kSRGB_SkColorProfileType ||
brianosman856cc172016-03-01 07:19:11 -0800333 info().colorType() == kRGBA_F16_SkColorType)
brianosmanc571c002016-03-17 13:01:26 -0700334 ? kSRGBA_8888_GrPixelConfig // This may not be the right byte-order
brianosman856cc172016-03-01 07:19:11 -0800335 : kSkia8888_GrPixelConfig;
caryclarkc8fcafb2015-01-30 12:37:02 -0800336 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
337 desc.fSampleCnt = attachmentInfo.fSampleCount;
338 desc.fStencilBits = attachmentInfo.fStencilBits;
339 GrGLint buffer;
340 GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
341 desc.fRenderTargetHandle = buffer;
bsalomond309e7a2015-04-30 14:18:54 -0700342 return grContext->textureProvider()->wrapBackendRenderTarget(desc);
caryclarkc8fcafb2015-01-30 12:37:02 -0800343}
344
345#endif