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(NULL)
20 {
21     fClicks.reset();
22     fWaitingOnInval = false;
23 
24 #ifdef SK_BUILD_FOR_WINCE
25     fColorType = kRGB_565_SkColorType;
26 #else
27     fColorType = kN32_SkColorType;
28 #endif
29 
30     fMatrix.reset();
31 }
32 
~SkWindow()33 SkWindow::~SkWindow() {
34     fClicks.deleteAll();
35     fMenus.deleteAll();
36 }
37 
createSurface()38 SkSurface* SkWindow::createSurface() {
39     const SkBitmap& bm = this->getBitmap();
40     return SkSurface::NewRasterDirect(bm.info(), bm.getPixels(), bm.rowBytes(), &fSurfaceProps);
41 }
42 
setMatrix(const SkMatrix & matrix)43 void SkWindow::setMatrix(const SkMatrix& matrix) {
44     if (fMatrix != matrix) {
45         fMatrix = matrix;
46         this->inval(NULL);
47     }
48 }
49 
preConcat(const SkMatrix & matrix)50 void SkWindow::preConcat(const SkMatrix& matrix) {
51     SkMatrix m;
52     m.setConcat(fMatrix, matrix);
53     this->setMatrix(m);
54 }
55 
postConcat(const SkMatrix & matrix)56 void SkWindow::postConcat(const SkMatrix& matrix) {
57     SkMatrix m;
58     m.setConcat(matrix, fMatrix);
59     this->setMatrix(m);
60 }
61 
setColorType(SkColorType ct)62 void SkWindow::setColorType(SkColorType ct) {
63     this->resize(fBitmap.width(), fBitmap.height(), ct);
64 }
65 
resize(int width,int height,SkColorType ct)66 void SkWindow::resize(int width, int height, SkColorType ct) {
67     if (ct == kUnknown_SkColorType)
68         ct = fColorType;
69 
70     if (width != fBitmap.width() || height != fBitmap.height() || ct != fColorType) {
71         fColorType = ct;
72         fBitmap.allocPixels(SkImageInfo::Make(width, height,
73                                               ct, kPremul_SkAlphaType));
74 
75         this->setSize(SkIntToScalar(width), SkIntToScalar(height));
76         this->inval(NULL);
77     }
78 }
79 
handleInval(const SkRect * localR)80 bool SkWindow::handleInval(const SkRect* localR) {
81     SkIRect ir;
82 
83     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 {
92         ir.set(0, 0,
93                SkScalarRoundToInt(this->width()),
94                SkScalarRoundToInt(this->height()));
95     }
96     fDirtyRgn.op(ir, SkRegion::kUnion_Op);
97 
98     this->onHandleInval(ir);
99     return true;
100 }
101 
forceInvalAll()102 void SkWindow::forceInvalAll() {
103     fDirtyRgn.setRect(0, 0,
104                       SkScalarCeilToInt(this->width()),
105                       SkScalarCeilToInt(this->height()));
106 }
107 
108 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
109     #include <windows.h>
110     #include <gx.h>
111     extern GXDisplayProperties gDisplayProps;
112 #endif
113 
114 #ifdef SK_SIMULATE_FAILED_MALLOC
115 extern bool gEnableControlledThrow;
116 #endif
117 
update(SkIRect * updateArea)118 bool SkWindow::update(SkIRect* updateArea) {
119     if (!fDirtyRgn.isEmpty()) {
120         SkBitmap bm = this->getBitmap();
121 
122 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
123         char* buffer = (char*)GXBeginDraw();
124         SkASSERT(buffer);
125 
126         RECT    rect;
127         GetWindowRect((HWND)((SkOSWindow*)this)->getHWND(), &rect);
128         buffer += rect.top * gDisplayProps.cbyPitch + rect.left * gDisplayProps.cbxPitch;
129 
130         bm.setPixels(buffer);
131 #endif
132 
133         SkAutoTUnref<SkSurface> surface(this->createSurface());
134         SkCanvas* canvas = surface->getCanvas();
135 
136         canvas->clipRegion(fDirtyRgn);
137         if (updateArea)
138             *updateArea = fDirtyRgn.getBounds();
139 
140         SkAutoCanvasRestore acr(canvas, true);
141         canvas->concat(fMatrix);
142 
143         // empty this now, so we can correctly record any inval calls that
144         // might be made during the draw call.
145         fDirtyRgn.setEmpty();
146 
147 #ifdef SK_SIMULATE_FAILED_MALLOC
148         gEnableControlledThrow = true;
149 #endif
150 #ifdef SK_BUILD_FOR_WIN32
151         //try {
152             this->draw(canvas);
153         //}
154         //catch (...) {
155         //}
156 #else
157         this->draw(canvas);
158 #endif
159 #ifdef SK_SIMULATE_FAILED_MALLOC
160         gEnableControlledThrow = false;
161 #endif
162 
163 #if defined(SK_BUILD_FOR_WINCE) && defined(USE_GX_SCREEN)
164         GXEndDraw();
165 #endif
166 
167         return true;
168     }
169     return false;
170 }
171 
handleChar(SkUnichar uni)172 bool SkWindow::handleChar(SkUnichar uni) {
173     if (this->onHandleChar(uni))
174         return true;
175 
176     SkView* focus = this->getFocusView();
177     if (focus == NULL)
178         focus = this;
179 
180     SkEvent evt(SK_EventType_Unichar);
181     evt.setFast32(uni);
182     return focus->doEvent(evt);
183 }
184 
handleKey(SkKey key)185 bool SkWindow::handleKey(SkKey key) {
186     if (key == kNONE_SkKey)
187         return false;
188 
189     if (this->onHandleKey(key))
190         return true;
191 
192     // send an event to the focus-view
193     {
194         SkView* focus = this->getFocusView();
195         if (focus == NULL)
196             focus = this;
197 
198         SkEvent evt(SK_EventType_Key);
199         evt.setFast32(key);
200         if (focus->doEvent(evt))
201             return true;
202     }
203 
204     if (key == kUp_SkKey || key == kDown_SkKey) {
205         if (this->moveFocus(key == kUp_SkKey ? kPrev_FocusDirection : kNext_FocusDirection) == NULL)
206             this->onSetFocusView(NULL);
207         return true;
208     }
209     return false;
210 }
211 
handleKeyUp(SkKey key)212 bool SkWindow::handleKeyUp(SkKey key) {
213     if (key == kNONE_SkKey)
214         return false;
215 
216     if (this->onHandleKeyUp(key))
217         return true;
218 
219     //send an event to the focus-view
220     {
221         SkView* focus = this->getFocusView();
222         if (focus == NULL)
223             focus = this;
224 
225         //should this one be the same?
226         SkEvent evt(SK_EventType_KeyUp);
227         evt.setFast32(key);
228         if (focus->doEvent(evt))
229             return true;
230     }
231     return false;
232 }
233 
addMenu(SkOSMenu * menu)234 void SkWindow::addMenu(SkOSMenu* menu) {
235     *fMenus.append() = menu;
236     this->onAddMenu(menu);
237 }
238 
setTitle(const char title[])239 void SkWindow::setTitle(const char title[]) {
240     if (NULL == title) {
241         title = "";
242     }
243     fTitle.set(title);
244     this->onSetTitle(title);
245 }
246 
onEvent(const SkEvent & evt)247 bool SkWindow::onEvent(const SkEvent& evt) {
248     if (evt.isType(SK_EventDelayInval)) {
249         for (SkRegion::Iterator iter(fDirtyRgn); !iter.done(); iter.next())
250             this->onHandleInval(iter.rect());
251         fWaitingOnInval = false;
252         return true;
253     }
254     return this->INHERITED::onEvent(evt);
255 }
256 
onGetFocusView(SkView ** focus) const257 bool SkWindow::onGetFocusView(SkView** focus) const {
258     if (focus)
259         *focus = fFocusView;
260     return true;
261 }
262 
onSetFocusView(SkView * focus)263 bool SkWindow::onSetFocusView(SkView* focus) {
264     if (fFocusView != focus) {
265         if (fFocusView)
266             fFocusView->onFocusChange(false);
267         fFocusView = focus;
268         if (focus)
269             focus->onFocusChange(true);
270     }
271     return true;
272 }
273 
onHandleInval(const SkIRect &)274 void SkWindow::onHandleInval(const SkIRect&) {
275 }
276 
onHandleChar(SkUnichar)277 bool SkWindow::onHandleChar(SkUnichar) {
278     return false;
279 }
280 
onHandleKey(SkKey)281 bool SkWindow::onHandleKey(SkKey) {
282     return false;
283 }
284 
onHandleKeyUp(SkKey)285 bool SkWindow::onHandleKeyUp(SkKey) {
286     return false;
287 }
288 
handleClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)289 bool SkWindow::handleClick(int x, int y, Click::State state, void *owner,
290                            unsigned modifierKeys) {
291     return this->onDispatchClick(x, y, state, owner, modifierKeys);
292 }
293 
onDispatchClick(int x,int y,Click::State state,void * owner,unsigned modifierKeys)294 bool SkWindow::onDispatchClick(int x, int y, Click::State state,
295                                void* owner, unsigned modifierKeys) {
296     bool handled = false;
297 
298     // First, attempt to find an existing click with this owner.
299     int index = -1;
300     for (int i = 0; i < fClicks.count(); i++) {
301         if (owner == fClicks[i]->fOwner) {
302             index = i;
303             break;
304         }
305     }
306 
307     switch (state) {
308         case Click::kDown_State: {
309             if (index != -1) {
310                 delete fClicks[index];
311                 fClicks.remove(index);
312             }
313             Click* click = this->findClickHandler(SkIntToScalar(x),
314                                                   SkIntToScalar(y), modifierKeys);
315 
316             if (click) {
317                 click->fOwner = owner;
318                 *fClicks.append() = click;
319                 SkView::DoClickDown(click, x, y, modifierKeys);
320                 handled = true;
321             }
322             break;
323         }
324         case Click::kMoved_State:
325             if (index != -1) {
326                 SkView::DoClickMoved(fClicks[index], x, y, modifierKeys);
327                 handled = true;
328             }
329             break;
330         case Click::kUp_State:
331             if (index != -1) {
332                 SkView::DoClickUp(fClicks[index], x, y, modifierKeys);
333                 delete fClicks[index];
334                 fClicks.remove(index);
335                 handled = true;
336             }
337             break;
338         default:
339             // Do nothing
340             break;
341     }
342     return handled;
343 }
344 
345 #if SK_SUPPORT_GPU
346 
347 #include "gl/GrGLInterface.h"
348 #include "gl/GrGLUtil.h"
349 #include "SkGr.h"
350 
renderTarget(const AttachmentInfo & attachmentInfo,const GrGLInterface * interface,GrContext * grContext)351 GrRenderTarget* SkWindow::renderTarget(const AttachmentInfo& attachmentInfo,
352         const GrGLInterface* interface, GrContext* grContext) {
353     GrBackendRenderTargetDesc desc;
354     desc.fWidth = SkScalarRoundToInt(this->width());
355     desc.fHeight = SkScalarRoundToInt(this->height());
356     desc.fConfig = kSkia8888_GrPixelConfig;
357     desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
358     desc.fSampleCnt = attachmentInfo.fSampleCount;
359     desc.fStencilBits = attachmentInfo.fStencilBits;
360     GrGLint buffer;
361     GR_GL_GetIntegerv(interface, GR_GL_FRAMEBUFFER_BINDING, &buffer);
362     desc.fRenderTargetHandle = buffer;
363     return grContext->textureProvider()->wrapBackendRenderTarget(desc);
364 }
365 
366 #endif
367