remove whitespace from end of lines
[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$
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
45 ASSERT(SurfObj != NULL);
46
47 ppdev = GDIDEV(SurfObj);
48
49 if(ppdev == NULL)
50 {
51 return(FALSE);
52 }
53
54 pgp = &ppdev->Pointer;
55
56 if (SPS_ACCEPT_NOEXCLUDE == pgp->Status ||
57 pgp->Exclude.right == -1)
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 ppdev->SafetyRemoveCount++;
72
73 if (ppdev->SafetyRemoveLevel)
74 {
75 /* already hidden */
76 return FALSE;
77 }
78
79 if (pgp->Exclude.right >= HazardX1
80 && pgp->Exclude.left <= HazardX2
81 && pgp->Exclude.bottom >= HazardY1
82 && pgp->Exclude.top <= HazardY2)
83 {
84 ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
85 if (pgp->MovePointer)
86 pgp->MovePointer(SurfObj, -1, -1, NULL);
87 else
88 EngMovePointer(SurfObj, -1, -1, NULL);
89 }
90
91 return(TRUE);
92 }
93
94 INT INTERNAL_CALL
95 MouseSafetyOnDrawEnd(SURFOBJ *SurfObj)
96 /*
97 * FUNCTION: Notify the mouse driver that drawing has finished on a surface.
98 */
99 {
100 GDIDEVICE *ppdev;
101 GDIPOINTER *pgp;
102
103 ASSERT(SurfObj != NULL);
104
105 ppdev = GDIDEV(SurfObj);
106
107 if(ppdev == NULL)
108 {
109 return(FALSE);
110 }
111
112 pgp = &ppdev->Pointer;
113
114 if(SPS_ACCEPT_NOEXCLUDE == pgp->Status ||
115 pgp->Exclude.right == -1)
116 {
117 return FALSE;
118 }
119
120 if (--ppdev->SafetyRemoveCount >= ppdev->SafetyRemoveLevel)
121 {
122 return FALSE;
123 }
124 if (pgp->MovePointer)
125 pgp->MovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude);
126 else
127 EngMovePointer(SurfObj, pgp->Pos.x, pgp->Pos.y, &pgp->Exclude);
128
129 ppdev->SafetyRemoveLevel = 0;
130
131 return(TRUE);
132 }
133
134 /* SOFTWARE MOUSE POINTER IMPLEMENTATION **************************************/
135
136 VOID INTERNAL_CALL
137 IntHideMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
138 {
139 GDIPOINTER *pgp;
140 POINTL pt;
141
142 ASSERT(ppdev);
143 ASSERT(DestSurface);
144
145 pgp = &ppdev->Pointer;
146
147 if (!pgp->Enabled)
148 {
149 return;
150 }
151
152 pgp->Enabled = FALSE;
153
154 pt.x = pgp->Pos.x - pgp->HotSpot.x;
155 pt.y = pgp->Pos.y - pgp->HotSpot.y;
156
157 if (pgp->SaveSurface != NULL)
158 {
159 RECTL DestRect;
160 POINTL SrcPoint;
161 SURFOBJ *SaveSurface;
162 SURFOBJ *MaskSurface;
163
164 DestRect.left = max(pt.x, 0);
165 DestRect.top = max(pt.y, 0);
166 DestRect.right = min(
167 pt.x + pgp->Size.cx,
168 DestSurface->sizlBitmap.cx);
169 DestRect.bottom = min(
170 pt.y + pgp->Size.cy,
171 DestSurface->sizlBitmap.cy);
172
173 SrcPoint.x = max(-pt.x, 0);
174 SrcPoint.y = max(-pt.y, 0);
175
176 if((SaveSurface = EngLockSurface(pgp->SaveSurface)))
177 {
178 if((MaskSurface = EngLockSurface(pgp->MaskSurface)))
179 {
180 EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
181 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, ROP3_TO_ROP4(SRCCOPY));
182 EngUnlockSurface(MaskSurface);
183 }
184 EngUnlockSurface(SaveSurface);
185 }
186 }
187 }
188
189 VOID INTERNAL_CALL
190 IntShowMousePointer(GDIDEVICE *ppdev, SURFOBJ *DestSurface)
191 {
192 GDIPOINTER *pgp;
193 SURFOBJ *SaveSurface;
194 POINTL pt;
195
196 ASSERT(ppdev);
197 ASSERT(DestSurface);
198
199 pgp = &ppdev->Pointer;
200
201 if (pgp->Enabled)
202 {
203 return;
204 }
205
206 pgp->Enabled = TRUE;
207
208 pt.x = pgp->Pos.x - pgp->HotSpot.x;
209 pt.y = pgp->Pos.y - pgp->HotSpot.y;
210
211 /*
212 * Copy the pixels under the cursor to temporary surface.
213 */
214
215 if (pgp->SaveSurface != NULL &&
216 (SaveSurface = EngLockSurface(pgp->SaveSurface)))
217 {
218 RECTL DestRect;
219 POINTL SrcPoint;
220
221 SrcPoint.x = max(pt.x, 0);
222 SrcPoint.y = max(pt.y, 0);
223
224 DestRect.left = SrcPoint.x - pt.x;
225 DestRect.top = SrcPoint.y - pt.y;
226 DestRect.right = min(
227 pgp->Size.cx,
228 DestSurface->sizlBitmap.cx - pt.x);
229 DestRect.bottom = min(
230 pgp->Size.cy,
231 DestSurface->sizlBitmap.cy - pt.y);
232
233 EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
234 &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCCOPY));
235 EngUnlockSurface(SaveSurface);
236 }
237
238 /*
239 * Blit the cursor on the screen.
240 */
241
242 {
243 RECTL DestRect;
244 POINTL SrcPoint;
245 SURFOBJ *ColorSurf;
246 SURFOBJ *MaskSurf = NULL;
247
248 DestRect.left = max(pt.x, 0);
249 DestRect.top = max(pt.y, 0);
250 DestRect.right = min(
251 pt.x + pgp->Size.cx,
252 DestSurface->sizlBitmap.cx);
253 DestRect.bottom = min(
254 pt.y + pgp->Size.cy,
255 DestSurface->sizlBitmap.cy);
256
257 SrcPoint.x = max(-pt.x, 0);
258 SrcPoint.y = max(-pt.y, 0);
259
260 if (pgp->MaskSurface)
261 MaskSurf = EngLockSurface(pgp->MaskSurface);
262
263 if (MaskSurf != NULL)
264 {
265 if (pgp->ColorSurface != NULL)
266 {
267 if((ColorSurf = EngLockSurface(pgp->ColorSurface)))
268 {
269 EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, pgp->XlateObject,
270 &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, R4_MASK);
271 EngUnlockSurface(ColorSurf);
272 }
273 }
274 else
275 {
276 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
277 &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCAND));
278 SrcPoint.y += pgp->Size.cy;
279 EngBitBlt(DestSurface, MaskSurf, NULL, NULL, pgp->XlateObject,
280 &DestRect, &SrcPoint, NULL, NULL, NULL, ROP3_TO_ROP4(SRCINVERT));
281 }
282 EngUnlockSurface(MaskSurf);
283 }
284 }
285 }
286
287 /*
288 * @implemented
289 */
290
291 ULONG STDCALL
292 EngSetPointerShape(
293 IN SURFOBJ *pso,
294 IN SURFOBJ *psoMask,
295 IN SURFOBJ *psoColor,
296 IN XLATEOBJ *pxlo,
297 IN LONG xHot,
298 IN LONG yHot,
299 IN LONG x,
300 IN LONG y,
301 IN RECTL *prcl,
302 IN FLONG fl)
303 {
304 GDIDEVICE *ppdev;
305 SURFOBJ *TempSurfObj;
306 GDIPOINTER *pgp;
307
308 ASSERT(pso);
309
310 ppdev = GDIDEV(pso);
311 pgp = &ppdev->Pointer;
312
313 IntHideMousePointer(ppdev, pso);
314
315 if (pgp->ColorSurface != NULL)
316 {
317 /* FIXME: Is this really needed? */
318 if((TempSurfObj = EngLockSurface(pgp->ColorSurface)))
319 {
320 EngFreeMem(TempSurfObj->pvBits);
321 TempSurfObj->pvBits = 0;
322 EngUnlockSurface(TempSurfObj);
323 }
324
325 EngDeleteSurface(pgp->ColorSurface);
326 pgp->MaskSurface = NULL;
327 }
328
329 if (pgp->MaskSurface != NULL)
330 {
331 /* FIXME: Is this really needed? */
332 if((TempSurfObj = EngLockSurface(pgp->MaskSurface)))
333 {
334 EngFreeMem(TempSurfObj->pvBits);
335 TempSurfObj->pvBits = 0;
336 EngUnlockSurface(TempSurfObj);
337 }
338
339 EngDeleteSurface(pgp->MaskSurface);
340 pgp->MaskSurface = NULL;
341 }
342
343 if (pgp->SaveSurface != NULL)
344 {
345 EngDeleteSurface(pgp->SaveSurface);
346 pgp->SaveSurface = NULL;
347 }
348
349 if (pgp->XlateObject != NULL)
350 {
351 EngDeleteXlate(pgp->XlateObject);
352 pgp->XlateObject = NULL;
353 }
354
355 /*
356 * See if we are being asked to hide the pointer.
357 */
358
359 if (psoMask == NULL)
360 {
361 return SPS_ACCEPT_NOEXCLUDE;
362 }
363
364 pgp->HotSpot.x = xHot;
365 pgp->HotSpot.y = yHot;
366
367 /* Actually this should be set by 'the other side', but it would be
368 * done right after this. It helps IntShowMousePointer. */
369 if (x != -1)
370 {
371 pgp->Pos.x = x;
372 pgp->Pos.y = y;
373 }
374
375 pgp->Size.cx = abs(psoMask->lDelta) << 3;
376 pgp->Size.cy = (psoMask->cjBits / abs(psoMask->lDelta)) >> 1;
377
378 if (psoColor != NULL)
379 {
380 PBYTE Bits;
381
382 Bits = EngAllocMem(0, psoColor->cjBits, TAG_MOUSE);
383 memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
384
385 pgp->ColorSurface = (HSURF)EngCreateBitmap(pgp->Size,
386 psoColor->lDelta, psoColor->iBitmapFormat,
387 psoColor->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
388 }
389 else
390 {
391 pgp->ColorSurface = NULL;
392 }
393
394 {
395 SIZEL Size;
396 PBYTE Bits;
397
398 Size.cx = pgp->Size.cx;
399 Size.cy = pgp->Size.cy << 1;
400 Bits = EngAllocMem(0, psoMask->cjBits, TAG_MOUSE);
401 memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
402
403 pgp->MaskSurface = (HSURF)EngCreateBitmap(Size,
404 psoMask->lDelta, psoMask->iBitmapFormat,
405 psoMask->lDelta < 0 ? 0 : BMF_TOPDOWN, Bits);
406 }
407
408 /*
409 * Create an XLATEOBJ that will be used for drawing masks.
410 * FIXME: We should get this in pxlo parameter!
411 */
412
413 if (pxlo == NULL)
414 {
415 HPALETTE BWPalette, DestPalette;
416 ULONG BWColors[] = {0, 0xFFFFFF};
417
418 BWPalette = EngCreatePalette(PAL_INDEXED, sizeof(BWColors) / sizeof(ULONG),
419 BWColors, 0, 0, 0);
420
421 DestPalette = ppdev->DevInfo.hpalDefault;
422 pgp->XlateObject = IntEngCreateXlate(0, PAL_INDEXED,
423 DestPalette, BWPalette);
424 EngDeletePalette(BWPalette);
425 }
426 else
427 {
428 pgp->XlateObject = pxlo;
429 }
430
431 /*
432 * Create surface for saving the pixels under the cursor.
433 */
434
435 {
436 LONG lDelta;
437
438 switch (pso->iBitmapFormat)
439 {
440 case BMF_1BPP:
441 lDelta = pgp->Size.cx >> 3;
442 break;
443 case BMF_4BPP:
444 lDelta = pgp->Size.cx >> 1;
445 break;
446 case BMF_8BPP:
447 lDelta = pgp->Size.cx;
448 break;
449 case BMF_16BPP:
450 lDelta = pgp->Size.cx << 1;
451 break;
452 case BMF_24BPP:
453 lDelta = pgp->Size.cx * 3;
454 break;
455 case BMF_32BPP:
456 lDelta = pgp->Size.cx << 2;
457 break;
458 default:
459 lDelta = 0;
460 break;
461 }
462
463 pgp->SaveSurface = (HSURF)EngCreateBitmap(
464 pgp->Size, lDelta, pso->iBitmapFormat, BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
465 }
466
467 if(x != -1)
468 {
469 IntShowMousePointer(ppdev, pso);
470
471 if (prcl != NULL)
472 {
473 prcl->left = x - pgp->HotSpot.x;
474 prcl->top = y - pgp->HotSpot.x;
475 prcl->right = prcl->left + pgp->Size.cx;
476 prcl->bottom = prcl->top + pgp->Size.cy;
477 }
478 } else if (prcl != NULL)
479 prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
480
481 return SPS_ACCEPT_EXCLUDE;
482 }
483
484 /*
485 * @implemented
486 */
487
488 VOID STDCALL
489 EngMovePointer(
490 IN SURFOBJ *pso,
491 IN LONG x,
492 IN LONG y,
493 IN RECTL *prcl)
494 {
495 GDIDEVICE *ppdev;
496 GDIPOINTER *pgp;
497
498 ASSERT(pso);
499
500 ppdev = GDIDEV(pso);
501
502 ASSERT(ppdev);
503
504 pgp = &ppdev->Pointer;
505
506 IntHideMousePointer(ppdev, pso);
507 if (x != -1)
508 {
509 /* Actually this should be set by 'the other side', but it would be
510 * done right after this. It helps IntShowMousePointer. */
511 pgp->Pos.x = x;
512 pgp->Pos.y = y;
513 IntShowMousePointer(ppdev, pso);
514 if (prcl != NULL)
515 {
516 prcl->left = x - pgp->HotSpot.x;
517 prcl->top = y - pgp->HotSpot.x;
518 prcl->right = prcl->left + pgp->Size.cx;
519 prcl->bottom = prcl->top + pgp->Size.cy;
520 }
521 } else if (prcl != NULL)
522 prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
523
524 }
525
526 /* EOF */