Release 940607
[wine] / misc / cursor.c
1 /*
2  *    WINE
3 */
4 static char Copyright[] = "Copyright  Martin Ayotte, 1993";
5
6 /*
7 #define DEBUG_CURSOR
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <X11/cursorfont.h>
18 #include <X11/Xlib.h>
19 #include "prototypes.h"
20 #include "windows.h"
21 #include "win.h"
22 #include "gdi.h"
23 #include "wine.h"
24 #include "cursor.h"
25
26 static int ShowCursCount = 0;
27 static HCURSOR hActiveCursor;
28 static HCURSOR hEmptyCursor = 0;
29 RECT    ClipCursorRect;
30 extern HINSTANCE hSysRes;
31 extern Window winHasCursor;
32 extern int desktopX, desktopY;   /* misc/main.c */
33
34 static struct { LPSTR name; HCURSOR cursor; } system_cursor[] =
35 {
36     { IDC_ARROW, 0 },
37     { IDC_IBEAM, 0 },
38     { IDC_WAIT, 0 },
39     { IDC_CROSS, 0 },
40     { IDC_UPARROW, 0 },
41     { IDC_SIZE, 0 },
42     { IDC_ICON, 0 },
43     { IDC_SIZENWSE, 0 },
44     { IDC_SIZENESW, 0 },
45     { IDC_SIZEWE, 0 },
46     { IDC_SIZENS, 0 }
47 };
48
49 #define NB_SYS_CURSORS  (sizeof(system_cursor)/sizeof(system_cursor[0]))
50
51
52 /**********************************************************************
53  *                      LoadCursor [USER.173]
54  */
55 HCURSOR LoadCursor(HANDLE instance, LPSTR cursor_name)
56 {
57     XColor      bkcolor;
58     XColor      fgcolor;
59     HCURSOR     hCursor;
60     HANDLE      rsc_mem;
61     WORD        *lp;
62     CURSORDESCRIP *lpcurdesc;
63     CURSORALLOC   *lpcur;
64     BITMAP      BitMap;
65     HBITMAP     hBitMap;
66     HDC         hMemDC;
67     HDC         hdc;
68     int i, j, image_size;
69 #ifdef DEBUG_RESOURCE
70     printf("LoadCursor: instance = %04x, name = %08x\n",
71            instance, cursor_name);
72 #endif    
73
74     if (!instance)
75     {
76         for (i = 0; i < NB_SYS_CURSORS; i++)
77             if (system_cursor[i].name == cursor_name)
78             {
79                 hCursor = system_cursor[i].cursor;
80                 break;
81             }
82         if (i == NB_SYS_CURSORS) return 0;
83         if (hCursor) return hCursor;
84     }
85     hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
86     if (hCursor == (HCURSOR)NULL) return 0;
87     if (!instance) system_cursor[i].cursor = hCursor;
88
89 #ifdef DEBUG_CURSOR
90     printf("LoadCursor Alloc hCursor=%X\n", hCursor);
91 #endif    
92     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
93     memset(lpcur, 0, sizeof(CURSORALLOC));
94     if (instance == (HANDLE)NULL) {
95         instance = hSysRes;
96         switch((LONG)cursor_name) {
97             case IDC_ARROW:
98                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_top_left_arrow);
99                 GlobalUnlock(hCursor);
100                 return hCursor;
101             case IDC_CROSS:
102                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_crosshair);
103                 GlobalUnlock(hCursor);
104                 return hCursor;
105             case IDC_IBEAM:
106                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_xterm);
107                 GlobalUnlock(hCursor);
108                 return hCursor;
109             case IDC_WAIT:
110                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_watch);
111                 GlobalUnlock(hCursor);
112                 return hCursor;
113             case IDC_SIZENS:
114                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_sb_v_double_arrow);
115                 GlobalUnlock(hCursor);
116                 return hCursor;
117             case IDC_SIZEWE:
118                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_sb_h_double_arrow);
119                 GlobalUnlock(hCursor);
120                 return hCursor;
121             case IDC_SIZENWSE:
122             case IDC_SIZENESW:
123                 lpcur->xcursor = XCreateFontCursor(XT_display, XC_fleur);
124                 GlobalUnlock(hCursor);
125                 return hCursor;
126             default:
127                 break;
128             }
129         }
130
131 #if 1
132     lpcur->xcursor = XCreateFontCursor(XT_display, XC_top_left_arrow);
133     GlobalUnlock(hCursor);
134     return hCursor;
135 #endif
136
137     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
138     rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
139                                &image_size);
140     if (rsc_mem == (HANDLE)NULL) {
141         printf("LoadCursor / Cursor %08X not Found !\n", cursor_name);
142         ReleaseDC(GetDesktopWindow(), hdc); 
143         return 0;
144         }
145     lp = (WORD *)GlobalLock(rsc_mem);
146     if (lp == NULL) {
147         GlobalFree(rsc_mem);
148         ReleaseDC(GetDesktopWindow(), hdc); 
149         return 0;
150         }
151     lpcurdesc = (CURSORDESCRIP *)(lp + 3);
152 #ifdef DEBUG_CURSOR
153     printf("LoadCursor / image_size=%d\n", image_size);
154     printf("LoadCursor / curReserved=%X\n", *lp);
155     printf("LoadCursor / curResourceType=%X\n", *(lp + 1));
156     printf("LoadCursor / curResourceCount=%X\n", *(lp + 2));
157     printf("LoadCursor / cursor Width=%d\n", (int)lpcurdesc->Width);
158     printf("LoadCursor / cursor Height=%d\n", (int)lpcurdesc->Height);
159     printf("LoadCursor / cursor curXHotspot=%d\n", (int)lpcurdesc->curXHotspot);
160     printf("LoadCursor / cursor curYHotspot=%d\n", (int)lpcurdesc->curYHotspot);
161     printf("LoadCursor / cursor curDIBSize=%lX\n", (DWORD)lpcurdesc->curDIBSize);
162     printf("LoadCursor / cursor curDIBOffset=%lX\n", (DWORD)lpcurdesc->curDIBOffset);
163 #endif
164     lpcur->descriptor = *lpcurdesc;
165     GlobalUnlock(rsc_mem);
166     GlobalFree(rsc_mem);
167     rsc_mem = RSC_LoadResource(instance, 
168         MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
169         NE_RSCTYPE_CURSOR, &image_size);
170     if (rsc_mem == (HANDLE)NULL) {
171         printf("LoadCursor / Cursor %08X Bitmap not Found !\n", cursor_name);
172         ReleaseDC(GetDesktopWindow(), hdc); 
173         return 0;
174         }
175     lp = (WORD *)GlobalLock(rsc_mem);
176     if (lp == NULL) {
177         GlobalFree(rsc_mem);
178         ReleaseDC(GetDesktopWindow(), hdc); 
179         return 0;
180         }
181         lp++;
182     for (j = 0; j < 16; j++)
183         printf("%04X ", *(lp + j));
184 /*
185     if (*lp == sizeof(BITMAPINFOHEADER))
186         lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
187     else
188 */
189         lpcur->hBitmap = 0;
190 /*     lp += sizeof(BITMAP); */
191     for (i = 0; i < 81; i++) {
192         char temp = *((char *)lp + 162 + i);
193         *((char *)lp + 162 + i) = *((char *)lp + 324 - i);
194         *((char *)lp + 324 - i) = temp;
195         }
196     lpcur->pixshape = XCreatePixmapFromBitmapData(
197         XT_display, DefaultRootWindow(XT_display), 
198         ((char *)lp + 211), 32, 32,
199 /*
200         lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
201 */
202         WhitePixel(XT_display, DefaultScreen(XT_display)), 
203         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
204     lpcur->pixmask = XCreatePixmapFromBitmapData(
205         XT_display, DefaultRootWindow(XT_display), 
206         ((char *)lp + 211), 32, 32,
207         WhitePixel(XT_display, DefaultScreen(XT_display)), 
208         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
209     memset(&bkcolor, 0, sizeof(XColor));
210     memset(&fgcolor, 0, sizeof(XColor));
211     bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
212     fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
213 printf("LoadCursor / before XCreatePixmapCursor !\n");
214     lpcur->xcursor = XCreatePixmapCursor(XT_display,
215         lpcur->pixshape, lpcur->pixmask, 
216         &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
217         lpcur->descriptor.curYHotspot);
218     GlobalUnlock(rsc_mem);
219     GlobalFree(rsc_mem);
220 /*
221     hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
222         lpcur->descriptor.curYHotspot, 32, 32,
223         (LPSTR)lp + 211, , (LPSTR)lp + 211);
224 */
225     XFreePixmap(XT_display, lpcur->pixshape);
226     XFreePixmap(XT_display, lpcur->pixmask);
227     ReleaseDC(GetDesktopWindow(), hdc); 
228     GlobalUnlock(hCursor);
229     return hCursor;
230 }
231
232
233
234 /**********************************************************************
235  *                      CreateCursor [USER.406]
236  */
237 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot, 
238         short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
239 {
240     XColor      bkcolor;
241     XColor      fgcolor;
242     HCURSOR     hCursor;
243     CURSORALLOC   *lpcur;
244     BITMAP      BitMap;
245     HBITMAP     hBitMap;
246     HDC         hMemDC;
247     HDC         hdc;
248     int i, j;
249 #ifdef DEBUG_RESOURCE
250     printf("CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
251        instance, nXhotspot, nYhotspot, nWidth, nHeight);
252     printf("CreateCursor: inst=%04x lpANDbitPlane=%08X lpXORbitPlane=%08X\n",
253         instance, lpANDbitPlane, lpXORbitPlane);
254 #endif    
255     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
256     hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
257     if (hCursor == (HCURSOR)NULL) {
258         ReleaseDC(GetDesktopWindow(), hdc); 
259         return 0;
260         }
261     printf("CreateCursor Alloc hCursor=%X\n", hCursor);
262     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
263     memset(lpcur, 0, sizeof(CURSORALLOC));
264     lpcur->descriptor.curXHotspot = nXhotspot;
265     lpcur->descriptor.curYHotspot = nYhotspot;
266     lpcur->pixshape = XCreatePixmapFromBitmapData(
267         XT_display, DefaultRootWindow(XT_display), 
268         lpXORbitPlane, nWidth, nHeight,
269         WhitePixel(XT_display, DefaultScreen(XT_display)), 
270         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
271     lpcur->pixmask = XCreatePixmapFromBitmapData(
272         XT_display, DefaultRootWindow(XT_display), 
273         lpANDbitPlane, nWidth, nHeight,
274         WhitePixel(XT_display, DefaultScreen(XT_display)), 
275         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
276     memset(&bkcolor, 0, sizeof(XColor));
277     memset(&fgcolor, 0, sizeof(XColor));
278     bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
279     fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
280     lpcur->xcursor = XCreatePixmapCursor(XT_display,
281         lpcur->pixshape, lpcur->pixmask, 
282         &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
283         lpcur->descriptor.curYHotspot);
284     XFreePixmap(XT_display, lpcur->pixshape);
285     XFreePixmap(XT_display, lpcur->pixmask);
286     ReleaseDC(GetDesktopWindow(), hdc); 
287     GlobalUnlock(hCursor);
288     return hCursor;
289 }
290
291
292
293 /**********************************************************************
294  *                      DestroyCursor [USER.458]
295  */
296 BOOL DestroyCursor(HCURSOR hCursor)
297 {
298     CURSORALLOC *lpcur;
299     if (hCursor == (HCURSOR)NULL) return FALSE;
300     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
301     if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
302     GlobalUnlock(hCursor);
303     GlobalFree(hCursor);
304     return TRUE;
305 }
306
307
308 /**********************************************************************
309  *                      CURSOR_SetWinCursor
310  *
311  * Set the cursor for a given window. To be used instead of SetCursor()
312  * wherever possible.
313  */
314 HCURSOR CURSOR_SetWinCursor( HWND hwnd, HCURSOR hCursor )
315 {
316     CURSORALLOC *lpcur;
317     HCURSOR     hOldCursor;
318     WND * wndPtr = WIN_FindWndPtr( hwnd );
319
320     if (!wndPtr || !hCursor) return 0;
321     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
322     hOldCursor = hActiveCursor;
323     if (hActiveCursor != hCursor) ShowCursCount = 0;
324     if (ShowCursCount >= 0)
325         XDefineCursor( display, wndPtr->window, lpcur->xcursor );
326     GlobalUnlock(hCursor);
327     hActiveCursor = hCursor;
328     return hOldCursor;
329 }
330
331
332 /**********************************************************************
333  *                      SetCursor [USER.69]
334  */
335 HCURSOR SetCursor(HCURSOR hCursor)
336 {
337     HDC         hDC;
338     HDC         hMemDC;
339     BITMAP      bm;
340     CURSORALLOC *lpcur;
341     HCURSOR     hOldCursor;
342     Window      root, child;
343     int         rootX, rootY;
344     int         childX, childY;
345     unsigned int mousebut;
346 #ifdef DEBUG_CURSOR
347     printf("SetCursor / hCursor=%04X !\n", hCursor);
348 #endif
349     if (hCursor == (HCURSOR)NULL) return FALSE;
350     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
351     hOldCursor = hActiveCursor;
352 #ifdef DEBUG_CURSOR
353     printf("SetCursor / lpcur->xcursor=%08X !\n", &lpcur->xcursor);
354     XQueryPointer(XT_display, DefaultRootWindow(XT_display),
355         &root, &child, &rootX, &rootY, &childX, &childY, &mousebut);
356     printf("SetCursor / winHasCursor=%08X !\n", winHasCursor);
357     printf("SetCursor / child=%08X !\n", child);
358 #endif
359     if (hActiveCursor != hCursor) ShowCursCount = 0;
360     if ((ShowCursCount >= 0) & (winHasCursor != 0)) {
361 /*      XUndefineCursor(XT_display, winHasCursor); */
362         XDefineCursor(XT_display, winHasCursor, lpcur->xcursor);
363         }
364     GlobalUnlock(hCursor);
365     hActiveCursor = hCursor;
366     return hOldCursor;
367 }
368
369 /**********************************************************************
370  *                      GetCursor [USER.247]
371  */
372 HCURSOR GetCursor(void)
373 {
374         return hActiveCursor;
375 }
376
377 /**********************************************************************
378  *                        SetCursorPos [USER.70]
379  */
380 void SetCursorPos(short x, short y)
381 {
382 #ifdef DEBUG_CURSOR
383     printf("SetCursorPos // x=%d y=%d\n", x, y);
384 #endif
385     XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
386 }
387
388
389 /**********************************************************************
390  *                        GetCursorPos [USER.17]
391  */
392 void GetCursorPos(LPPOINT lpRetPoint)
393 {
394     Window      root, child;
395     int         rootX, rootY;
396     int         childX, childY;
397     unsigned int mousebut;
398
399     if (!lpRetPoint) return;
400     if (!XQueryPointer( display, rootWindow, &root, &child,
401                         &rootX, &rootY, &childX, &childY, &mousebut ))
402         lpRetPoint->x = lpRetPoint->y = 0;
403     else
404     {
405         lpRetPoint->x = rootX + desktopX;
406         lpRetPoint->y = rootY + desktopY;
407     }
408 #ifdef DEBUG_CURSOR
409         printf("GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
410 #endif
411 }
412
413
414 /**********************************************************************
415  *                      ShowCursor [USER.71]
416  */
417 int ShowCursor(BOOL bShow)
418 {
419     HCURSOR     hCursor;
420 #ifdef DEBUG_CURSOR
421         printf("ShowCursor bShow=%d ShowCount=%d !\n", bShow, ShowCursCount);
422 #endif
423     if (bShow)
424         ShowCursCount++;
425     else
426         ShowCursCount--;
427     if (ShowCursCount >= 0) {
428 /*      if (hCursor == (HCURSOR)NULL) */
429             hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
430         SetCursor(hCursor);
431         }
432     else {
433 /*      XUndefineCursor(XT_display, winHasCursor); */
434         if (hEmptyCursor == (HCURSOR)NULL)
435             hEmptyCursor = CreateCursor((HINSTANCE)NULL, 1, 1, 1, 1, 
436                                         "\xFF\xFF", "\xFF\xFF");
437         hCursor = SetCursor(hEmptyCursor);
438         hActiveCursor = hCursor;
439         }
440     return 0;
441 }
442
443
444 /**********************************************************************
445  *                        ClipCursor [USER.16]
446  */
447 void ClipCursor(LPRECT lpNewClipRect)
448 {
449     CopyRect(&ClipCursorRect, lpNewClipRect);
450 }
451
452
453 /**********************************************************************
454  *                        GetClipCursor [USER.309]
455  */
456 void GetClipCursor(LPRECT lpRetClipRect)
457 {
458     if (lpRetClipRect != NULL)
459         CopyRect(lpRetClipRect, &ClipCursorRect);
460 }
461
462
463
464