|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <hal.h> |
|
17 #include <e32std.h> |
|
18 #include <stdlib.h> |
|
19 #include <bitdraw.h> |
|
20 #include "ScreenInfo.h" |
|
21 #include "_WININC.H" |
|
22 |
|
23 /** |
|
24 The max allowed screen number + 1. |
|
25 @internalComponent |
|
26 */ |
|
27 const TInt KMaxScreenNumber = 32; |
|
28 |
|
29 /** |
|
30 TheWinsWindowHandlers array is used as a container for the created RWindows objects. |
|
31 Each RWindows object manages single Windows OS window, which can be shared between one |
|
32 or more Symbian OS devices. |
|
33 It cannot be a C++ array (some of the CArray... classes), because it is part of a shared |
|
34 global memory. If it is a C++ array, then its constructor will be called every time, when |
|
35 an exe loads scdv.dll, which means - the array data will be destroyed! |
|
36 @internalComponent |
|
37 */ |
|
38 static RWindows* TheWinsWindowHandlers[KMaxScreenNumber]; |
|
39 |
|
40 /** |
|
41 WindowHandler() global function is used to get a pointer to the RWindows object, responsible |
|
42 for the drawing operations on the Emulator on the screen with aScreenNo number. |
|
43 @param aScreenNo Screen number |
|
44 @return A pointer to the related RWindows object or NULL if there is no such object. |
|
45 @panic "SCDV-13" panic if the aScreenNo is out of bounds [0..32]. |
|
46 @see RPointerArray |
|
47 @internalComponent |
|
48 */ |
|
49 RWindows* WindowHandler(TInt aScreenNo) |
|
50 { |
|
51 __ASSERT_ALWAYS(aScreenNo >= 0 && aScreenNo < KMaxScreenNumber, ::Panic(EScreenDriverPanicInvalidScreenNo)); |
|
52 return TheWinsWindowHandlers[aScreenNo]; |
|
53 } |
|
54 |
|
55 /** |
|
56 Used in CreateScreenSemaphoreName(). |
|
57 @see CreateScreenSemaphoreName() |
|
58 @internalComponent |
|
59 */ |
|
60 _LIT(KWindowInUseSemaphore,"WindowInUseSemaphore"); |
|
61 |
|
62 /** |
|
63 This global function is used for the creation of the name of the semaphore, which helps |
|
64 RWindows functionality to detect the moment, when the related Windows OS window can be |
|
65 destroyed safely - no more clients (Symbian OS screen devices). |
|
66 @param aScreenNo Screen number |
|
67 @param aScreenSemaphoreName An output parameter, where the semaphore name will be constructed |
|
68 in the following format "WindowInUseSemaphore<ScreenNo>". |
|
69 The length of aScreenSemaphoreName should be big enough for |
|
70 the semaphore name. |
|
71 @internalComponent |
|
72 */ |
|
73 void CreateScreenSemaphoreName(TInt aScreenNo, TDes& aScreenSemaphoreName) |
|
74 { |
|
75 aScreenSemaphoreName.Copy(KWindowInUseSemaphore); |
|
76 aScreenSemaphoreName.AppendNum(aScreenNo); |
|
77 } |
|
78 |
|
79 /** |
|
80 */ |
|
81 RWindows::RWindows(): |
|
82 iHwnd(NULL), |
|
83 iHdc(NULL), |
|
84 iHbitmap(NULL), |
|
85 iBitmapInfo(NULL), |
|
86 iBitmapBits(NULL), |
|
87 iH90bitmap(NULL), |
|
88 i90BitmapInfo(NULL), |
|
89 i90BitmapBits(NULL), |
|
90 i90ByteWidth(0), |
|
91 iByteWidth(0), |
|
92 iEpocBitmapBits(NULL), |
|
93 iOrientation(0), |
|
94 iScreenNo(-1) |
|
95 { |
|
96 } |
|
97 |
|
98 /** |
|
99 The method returns a pointer to the RWindows object, which manages the Windows OS window |
|
100 for the aScreenNo Symbian OS device screen. |
|
101 If no RWindows object exists for the requested screen number, it will be created. |
|
102 @param aScreenNo Screen number |
|
103 @param aHwnd Windows OS - window handle |
|
104 @param aSize Screen size in pixels |
|
105 @return A pointer to the related for that screen number RWindows object or NULL if |
|
106 GetWindow() call fails. The reason for the failure can be: no memory or some |
|
107 Windows OS related problem. |
|
108 */ |
|
109 RWindows* RWindows::GetWindow(TInt aScreenNo, TAny* aHwnd, const TSize& aSize) |
|
110 { |
|
111 //If TheWinsWindowHandlers[aScreenNo] is not null, then it is a valid RWindows object, |
|
112 //return it (a pointer to it). |
|
113 if(TheWinsWindowHandlers[aScreenNo]) |
|
114 { |
|
115 return TheWinsWindowHandlers[aScreenNo]; |
|
116 } |
|
117 //TheWinsWindowHandlers[aScreenNo] is null - allocate a memory for it. |
|
118 //If the allocation fails - return NULL. |
|
119 TheWinsWindowHandlers[aScreenNo] = (RWindows*)GlobalAlloc(GPTR,sizeof(RWindows)); |
|
120 if(!TheWinsWindowHandlers[aScreenNo]) |
|
121 { |
|
122 return NULL; |
|
123 } |
|
124 //Construct TheWinsWindowHandlers[aScreenNo] object, return NULL if the construction fails. |
|
125 TRAPD(ret,TheWinsWindowHandlers[aScreenNo]->ConstructL(aHwnd,aSize)); |
|
126 if (ret != KErrNone) |
|
127 { |
|
128 TheWinsWindowHandlers[aScreenNo]->Destroy(); |
|
129 TheWinsWindowHandlers[aScreenNo] = NULL; |
|
130 return NULL; |
|
131 } |
|
132 // |
|
133 TheWinsWindowHandlers[aScreenNo]->iScreenNo = aScreenNo; |
|
134 return TheWinsWindowHandlers[aScreenNo]; |
|
135 } |
|
136 |
|
137 /** |
|
138 The method releases the access the RWindows object, which manages aScreenNo screen. |
|
139 If there are no more clients (Symbian OS devices) for that window, it will be destroyed. |
|
140 @param aScreenNo Screen number |
|
141 */ |
|
142 void RWindows::ReleaseWindow(TInt aScreenNo) |
|
143 { |
|
144 if(TheWinsWindowHandlers[aScreenNo] == NULL) |
|
145 {//The related TheWinsWindowHandlers[aScreenNo] is NULL, which means that the |
|
146 //related RWindows object has been destroyed. Do nothing. |
|
147 return; |
|
148 } |
|
149 RSemaphore windowInUse; |
|
150 TBuf<32> screenSemaphoreName; |
|
151 ::CreateScreenSemaphoreName(aScreenNo, screenSemaphoreName); |
|
152 TInt ret = windowInUse.OpenGlobal(screenSemaphoreName,EOwnerThread); |
|
153 //The related semaphore does not exist, which means - all the clients, which have a shared |
|
154 //access to aScreenNo screen, do not use it anymore. It is safe to destroy the related |
|
155 //Windows OS window object. |
|
156 if (ret == KErrNotFound) |
|
157 { |
|
158 TheWinsWindowHandlers[aScreenNo]->Destroy(); |
|
159 TheWinsWindowHandlers[aScreenNo] = NULL; |
|
160 } |
|
161 windowInUse.Close(); |
|
162 } |
|
163 |
|
164 TUint8* RWindows::PixelAddress(TInt aX,TInt aY) |
|
165 { |
|
166 if (iOrientation & 1) |
|
167 { |
|
168 TUint8* pixelPtr = i90BitmapBits; |
|
169 pixelPtr += i90ByteWidth * (i90BitmapInfo->bmiHeader.biHeight - aY - 1); |
|
170 pixelPtr += aX * 3; |
|
171 return pixelPtr; |
|
172 } |
|
173 |
|
174 TUint8* pixelPtr = iBitmapBits; |
|
175 pixelPtr += iByteWidth * (iBitmapInfo->bmiHeader.biHeight - aY - 1); |
|
176 pixelPtr += aX * 3; |
|
177 return pixelPtr; |
|
178 } |
|
179 |
|
180 |
|
181 |
|
182 void RWindows::Destroy() |
|
183 { |
|
184 GdiFlush(); |
|
185 if (iHbitmap) DeleteObject(iHbitmap); |
|
186 if (iH90bitmap) DeleteObject(iH90bitmap); |
|
187 GlobalFree(iBitmapInfo); |
|
188 GlobalFree(i90BitmapInfo); |
|
189 if (iHwnd && iHdc) ReleaseDC(iHwnd,iHdc); |
|
190 GlobalFree(iEpocBitmapBits); |
|
191 GlobalFree(this); |
|
192 } |
|
193 |
|
194 void RWindows::ConstructL(TAny* aHwnd,const TSize& aSize) |
|
195 { |
|
196 iHwnd = (HWND)aHwnd; |
|
197 iHdc = GetDC(iHwnd); |
|
198 User::LeaveIfNull(iHdc); |
|
199 SetMapMode(iHdc,MM_TEXT); |
|
200 SetROP2(iHdc,R2_COPYPEN); |
|
201 |
|
202 iByteWidth = aSize.iWidth*3; |
|
203 i90ByteWidth = aSize.iHeight*3; |
|
204 TInt byteSize = aSize.iWidth * aSize.iHeight * 3; |
|
205 |
|
206 iBitmapInfo = (BITMAPINFO*)User::LeaveIfNull(GlobalAlloc(GPTR,sizeof(BITMAPINFO))); |
|
207 iBitmapInfo->bmiHeader.biBitCount = 24; |
|
208 iBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
209 iBitmapInfo->bmiHeader.biWidth = aSize.iWidth; |
|
210 iBitmapInfo->bmiHeader.biHeight = aSize.iHeight; |
|
211 iBitmapInfo->bmiHeader.biPlanes = 1; |
|
212 iBitmapInfo->bmiHeader.biCompression = BI_RGB; |
|
213 |
|
214 i90BitmapInfo = (BITMAPINFO*)User::LeaveIfNull(GlobalAlloc(GPTR,sizeof(BITMAPINFO))); |
|
215 i90BitmapInfo->bmiHeader.biBitCount = 24; |
|
216 i90BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
217 i90BitmapInfo->bmiHeader.biWidth = aSize.iHeight; |
|
218 i90BitmapInfo->bmiHeader.biHeight = aSize.iWidth; |
|
219 i90BitmapInfo->bmiHeader.biPlanes = 1; |
|
220 i90BitmapInfo->bmiHeader.biCompression = BI_RGB; |
|
221 |
|
222 iHbitmap = CreateDIBSection(iHdc,iBitmapInfo,DIB_RGB_COLORS,(TAny**)&iBitmapBits,NULL,0); |
|
223 User::LeaveIfNull(iHbitmap); |
|
224 Mem::Fill(iBitmapBits,byteSize,0xff); |
|
225 iH90bitmap = CreateDIBSection(iHdc,i90BitmapInfo,DIB_RGB_COLORS,(TAny**)&i90BitmapBits,NULL,0); |
|
226 User::LeaveIfNull(iH90bitmap); |
|
227 Mem::Fill(i90BitmapBits,byteSize,0xff); |
|
228 |
|
229 //We have to allocate iEpocBitmapBits to be large enough to hold all color bytes (32 bpp) |
|
230 //for the rectangle with aSize.iWidth & aSize.iHeight dimensions. |
|
231 iEpocBitmapBits = (TUint32*)User::LeaveIfNull(GlobalAlloc(GMEM_FIXED,aSize.iWidth * aSize.iHeight * 4)); |
|
232 Mem::Fill(iEpocBitmapBits,aSize.iWidth * aSize.iHeight * 4,0xff); |
|
233 } |
|
234 |
|
235 void RWindows::SetOrientation(TInt aOrientation) |
|
236 { |
|
237 iOrientation = aOrientation; |
|
238 } |
|
239 |
|
240 TInt RWindows::Orientation() const |
|
241 { |
|
242 return iOrientation; |
|
243 } |
|
244 |
|
245 void RWindows::Update(const TRegion& aRgn,const TSize& aSize) |
|
246 { |
|
247 if(aRgn.CheckError()) |
|
248 UpdateRect(TRect(aSize),aSize); |
|
249 else |
|
250 for(TInt count=0;count<aRgn.Count();count++) |
|
251 UpdateRect(aRgn[count],aSize); |
|
252 } |
|
253 |
|
254 void RWindows::UpdateRect(const TRect& aRect,const TSize& aSize) |
|
255 { |
|
256 if (iOrientation & 1) |
|
257 SetDIBitsToDevice(iHdc,aRect.iTl.iX,aRect.iTl.iY,aRect.Width(),aRect.Height(), |
|
258 aRect.iTl.iX,aSize.iWidth-aRect.iBr.iY,0,aSize.iWidth,i90BitmapBits, |
|
259 ((LPBITMAPINFO)i90BitmapInfo),DIB_RGB_COLORS); |
|
260 else |
|
261 SetDIBitsToDevice(iHdc,aRect.iTl.iX,aRect.iTl.iY,aRect.Width(),aRect.Height(), |
|
262 aRect.iTl.iX,aSize.iHeight-aRect.iBr.iY,0,aSize.iHeight,iBitmapBits, |
|
263 ((LPBITMAPINFO)iBitmapInfo),DIB_RGB_COLORS); |
|
264 } |
|
265 |
|
266 //Gets the Size dimension the RWindow is using as per orientation |
|
267 TSize RWindows::GetOrientedSize() |
|
268 { |
|
269 TSize orientedSize; |
|
270 if (iOrientation&1) |
|
271 orientedSize.SetSize(iEpocBitmapSize.iHeight,iEpocBitmapSize.iWidth); |
|
272 else |
|
273 orientedSize = iEpocBitmapSize; |
|
274 |
|
275 return orientedSize; |
|
276 } |
|
277 |
|
278 //Gets the actual orientation based refresh rect required from a 'physical' screen reference. |
|
279 TRect RWindows::GetOrientedRect(const TRect &aScreenRect) |
|
280 { |
|
281 TRect orientedRect; |
|
282 |
|
283 switch(iOrientation) |
|
284 { |
|
285 case 1: |
|
286 { |
|
287 orientedRect.SetRect(aScreenRect.iTl.iY, |
|
288 iEpocBitmapSize.iWidth-aScreenRect.iBr.iX, |
|
289 aScreenRect.iBr.iY, |
|
290 iEpocBitmapSize.iWidth-aScreenRect.iTl.iX); |
|
291 break; |
|
292 } |
|
293 case 2: |
|
294 { |
|
295 orientedRect.SetRect(iEpocBitmapSize.iWidth-aScreenRect.iBr.iX, |
|
296 iEpocBitmapSize.iHeight-aScreenRect.iBr.iY, |
|
297 iEpocBitmapSize.iWidth-aScreenRect.iTl.iX, |
|
298 iEpocBitmapSize.iHeight-aScreenRect.iTl.iY); |
|
299 break; |
|
300 } |
|
301 case 3: |
|
302 { |
|
303 orientedRect.SetRect(iEpocBitmapSize.iHeight-aScreenRect.iBr.iY, |
|
304 aScreenRect.iTl.iX, |
|
305 iEpocBitmapSize.iHeight-aScreenRect.iTl.iY, |
|
306 aScreenRect.iBr.iX); |
|
307 break; |
|
308 } |
|
309 default: |
|
310 { |
|
311 orientedRect = aScreenRect; |
|
312 break; |
|
313 } |
|
314 } |
|
315 |
|
316 return orientedRect; |
|
317 } |