1 /*
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 */
7
8 #include "SkWindow.h"
9 #include "SkCanvas.h"
10 #include "SkOSMenu.h"
11 #include "SkSurface.h"
12 #include "SkSystemEventTypes.h"
13 #include "SkTime.h"
14
15 #define SK_EventDelayInval "\xd" "n" "\xa" "l"
16
SkWindow()17 SkWindow::SkWindow()
18 : fSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType)
19 , fFocusView(nullptr)
20 {
21 fClicks.reset();
22 fWaitingOnInval = false;
23 fMatrix.reset();
24
25 fBitmap.allocN32Pixels(0, 0);
26 }
27
~SkWindow()28 SkWindow::~SkWindow() {
29 fClicks.deleteAll();
30 fMenus.deleteAll();
31 }
32
createSurface()33 SkSurface* SkWindow::createSurface() {
34 const SkBitmap& bm = this->getBitmap();
35 return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
36 }
37
setMatrix(const SkMatrix & matrix)38 void SkWindow::setMatrix(const SkMatrix& matrix) {
39 if (fMatrix != matrix) {
40 fMatrix = matrix;
41 this->inval(nullptr);
42 }
43 }
44
preConcat(const SkMatrix & matrix)45 void SkWindow::preConcat(const SkMatrix& matrix) {
46 SkMatrix m;
47 m.setConcat(fMatrix, matrix);
48 this->setMatrix(m);
49 }
50
postConcat(const SkMatrix & matrix)51 void SkWindow::postConcat(const SkMatrix& matrix) {
52 SkMatrix m;
53 m.setConcat(matrix, fMatrix);
54 this->setMatrix(m);
55 }
56
resize(const SkImageInfo & info)57 void SkWindow::resize(const SkImageInfo& info) {
58 if (fBitmap.info() != info) {
59 fBitmap.allocPixels(info);
60 this->inval(nullptr);
61 }
62 this->setSize(SkIntToScalar(fBitmap.width()), SkIntToScalar(fBitmap.height()));
63 }
64
resize(int width,int height)65 void SkWindow::resize(int width, int height) {
66 this->resize(fBitmap.info().makeWH(width, height));
67 }
68
setColorType(SkColorType ct,SkColorProfileType pt)69 void 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));
72 }
73
handleInval(const SkRect * localR)74 bool SkWindow::handleInval(const SkRect* localR) {
75 SkIRect ir;
76
77 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 {
86 ir.set(0, 0,
87 SkScalarRoundToInt(this->width()),
88 SkScalarRoundToInt(this->height()));
89 }
90 fDirtyRgn.op(ir, SkRegion::kUnion_Op);
91
92 this->onHandleInval(ir);
93 return true;
94 }
95
forceInvalAll()96 void SkWindow::forceInvalAll() {
97 fDirtyRgn.setRect(0, 0,
98 SkScalarCeilToInt(this->width()),
99 SkScalarCeilToInt(this->height()));
100 }
101
102 #ifdef SK_SIMULATE_FAILED_MALLOC
103 extern bool gEnableControlledThrow;
104 #endif
105
update(SkIRect * updateArea)106 bool SkWindow::update(SkIRect* updateArea) {
107 if (!fDirtyRgn.isEmpty()) {
108 SkAutoTUnref<SkSurface> surface(this->createSurface());
109 SkCanvas* canvas = surface->getCanvas();
110
111 canvas->clipRegion(fDirtyRgn);
112 if (updateArea) {
113 *updateArea = fDirtyRgn.getBounds();
114 }
115
116 SkAutoCanvasRestore acr(canvas, true);
117 canvas->concat(fMatrix);
118
119 // empty this now, so we can correctly record any inval calls that
120 // might be made during the draw call.
121 fDirtyRgn.setEmpty();
122
123 #ifdef SK_SIMULATE_FAILED_MALLOC
124 gEnableControlledThrow = true;
125 #endif
126 #ifdef SK_BUILD_FOR_WIN32
127 //try {
128 this->draw(canvas);
129 //}
130 //catch (...) {
131 //}
132 #else
133 this->draw(canvas);
134 #endif
135 #ifdef SK_SIMULATE_FAILED_MALLOC
136 gEnableControlledThrow = false;
137 #endif
138
139 return true;
140 }
141 return false;
142 }
143
handleChar(SkUnichar uni)144 bool SkWindow::handleChar(SkUnichar uni) {
145 if (this->onHandleChar(uni))
146 return true;
147
148 SkView* focus = this->getFocusView();
149 if (focus == nullptr)
150 focus = this;
151
152 SkEvent evt(SK_EventType_Unichar);
153 evt.setFast32(uni);
154 return focus->doEvent(evt);
155 }
156
handleKey(SkKey key)157 bool SkWindow::handleKey(SkKey key) {
158 if (key == kNONE_SkKey)
159 return false;
160
161 if (this->onHandleKey(key))
162 return true;
163
164 // send an event to the focus-view
165 {
166 SkView* focus = this->getFocusView();
167 if (focus == nullptr)
168 focus = this;
169
170 SkEvent evt(SK_EventType_Key);
171 evt.setFast32(key);
172 if (focus->doEvent(evt))
173 return true;
174 }
175
176 if (key == kUp_SkKey || key == kDown_SkKey) {
177 if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == nullptr)
178 this->onSetFocusView(nullptr);
179 return true;
180 }
181 return false;
182 }
183
handleKeyUp(SkKey key)184 bool SkWindow::handleKeyUp(SkKey key) {
185 if (key == kNONE_SkKey)
186 return false;
187
188 if (this->onHandleKeyUp(key))
189 return true;
190
191 //send an event to the focus-view
192 {
193 SkView* focus = this->getFocusView();
194 if (focus == nullptr)
195 focus = this;
196
197 //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
addMenu(SkOSMenu * menu)206 void SkWindow::addMenu(SkOSMenu* menu) {
207 *fMenus.append() = menu;
208 this->onAddMenu(menu);
209 }
210
setTitle(const char title[])211 void SkWindow::setTitle(const char title[]) {
212 if (nullptr == title) {
213 title = "";
214 }
215 fTitle.set(title);
216 this->onSetTitle(title);
217 }
218
onEvent(const SkEvent & evt)219 bool SkWindow::onEvent(const SkEvent& evt) {
220 if (evt.isType(SK_EventDelayInval)) {
221 for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
222 this->onHandleInval(iter.rect());
223 fWaitingOnInval = false;
224 return true;
225 }
226 return this->INHERITED::onEvent(evt);
227 }
228
onGetFocusView(SkView ** focus) const229 bool SkWindow::onGetFocusView(SkView** focus) const {
230 if (focus)
231 *focus = fFocusView;
232 return true;
233 }
234
onSetFocusView(SkView * focus)235 bool SkWindow::onSetFocusView(SkView* focus) {
236 if (fFocusView != focus) {
237 if (fFocusView)
238 fFocusView->onFocusChange(false);
239 fFocusView = focus;
240 if (focus)
241 focus->onFocusChange(true);
242 }
243 return true;
244 }
245
onHandleInval(const SkIRect &)246 void SkWindow::onHandleInval(const SkIRect&) {
247 }
248
onHandleChar(SkUnichar)249 bool SkWindow::onHandleChar(SkUnichar) {
250 return false;
251 }
252
onHandleKey(SkKey)253 bool SkWindow::onHandleKey(SkKey) {
254 return false;
255 }
256
onHandleKeyUp(SkKey)257 bool SkWindow::onHandleKeyUp(SkKey) {
258 return false;
259 }
260
handleClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)261 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
262 unsigned modifierKeys) {
263 return this->onDispatchClick(x, y, state, owner, modifierKeys);
264 }
265
onDispatchClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)266 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
267 void* owner, unsigned modifierKeys) {
268 bool handled = false;
269
270 // 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
279 switch (state) {
280 case Click::kDown_State: {
281 if (index != -1) {
282 delete fClicks[index];
283 fClicks.remove(index);
284 }
285 Click* click = this->findClickHandler(SkIntToScalar(x),
286 SkIntToScalar(y), modifierKeys);
287
288 if (click) {
289 click->fOwner = owner;
290 *fClicks.append() = click;
291 SkView::DoClickDown(click, x, y, modifierKeys);
292 handled = true;
293 }
294 break;
295 }
296 case Click::kMoved_State:
297 if (index != -1) {
298 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
299 handled = true;
300 }
301 break;
302 case Click::kUp_State:
303 if (index != -1) {
304 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
305 delete fClicks[index];
306 fClicks.remove(index);
307 handled = true;
308 }
309 break;
310 default:
311 // Do nothing
312 break;
313 }
314 return handled;
315 }
316
317 #if SK_SUPPORT_GPU
318
319 #include "GrContext.h"
320 #include "gl/GrGLInterface.h"
321 #include "gl/GrGLUtil.h"
322 #include "SkGr.h"
323
renderTarget(const AttachmentInfo & attachmentInfo,const GrGLInterface * interface,GrContext * grContext)324 GrRenderTarget* 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());
329 desc.fConfig = kSkia8888_GrPixelConfig;
330 desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
331 desc.fSampleCnt = attachmentInfo.fSampleCount;
332 desc.fStencilBits = attachmentInfo.fStencilBits;
333 GrGLint buffer;
334 GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
335 desc.fRenderTargetHandle = buffer;
336 return grContext->textureProvider()->wrapBackendRenderTarget(desc);
337 }
338
339 #endif
340