Release 940524
[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     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
131     rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
132                                &image_size);
133     if (rsc_mem == (HANDLE)NULL) {
134         printf("LoadCursor / Cursor %08X not Found !\n", cursor_name);
135         ReleaseDC(GetDesktopWindow(), hdc); 
136         return 0;
137         }
138     lp = (WORD *)GlobalLock(rsc_mem);
139     if (lp == NULL) {
140         GlobalFree(rsc_mem);
141         ReleaseDC(GetDesktopWindow(), hdc); 
142         return 0;
143         }
144     lpcurdesc = (CURSORDESCRIP *)(lp + 3);
145 #ifdef DEBUG_CURSOR
146     printf("LoadCursor / image_size=%d\n", image_size);
147     printf("LoadCursor / curReserved=%X\n", *lp);
148     printf("LoadCursor / curResourceType=%X\n", *(lp + 1));
149     printf("LoadCursor / curResourceCount=%X\n", *(lp + 2));
150     printf("LoadCursor / cursor Width=%d\n", (int)lpcurdesc->Width);
151     printf("LoadCursor / cursor Height=%d\n", (int)lpcurdesc->Height);
152     printf("LoadCursor / cursor curXHotspot=%d\n", (int)lpcurdesc->curXHotspot);
153     printf("LoadCursor / cursor curYHotspot=%d\n", (int)lpcurdesc->curYHotspot);
154     printf("LoadCursor / cursor curDIBSize=%lX\n", (DWORD)lpcurdesc->curDIBSize);
155     printf("LoadCursor / cursor curDIBOffset=%lX\n", (DWORD)lpcurdesc->curDIBOffset);
156 #endif
157     lpcur->descriptor = *lpcurdesc;
158     GlobalUnlock(rsc_mem);
159     GlobalFree(rsc_mem);
160     rsc_mem = RSC_LoadResource(instance, 
161         MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
162         NE_RSCTYPE_CURSOR, &image_size);
163     if (rsc_mem == (HANDLE)NULL) {
164         printf("LoadCursor / Cursor %08X Bitmap not Found !\n", cursor_name);
165         ReleaseDC(GetDesktopWindow(), hdc); 
166         return 0;
167         }
168     lp = (WORD *)GlobalLock(rsc_mem);
169     if (lp == NULL) {
170         GlobalFree(rsc_mem);
171         ReleaseDC(GetDesktopWindow(), hdc); 
172         return 0;
173         }
174         lp++;
175     for (j = 0; j < 16; j++)
176         printf("%04X ", *(lp + j));
177 /*
178     if (*lp == sizeof(BITMAPINFOHEADER))
179         lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
180     else
181 */
182         lpcur->hBitmap = 0;
183 /*     lp += sizeof(BITMAP); */
184     for (i = 0; i < 81; i++) {
185         char temp = *((char *)lp + 162 + i);
186         *((char *)lp + 162 + i) = *((char *)lp + 324 - i);
187         *((char *)lp + 324 - i) = temp;
188         }
189     lpcur->pixshape = XCreatePixmapFromBitmapData(
190         XT_display, DefaultRootWindow(XT_display), 
191         ((char *)lp + 211), 32, 32,
192 /*
193         lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
194 */
195         WhitePixel(XT_display, DefaultScreen(XT_display)), 
196         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
197     lpcur->pixmask = XCreatePixmapFromBitmapData(
198         XT_display, DefaultRootWindow(XT_display), 
199         ((char *)lp + 211), 32, 32,
200         WhitePixel(XT_display, DefaultScreen(XT_display)), 
201         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
202     memset(&bkcolor, 0, sizeof(XColor));
203     memset(&fgcolor, 0, sizeof(XColor));
204     bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
205     fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
206 printf("LoadCursor / before XCreatePixmapCursor !\n");
207     lpcur->xcursor = XCreatePixmapCursor(XT_display,
208         lpcur->pixshape, lpcur->pixmask, 
209         &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
210         lpcur->descriptor.curYHotspot);
211     GlobalUnlock(rsc_mem);
212     GlobalFree(rsc_mem);
213 /*
214     hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
215         lpcur->descriptor.curYHotspot, 32, 32,
216         (LPSTR)lp + 211, , (LPSTR)lp + 211);
217 */
218     XFreePixmap(XT_display, lpcur->pixshape);
219     XFreePixmap(XT_display, lpcur->pixmask);
220     ReleaseDC(GetDesktopWindow(), hdc); 
221     GlobalUnlock(hCursor);
222     return hCursor;
223 }
224
225
226
227 /**********************************************************************
228  *                      CreateCursor [USER.406]
229  */
230 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot, 
231         short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
232 {
233     XColor      bkcolor;
234     XColor      fgcolor;
235     HCURSOR     hCursor;
236     CURSORALLOC   *lpcur;
237     BITMAP      BitMap;
238     HBITMAP     hBitMap;
239     HDC         hMemDC;
240     HDC         hdc;
241     int i, j;
242 #ifdef DEBUG_RESOURCE
243     printf("CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
244        instance, nXhotspot, nYhotspot, nWidth, nHeight);
245     printf("CreateCursor: inst=%04x lpANDbitPlane=%08X lpXORbitPlane=%08X\n",
246         instance, lpANDbitPlane, lpXORbitPlane);
247 #endif    
248     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
249     hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
250     if (hCursor == (HCURSOR)NULL) {
251         ReleaseDC(GetDesktopWindow(), hdc); 
252         return 0;
253         }
254     printf("CreateCursor Alloc hCursor=%X\n", hCursor);
255     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
256     memset(lpcur, 0, sizeof(CURSORALLOC));
257     lpcur->descriptor.curXHotspot = nXhotspot;
258     lpcur->descriptor.curYHotspot = nYhotspot;
259     lpcur->pixshape = XCreatePixmapFromBitmapData(
260         XT_display, DefaultRootWindow(XT_display), 
261         lpXORbitPlane, nWidth, nHeight,
262         WhitePixel(XT_display, DefaultScreen(XT_display)), 
263         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
264     lpcur->pixmask = XCreatePixmapFromBitmapData(
265         XT_display, DefaultRootWindow(XT_display), 
266         lpANDbitPlane, nWidth, nHeight,
267         WhitePixel(XT_display, DefaultScreen(XT_display)), 
268         BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
269     memset(&bkcolor, 0, sizeof(XColor));
270     memset(&fgcolor, 0, sizeof(XColor));
271     bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
272     fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
273     lpcur->xcursor = XCreatePixmapCursor(XT_display,
274         lpcur->pixshape, lpcur->pixmask, 
275         &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
276         lpcur->descriptor.curYHotspot);
277     XFreePixmap(XT_display, lpcur->pixshape);
278     XFreePixmap(XT_display, lpcur->pixmask);
279     ReleaseDC(GetDesktopWindow(), hdc); 
280     GlobalUnlock(hCursor);
281     return hCursor;
282 }
283
284
285
286 /**********************************************************************
287  *                      DestroyCursor [USER.458]
288  */
289 BOOL DestroyCursor(HCURSOR hCursor)
290 {
291     CURSORALLOC *lpcur;
292     if (hCursor == (HCURSOR)NULL) return FALSE;
293     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
294     if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
295     GlobalUnlock(hCursor);
296     GlobalFree(hCursor);
297     return TRUE;
298 }
299
300
301 /**********************************************************************
302  *                      CURSOR_SetWinCursor
303  *
304  * Set the cursor for a given window. To be used instead of SetCursor()
305  * wherever possible.
306  */
307 HCURSOR CURSOR_SetWinCursor( HWND hwnd, HCURSOR hCursor )
308 {
309     CURSORALLOC *lpcur;
310     HCURSOR     hOldCursor;
311     WND * wndPtr = WIN_FindWndPtr( hwnd );
312
313     if (!wndPtr || !hCursor) return 0;
314     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
315     hOldCursor = hActiveCursor;
316     if (hActiveCursor != hCursor) ShowCursCount = 0;
317     if (ShowCursCount >= 0)
318         XDefineCursor( display, wndPtr->window, lpcur->xcursor );
319     GlobalUnlock(hCursor);
320     hActiveCursor = hCursor;
321     return hOldCursor;
322 }
323
324
325 /**********************************************************************
326  *                      SetCursor [USER.69]
327  */
328 HCURSOR SetCursor(HCURSOR hCursor)
329 {
330     HDC         hDC;
331     HDC         hMemDC;
332     BITMAP      bm;
333     CURSORALLOC *lpcur;
334     HCURSOR     hOldCursor;
335     Window      root, child;
336     int         rootX, rootY;
337     int         childX, childY;
338     unsigned int mousebut;
339 #ifdef DEBUG_CURSOR
340     printf("SetCursor / hCursor=%04X !\n", hCursor);
341 #endif
342     if (hCursor == (HCURSOR)NULL) return FALSE;
343     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
344     hOldCursor = hActiveCursor;
345 #ifdef DEBUG_CURSOR
346     printf("SetCursor / lpcur->xcursor=%08X !\n", &lpcur->xcursor);
347     XQueryPointer(XT_display, DefaultRootWindow(XT_display),
348         &root, &child, &rootX, &rootY, &childX, &childY, &mousebut);
349     printf("SetCursor / winHasCursor=%08X !\n", winHasCursor);
350     printf("SetCursor / child=%08X !\n", child);
351 #endif
352     if (hActiveCursor != hCursor) ShowCursCount = 0;
353     if ((ShowCursCount >= 0) & (winHasCursor != 0)) {
354 /*      XUndefineCursor(XT_display, winHasCursor); */
355         XDefineCursor(XT_display, winHasCursor, lpcur->xcursor);
356         }
357     GlobalUnlock(hCursor);
358     hActiveCursor = hCursor;
359     return hOldCursor;
360 }
361
362 /**********************************************************************
363  *                      GetCursor [USER.247]
364  */
365 HCURSOR GetCursor(void)
366 {
367         return hActiveCursor;
368 }
369
370 /**********************************************************************
371  *                        SetCursorPos [USER.70]
372  */
373 void SetCursorPos(short x, short y)
374 {
375 #ifdef DEBUG_CURSOR
376     printf("SetCursorPos // x=%d y=%d\n", x, y);
377 #endif
378     XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
379 }
380
381
382 /**********************************************************************
383  *                        GetCursorPos [USER.17]
384  */
385 void GetCursorPos(LPPOINT lpRetPoint)
386 {
387     Window      root, child;
388     int         rootX, rootY;
389     int         childX, childY;
390     unsigned int mousebut;
391
392     if (!lpRetPoint) return;
393     if (!XQueryPointer( display, rootWindow, &root, &child,
394                         &rootX, &rootY, &childX, &childY, &mousebut ))
395         lpRetPoint->x = lpRetPoint->y = 0;
396     else
397     {
398         lpRetPoint->x = rootX + desktopX;
399         lpRetPoint->y = rootY + desktopY;
400     }
401 #ifdef DEBUG_CURSOR
402         printf("GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
403 #endif
404 }
405
406
407 /**********************************************************************
408  *                      ShowCursor [USER.71]
409  */
410 int ShowCursor(BOOL bShow)
411 {
412     HCURSOR     hCursor;
413 #ifdef DEBUG_CURSOR
414         printf("ShowCursor bShow=%d ShowCount=%d !\n", bShow, ShowCursCount);
415 #endif
416     if (bShow)
417         ShowCursCount++;
418     else
419         ShowCursCount--;
420     if (ShowCursCount >= 0) {
421 /*      if (hCursor == (HCURSOR)NULL) */
422             hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
423         SetCursor(hCursor);
424         }
425     else {
426 /*      XUndefineCursor(XT_display, winHasCursor); */
427         if (hEmptyCursor == (HCURSOR)NULL)
428             hEmptyCursor = CreateCursor((HINSTANCE)NULL, 1, 1, 1, 1, 
429                                         "\xFF\xFF", "\xFF\xFF");
430         hCursor = SetCursor(hEmptyCursor);
431         hActiveCursor = hCursor;
432         }
433     return 0;
434 }
435
436
437 /**********************************************************************
438  *                        ClipCursor [USER.16]
439  */
440 void ClipCursor(LPRECT lpNewClipRect)
441 {
442     CopyRect(&ClipCursorRect, lpNewClipRect);
443 }
444
445
446 /**********************************************************************
447  *                        GetClipCursor [USER.309]
448  */
449 void GetClipCursor(LPRECT lpRetClipRect)
450 {
451     if (lpRetClipRect != NULL)
452         CopyRect(lpRetClipRect, &ClipCursorRect);
453 }
454
455
456
457