* Sync up to trunk HEAD (r62286).
[reactos.git] / win32ss / drivers / displays / framebuf / pointer.c
1 /*
2 * ReactOS Generic Framebuffer display driver
3 *
4 * Copyright (C) 2004 Filip Navara
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21 #include "framebuf.h"
22
23 #ifndef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT
24
25 /*
26 * DrvSetPointerShape
27 *
28 * Sets the new pointer shape.
29 *
30 * Status
31 * @unimplemented
32 */
33
34 ULONG APIENTRY
35 DrvSetPointerShape(
36 IN SURFOBJ *pso,
37 IN SURFOBJ *psoMask,
38 IN SURFOBJ *psoColor,
39 IN XLATEOBJ *pxlo,
40 IN LONG xHot,
41 IN LONG yHot,
42 IN LONG x,
43 IN LONG y,
44 IN RECTL *prcl,
45 IN FLONG fl)
46 {
47 /* return SPS_DECLINE;*/
48 return EngSetPointerShape(pso, psoMask, psoColor, pxlo, xHot, yHot, x, y, prcl, fl);
49 }
50
51 /*
52 * DrvMovePointer
53 *
54 * Moves the pointer to a new position and ensures that GDI does not interfere
55 * with the display of the pointer.
56 *
57 * Status
58 * @unimplemented
59 */
60
61 VOID APIENTRY
62 DrvMovePointer(
63 IN SURFOBJ *pso,
64 IN LONG x,
65 IN LONG y,
66 IN RECTL *prcl)
67 {
68 EngMovePointer(pso, x, y, prcl);
69 }
70
71 #else
72
73 VOID FASTCALL
74 IntHideMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
75 {
76 if (ppdev->PointerAttributes.Enable == FALSE)
77 {
78 return;
79 }
80
81 ppdev->PointerAttributes.Enable = FALSE;
82 if (ppdev->PointerSaveSurface != NULL)
83 {
84 RECTL DestRect;
85 POINTL SrcPoint;
86 SURFOBJ *SaveSurface;
87 SURFOBJ *MaskSurface;
88
89 DestRect.left = max(ppdev->PointerAttributes.Column, 0);
90 DestRect.top = max(ppdev->PointerAttributes.Row, 0);
91 DestRect.right = min(
92 ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
93 ppdev->ScreenWidth - 1);
94 DestRect.bottom = min(
95 ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
96 ppdev->ScreenHeight - 1);
97
98 SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
99 SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
100
101 SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
102 MaskSurface = EngLockSurface(ppdev->PointerMaskSurface);
103 EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
104 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
105 EngUnlockSurface(MaskSurface);
106 EngUnlockSurface(SaveSurface);
107 }
108 }
109
110 VOID FASTCALL
111 IntShowMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
112 {
113 if (ppdev->PointerAttributes.Enable == TRUE)
114 {
115 return;
116 }
117
118 ppdev->PointerAttributes.Enable = TRUE;
119
120 /*
121 * Copy the pixels under the cursor to temporary surface.
122 */
123
124 if (ppdev->PointerSaveSurface != NULL)
125 {
126 RECTL DestRect;
127 POINTL SrcPoint;
128 SURFOBJ *SaveSurface;
129
130 SrcPoint.x = max(ppdev->PointerAttributes.Column, 0);
131 SrcPoint.y = max(ppdev->PointerAttributes.Row, 0);
132
133 DestRect.left = SrcPoint.x - ppdev->PointerAttributes.Column;
134 DestRect.top = SrcPoint.y - ppdev->PointerAttributes.Row;
135 DestRect.right = min(
136 ppdev->PointerAttributes.Width,
137 ppdev->ScreenWidth - ppdev->PointerAttributes.Column - 1);
138 DestRect.bottom = min(
139 ppdev->PointerAttributes.Height,
140 ppdev->ScreenHeight - ppdev->PointerAttributes.Row - 1);
141
142 SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
143 EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
144 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
145 EngUnlockSurface(SaveSurface);
146 }
147
148 /*
149 * Blit the cursor on the screen.
150 */
151
152 {
153 RECTL DestRect;
154 POINTL SrcPoint;
155 SURFOBJ *ColorSurf;
156 SURFOBJ *MaskSurf;
157
158 DestRect.left = max(ppdev->PointerAttributes.Column, 0);
159 DestRect.top = max(ppdev->PointerAttributes.Row, 0);
160 DestRect.right = min(
161 ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
162 ppdev->ScreenWidth - 1);
163 DestRect.bottom = min(
164 ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
165 ppdev->ScreenHeight - 1);
166
167 SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
168 SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
169
170 MaskSurf = EngLockSurface(ppdev->PointerMaskSurface);
171 if (ppdev->PointerColorSurface != NULL)
172 {
173 ColorSurf = EngLockSurface(ppdev->PointerColorSurface);
174 EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, ppdev->PointerXlateObject,
175 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
176 EngUnlockSurface(ColorSurf);
177 }
178 else
179 {
180 /* FIXME */
181 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
182 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
183 SrcPoint.y += ppdev->PointerAttributes.Height;
184 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
185 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
186 }
187 EngUnlockSurface(MaskSurf);
188 }
189 }
190
191 /*
192 * DrvSetPointerShape
193 *
194 * Sets the new pointer shape.
195 *
196 * Status
197 * @implemented
198 */
199
200 ULONG APIENTRY
201 DrvSetPointerShape(
202 IN SURFOBJ *pso,
203 IN SURFOBJ *psoMask,
204 IN SURFOBJ *psoColor,
205 IN XLATEOBJ *pxlo,
206 IN LONG xHot,
207 IN LONG yHot,
208 IN LONG x,
209 IN LONG y,
210 IN RECTL *prcl,
211 IN FLONG fl)
212 {
213 PPDEV ppdev = (PPDEV)pso->dhpdev;
214 SURFOBJ *TempSurfObj;
215
216 IntHideMousePointer(ppdev, pso);
217
218 if (ppdev->PointerColorSurface != NULL)
219 {
220 /* FIXME: Is this really needed? */
221 TempSurfObj = EngLockSurface(ppdev->PointerColorSurface);
222 EngFreeMem(TempSurfObj->pvBits);
223 TempSurfObj->pvBits = 0;
224 EngUnlockSurface(TempSurfObj);
225
226 EngDeleteSurface(ppdev->PointerColorSurface);
227 ppdev->PointerMaskSurface = NULL;
228 }
229
230 if (ppdev->PointerMaskSurface != NULL)
231 {
232 /* FIXME: Is this really needed? */
233 TempSurfObj = EngLockSurface(ppdev->PointerMaskSurface);
234 EngFreeMem(TempSurfObj->pvBits);
235 TempSurfObj->pvBits = 0;
236 EngUnlockSurface(TempSurfObj);
237
238 EngDeleteSurface(ppdev->PointerMaskSurface);
239 ppdev->PointerMaskSurface = NULL;
240 }
241
242 if (ppdev->PointerSaveSurface != NULL)
243 {
244 EngDeleteSurface(ppdev->PointerSaveSurface);
245 ppdev->PointerSaveSurface = NULL;
246 }
247
248 /*
249 * See if we are being asked to hide the pointer.
250 */
251
252 if (psoMask == NULL)
253 {
254 return SPS_ACCEPT_EXCLUDE;
255 }
256
257 ppdev->PointerHotSpot.x = xHot;
258 ppdev->PointerHotSpot.y = yHot;
259
260 ppdev->PointerXlateObject = pxlo;
261 ppdev->PointerAttributes.Column = x - xHot;
262 ppdev->PointerAttributes.Row = y - yHot;
263 ppdev->PointerAttributes.Width = psoMask->lDelta << 3;
264 ppdev->PointerAttributes.Height = (psoMask->cjBits / psoMask->lDelta) >> 1;
265
266 if (psoColor != NULL)
267 {
268 SIZEL Size;
269 PBYTE Bits;
270
271 Size.cx = ppdev->PointerAttributes.Width;
272 Size.cy = ppdev->PointerAttributes.Height;
273 Bits = EngAllocMem(0, psoColor->cjBits, ALLOC_TAG);
274 memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
275
276 ppdev->PointerColorSurface = (HSURF)EngCreateBitmap(Size,
277 psoColor->lDelta, psoColor->iBitmapFormat, 0, Bits);
278 }
279 else
280 {
281 ppdev->PointerColorSurface = NULL;
282 }
283
284 if (psoMask != NULL)
285 {
286 SIZEL Size;
287 PBYTE Bits;
288
289 Size.cx = ppdev->PointerAttributes.Width;
290 Size.cy = ppdev->PointerAttributes.Height << 1;
291 Bits = EngAllocMem(0, psoMask->cjBits, ALLOC_TAG);
292 memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
293
294 ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
295 psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
296 }
297 else
298 {
299 ppdev->PointerMaskSurface = NULL;
300 }
301
302 /*
303 * Create surface for saving the pixels under the cursor.
304 */
305
306 {
307 SIZEL Size;
308 LONG lDelta;
309
310 Size.cx = ppdev->PointerAttributes.Width;
311 Size.cy = ppdev->PointerAttributes.Height;
312
313 switch (pso->iBitmapFormat)
314 {
315 case BMF_8BPP: lDelta = Size.cx; break;
316 case BMF_16BPP: lDelta = Size.cx << 1; break;
317 case BMF_24BPP: lDelta = Size.cx * 3; break;
318 case BMF_32BPP: lDelta = Size.cx << 2; break;
319 }
320
321 ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
322 Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
323 }
324
325 IntShowMousePointer(ppdev, pso);
326
327 return SPS_ACCEPT_EXCLUDE;
328 }
329
330 /*
331 * DrvMovePointer
332 *
333 * Moves the pointer to a new position and ensures that GDI does not interfere
334 * with the display of the pointer.
335 *
336 * Status
337 * @implemented
338 */
339
340 VOID APIENTRY
341 DrvMovePointer(
342 IN SURFOBJ *pso,
343 IN LONG x,
344 IN LONG y,
345 IN RECTL *prcl)
346 {
347 PPDEV ppdev = (PPDEV)pso->dhpdev;
348 BOOL WasVisible;
349
350 WasVisible = ppdev->PointerAttributes.Enable;
351 if (WasVisible)
352 {
353 IntHideMousePointer(ppdev, pso);
354 }
355
356 if (x == -1)
357 {
358 return;
359 }
360
361 ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
362 ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
363
364 if (WasVisible)
365 {
366 IntShowMousePointer(ppdev, pso);
367 }
368 }
369
370 #endif