1. remove mouse cursor hacks from eng/mouse
[reactos.git] / reactos / subsys / win32k / eng / mouse.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: mouse.c,v 1.78 2004/12/12 01:40:36 weiden Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * PURPOSE: Mouse
23 * FILE: subsys/win32k/eng/mouse.c
24 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
25 * REVISION HISTORY:
26 * 06-06-2001 CSH Created
27 */
28 /* INCLUDES ******************************************************************/
29 #include <w32k.h>
30
31 /* FUNCTIONS *****************************************************************/
32
33 INT INTERNAL_CALL
34 MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1,
35 LONG HazardY1, LONG HazardX2, LONG HazardY2)
36 /*
37 * FUNCTION: Notify the mouse driver that drawing is about to begin in
38 * a rectangle on a particular surface.
39 */
40 {
41 LONG tmp;
42 GDIDEVICE *ppdev;
43 GDIPOINTER *pgp;
44 POINTL pt;
45
46 ASSERT(SurfObj != NULL);
47
48 ppdev = GDIDEV(SurfObj);
49
50 if(ppdev == NULL)
51 {
52 return(FALSE);
53 }
54
55 pgp = &ppdev->Pointer;
56
57 if (SPS_ACCEPT_NOEXCLUDE == pgp->Status)
58 {
59 return(FALSE);
60 }
61
62 if (HazardX1 > HazardX2)
63 {
64 tmp = HazardX2; HazardX2 = HazardX1; HazardX1 = tmp;
65 }
66 if (HazardY1 > HazardY2)
67 {
68 tmp = HazardY2; HazardY2 = HazardY1; HazardY1 = tmp;
69 }
70
71 pt.x = pgp->Pos.x - pgp->HotSpot.x;
72 pt.y = pgp->Pos.y - pgp->HotSpot.y;
73
74 if (pt.x + pgp->Size.cx >= HazardX1
75 && pt.x <= HazardX2
76 && pt.y + pgp->Size.cy >= HazardY1
77 && pt.y <= HazardY2)
78 {
79 if (0 != pgp->SafetyRemoveCount++)
80 {
81 return FALSE;
82 }
83 pgp->SafetySwitch = TRUE;
84 if (pgp->MovePointer)
85 pgp->MovePointer(SurfObj, -1, -1, NULL);
86 else
87 EngMovePointer(SurfObj, -1, -1, NULL);
88 }
89
90 return(TRUE);
91 }
92
93 INT INTERNAL_CALL
94 MouseSafetyOnDrawEnd(SURFOBJ *SurfObj)
95 /*
96 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
97 */
98 {
99 GDIDEVICE *ppdev;
100 GDIPOINTER *pgp;
101
102 ASSERT(SurfObj != NULL);
103
104 ppdev = GDIDEV(SurfObj);
105
106 if(ppdev == NULL)
107 {
108 return(FALSE);
109 }
110
111 pgp = &ppdev->Pointer;
112
113 if(SPS_ACCEPT_NOEXCLUDE == pgp->Status)
114 {
115 return FALSE;
116 }
117
118 if (pgp->SafetySwitch)
119 {
120 if (1 < pgp->SafetyRemoveCount--)
121 {
122 /* Someone else removed it too, let them restore it */
123 return FALSE;
124 }
125 if (pgp->MovePointer)
126 pgp->MovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, NULL);
127 else
128 EngMovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, NULL);
129 pgp->SafetySwitch = FALSE;
130 }
131
132 return(TRUE);
133 }
134
135 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
136
137 VOID INTERNAL_CALL
138 IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
139 {
140 GDIPOINTER *pgp;
141 POINTL pt;
142
143 ASSERT(ppdev);
144 ASSERT(DestSurface);
145
146 pgp = &ppdev->Pointer;
147
148 if (!pgp->Enabled)
149 {
150 return;
151 }
152
153 pgp->Enabled = FALSE;
154
155 if(pgp->Pos.x == -1)
156 {
157 return;
158 }
159
160 pt.x = pgp->Pos.x - pgp->HotSpot.x;
161 pt.y = pgp->Pos.y - pgp->HotSpot.y;
162
163 if (pgp->SaveSurface != NULL)
164 {
165 RECTL DestRect;
166 POINTL SrcPoint;
167 SURFOBJ *SaveSurface;
168 SURFOBJ *MaskSurface;
169
170 DestRect.left = max(pt.x, 0);
171 DestRect.top = max(pt.y, 0);
172 DestRect.right = min(
173 pt.x + pgp->Size.cx,
174 DestSurface->sizlBitmap.cx);
175 DestRect.bottom = min(
176 pt.y + pgp->Size.cy,
177 DestSurface->sizlBitmap.cy);
178
179 SrcPoint.x = max(-pt.x, 0);
180 SrcPoint.y = max(-pt.y, 0);
181
182 if((SaveSurface = EngLockSurface(pgp->SaveSurface)))
183 {
184 if((MaskSurface = EngLockSurface(pgp->MaskSurface)))
185 {
186 EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
187 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
188 EngUnlockSurface(MaskSurface);
189 }
190 EngUnlockSurface(SaveSurface);
191 }
192 }
193 }
194
195 VOID INTERNAL_CALL
196 IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
197 {
198 GDIPOINTER *pgp;
199 SURFOBJ *SaveSurface;
200 POINTL pt;
201
202 ASSERT(ppdev);
203 ASSERT(DestSurface);
204
205 pgp = &ppdev->Pointer;
206
207 if (pgp->Enabled)
208 {
209 return;
210 }
211
212 pgp->Enabled = TRUE;
213
214 pt.x = pgp->Pos.x - pgp->HotSpot.x;
215 pt.y = pgp->Pos.y - pgp->HotSpot.y;
216
217 /*
218 * Copy the pixels under the cursor to temporary surface.
219 */
220
221 if (pgp->SaveSurface != NULL &&
222 (SaveSurface = EngLockSurface(pgp->SaveSurface)))
223 {
224 RECTL DestRect;
225 POINTL SrcPoint;
226
227 SrcPoint.x = max(pt.x, 0);
228 SrcPoint.y = max(pt.y, 0);
229
230 DestRect.left = SrcPoint.x - pt.x;
231 DestRect.top = SrcPoint.y - pt.y;
232 DestRect.right = min(
233 pgp->Size.cx,
234 DestSurface->sizlBitmap.cx - pt.x);
235 DestRect.bottom = min(
236 pgp->Size.cy,
237 DestSurface->sizlBitmap.cy - pt.y);
238
239 EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
240 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
241 EngUnlockSurface(SaveSurface);
242 }
243
244 /*
245 * Blit the cursor on the screen.
246 */
247
248 {
249 RECTL DestRect;
250 POINTL SrcPoint;
251 SURFOBJ *ColorSurf;
252 SURFOBJ *MaskSurf;
253
254 DestRect.left = max(pt.x, 0);
255 DestRect.top = max(pt.y, 0);
256 DestRect.right = min(
257 pt.x + pgp->Size.cx,
258 DestSurface->sizlBitmap.cx);
259 DestRect.bottom = min(
260 pt.y + pgp->Size.cy,
261 DestSurface->sizlBitmap.cy);
262
263 SrcPoint.x = max(-pt.x, 0);
264 SrcPoint.y = max(-pt.y, 0);
265
266 MaskSurf = EngLockSurface(pgp->MaskSurface);
267 if (MaskSurf != NULL)
268 {
269 if (pgp->ColorSurface != NULL)
270 {
271 if((ColorSurf = EngLockSurface(pgp->ColorSurface)))
272 {
273 EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, pgp->XlateObject,
274 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
275 EngUnlockSurface(ColorSurf);
276 }
277 }
278 else
279 {
280 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
281 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
282 SrcPoint.y += pgp->Size.cy;
283 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
284 &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
285 }
286 EngUnlockSurface(MaskSurf);
287 }
288 }
289 }
290
291 /*
292 * @implemented
293 */
294
295 ULONG STDCALL
296 EngSetPointerShape(
297 IN SURFOBJ *pso,
298 IN SURFOBJ *psoMask,
299 IN SURFOBJ *psoColor,
300 IN XLATEOBJ *pxlo,
301 IN LONG xHot,
302 IN LONG yHot,
303 IN LONG x,
304 IN LONG y,
305 IN RECTL *prcl,
306 IN FLONG fl)
307 {
308 GDIDEVICE *ppdev;
309 SURFOBJ *TempSurfObj;
310 GDIPOINTER *pgp;
311
312 ASSERT(pso);
313
314 ppdev = GDIDEV(pso);
315 pgp = &ppdev->Pointer;
316
317 IntHideMousePointer(ppdev, pso);
318
319 if (pgp->ColorSurface != NULL)
320 {
321 /* FIXME: Is this really needed? */
322 if((TempSurfObj = EngLockSurface(pgp->ColorSurface)))
323 {
324 EngFreeMem(TempSurfObj->pvBits);
325 TempSurfObj->pvBits = 0;
326 EngUnlockSurface(TempSurfObj);
327 }
328
329 EngDeleteSurface(pgp->ColorSurface);
330 pgp->MaskSurface = NULL;
331 }
332
333 if (pgp->MaskSurface != NULL)
334 {
335 /* FIXME: Is this really needed? */
336 if((TempSurfObj = EngLockSurface(pgp->MaskSurface)))
337 {
338 EngFreeMem(TempSurfObj->pvBits);
339 TempSurfObj->pvBits = 0;
340 EngUnlockSurface(TempSurfObj);
341 }
342
343 EngDeleteSurface(pgp->MaskSurface);
344 pgp->MaskSurface = NULL;
345 }
346
347 if (pgp->SaveSurface != NULL)
348 {
349 EngDeleteSurface(pgp->SaveSurface);
350 pgp->SaveSurface = NULL;
351 }
352
353 if (pgp->XlateObject != NULL)
354 {
355 EngDeleteXlate(pgp->XlateObject);
356 pgp->XlateObject = NULL;
357 }
358
359 /*
360 * See if we are being asked to hide the pointer.
361 */
362
363 if (psoMask == NULL)
364 {
365 return SPS_ACCEPT_NOEXCLUDE;
366 }
367
368 pgp->HotSpot.x = xHot;
369 pgp->HotSpot.y = yHot;
370
371 pgp->Pos.x = x;
372 pgp->Pos.y = y;
373 pgp->Size.cx = abs(psoMask->lDelta) << 3;
374 pgp->Size.cy = (psoMask->cjBits / abs(psoMask->lDelta)) >> 1;
375
376 if (prcl != NULL)
377 {
378 /* FIXME - right rectangle when x == -1? */
379 prcl->left = pgp->Pos.x - pgp->HotSpot.x;
380 prcl->top = pgp->Pos.y - pgp->HotSpot.x;
381 prcl->right = prcl->left + pgp->Size.cx;
382 prcl->bottom = prcl->top + pgp->Size.cy;
383 }
384
385 if (psoColor != NULL)
386 {
387 PBYTE Bits;
388
389 Bits = EngAllocMem(0, psoColor->cjBits, TAG_MOUSE);
390 memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
391
392 pgp->ColorSurface = (HSURF)EngCreateBitmap(pgp->Size,
393 psoColor->lDelta, psoColor->iBitmapFormat,
394 psoColor->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
395 }
396 else
397 {
398 pgp->ColorSurface = NULL;
399 }
400
401 {
402 SIZEL Size;
403 PBYTE Bits;
404
405 Size.cx = pgp->Size.cx;
406 Size.cy = pgp->Size.cy << 1;
407 Bits = EngAllocMem(0, psoMask->cjBits, TAG_MOUSE);
408 memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
409
410 pgp->MaskSurface = (HSURF)EngCreateBitmap(Size,
411 psoMask->lDelta, psoMask->iBitmapFormat,
412 psoMask->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
413 }
414
415 /*
416 * Create an XLATEOBJ that will be used for drawing masks.
417 * FIXME: We should get this in pxlo parameter!
418 */
419
420 if (pxlo == NULL)
421 {
422 HPALETTE BWPalette, DestPalette;
423 ULONG BWColors[] = {0, 0xFFFFFF};
424
425 BWPalette = EngCreatePalette(PAL_INDEXED, sizeof(BWColors) / sizeof(ULONG),
426 BWColors, 0, 0, 0);
427
428 DestPalette = ppdev->DevInfo.hpalDefault;
429 pgp->XlateObject = IntEngCreateXlate(0, PAL_INDEXED,
430 DestPalette, BWPalette);
431 EngDeletePalette(BWPalette);
432 }
433 else
434 {
435 pgp->XlateObject = pxlo;
436 }
437
438 /*
439 * Create surface for saving the pixels under the cursor.
440 */
441
442 {
443 LONG lDelta;
444
445 switch (pso->iBitmapFormat)
446 {
447 case BMF_1BPP:
448 lDelta = pgp->Size.cx >> 3;
449 break;
450 case BMF_4BPP:
451 lDelta = pgp->Size.cx >> 1;
452 break;
453 case BMF_8BPP:
454 lDelta = pgp->Size.cx;
455 break;
456 case BMF_16BPP:
457 lDelta = pgp->Size.cx << 1;
458 break;
459 case BMF_24BPP:
460 lDelta = pgp->Size.cx * 3;
461 break;
462 case BMF_32BPP:
463 lDelta = pgp->Size.cx << 2;
464 break;
465 default:
466 lDelta = 0;
467 break;
468 }
469
470 pgp->SaveSurface = (HSURF)EngCreateBitmap(
471 pgp->Size, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
472 }
473
474 if(x != -1)
475 {
476 IntShowMousePointer(ppdev, pso);
477 }
478
479 return SPS_ACCEPT_EXCLUDE;
480 }
481
482 /*
483 * @implemented
484 */
485
486 VOID STDCALL
487 EngMovePointer(
488 IN SURFOBJ *pso,
489 IN LONG x,
490 IN LONG y,
491 IN RECTL *prcl)
492 {
493 GDIDEVICE *ppdev;
494 GDIPOINTER *pgp;
495
496 ASSERT(pso);
497
498 ppdev = GDIDEV(pso);
499
500 ASSERT(ppdev);
501
502 pgp = &ppdev->Pointer;
503
504
505 IntHideMousePointer(ppdev, pso);
506 if (x != -1)
507 {
508 pgp->Pos.x = x;
509 pgp->Pos.y = y;
510 IntShowMousePointer(ppdev, pso);
511 }
512
513 if (prcl != NULL)
514 {
515 /* FIXME - right rectangle when x == -1? */
516 prcl->left = pgp->Pos.x - pgp->HotSpot.x;
517 prcl->top = pgp->Pos.y - pgp->HotSpot.x;
518 prcl->right = prcl->left + pgp->Size.cx;
519 prcl->bottom = prcl->top + pgp->Size.cy;
520 }
521 }
522
523 /* EOF */