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)
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 = NULL;
224       EngUnlockSurface(TempSurfObj);
225 
226       EngDeleteSurface(ppdev->PointerColorSurface);
227       ppdev->PointerColorSurface = 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 = NULL;
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 
280    {
281       SIZEL Size;
282       PBYTE Bits;
283 
284       Size.cx = ppdev->PointerAttributes.Width;
285       Size.cy = ppdev->PointerAttributes.Height << 1;
286       Bits = EngAllocMem(0, psoMask->cjBits, ALLOC_TAG);
287       memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
288 
289       ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
290          psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
291    }
292 
293    /*
294     * Create surface for saving the pixels under the cursor.
295     */
296 
297    {
298       SIZEL Size;
299       LONG lDelta;
300 
301       Size.cx = ppdev->PointerAttributes.Width;
302       Size.cy = ppdev->PointerAttributes.Height;
303 
304       switch (pso->iBitmapFormat)
305       {
306          case BMF_8BPP: lDelta = Size.cx; break;
307          case BMF_16BPP: lDelta = Size.cx << 1; break;
308          case BMF_24BPP: lDelta = Size.cx * 3; break;
309          case BMF_32BPP: lDelta = Size.cx << 2; break;
310       }
311 
312       ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
313          Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
314    }
315 
316    IntShowMousePointer(ppdev, pso);
317 
318    return SPS_ACCEPT_EXCLUDE;
319 }
320 
321 /*
322  * DrvMovePointer
323  *
324  * Moves the pointer to a new position and ensures that GDI does not interfere
325  * with the display of the pointer.
326  *
327  * Status
328  *    @implemented
329  */
330 
331 VOID APIENTRY
332 DrvMovePointer(
333    IN SURFOBJ *pso,
334    IN LONG x,
335    IN LONG y,
336    IN RECTL *prcl)
337 {
338    PPDEV ppdev = (PPDEV)pso->dhpdev;
339    BOOL WasVisible;
340 
341    WasVisible = ppdev->PointerAttributes.Enable;
342    if (WasVisible)
343    {
344       IntHideMousePointer(ppdev, pso);
345    }
346 
347    if (x == -1)
348    {
349       return;
350    }
351 
352    ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
353    ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
354 
355    if (WasVisible)
356    {
357       IntShowMousePointer(ppdev, pso);
358    }
359 }
360 
361 #endif
362