Release 950109
[wine.git] / windows / cursor.c
blob5ba75a7f6f7d8732a7f3f6b718c265352f59f344
1 /*
2 * WINE
3 static char Copyright[] = "Copyright Martin Ayotte, 1993";
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include <unistd.h>
13 #include <X11/cursorfont.h>
14 #include <X11/Xlib.h>
15 #include "windows.h"
16 #include "win.h"
17 #include "gdi.h"
18 #include "library.h"
19 #include "neexe.h"
20 #include "wine.h"
21 #include "cursor.h"
22 #include "stddebug.h"
23 /* #define DEBUG_CURSOR */
24 /* #define DEBUG_RESOURCE */
25 #include "debug.h"
27 static int ShowCursCount = 0;
28 static HCURSOR hActiveCursor;
29 static HCURSOR hEmptyCursor = 0;
30 RECT ClipCursorRect;
32 static struct { LPSTR name; HCURSOR cursor; } system_cursor[] =
34 { IDC_ARROW, 0 },
35 { IDC_IBEAM, 0 },
36 { IDC_WAIT, 0 },
37 { IDC_CROSS, 0 },
38 { IDC_UPARROW, 0 },
39 { IDC_SIZE, 0 },
40 { IDC_ICON, 0 },
41 { IDC_SIZENWSE, 0 },
42 { IDC_SIZENESW, 0 },
43 { IDC_SIZEWE, 0 },
44 { IDC_SIZENS, 0 }
47 #define NB_SYS_CURSORS (sizeof(system_cursor)/sizeof(system_cursor[0]))
50 /**********************************************************************
51 * LoadCursor [USER.173]
53 HCURSOR LoadCursor(HANDLE instance, LPSTR cursor_name)
55 XColor bkcolor;
56 XColor fgcolor;
57 HCURSOR hCursor;
58 HANDLE rsc_mem;
59 WORD *lp;
60 CURSORDESCRIP *lpcurdesc;
61 CURSORALLOC *lpcur;
62 HDC hdc;
63 int i, j, image_size;
65 dprintf_resource(stddeb,"LoadCursor: instance = %04x, name = %p\n",
66 instance, cursor_name);
67 if (!instance)
69 for (i = 0; i < NB_SYS_CURSORS; i++)
70 if (system_cursor[i].name == cursor_name)
72 if (system_cursor[i].cursor) return system_cursor[i].cursor;
73 else break;
75 if (i == NB_SYS_CURSORS) return 0;
77 hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L);
78 if (hCursor == (HCURSOR)NULL) return 0;
79 if (!instance) system_cursor[i].cursor = hCursor;
81 dprintf_cursor(stddeb,"LoadCursor Alloc hCursor=%X\n", hCursor);
82 lpcur = (CURSORALLOC *)GlobalLock(hCursor);
83 memset(lpcur, 0, sizeof(CURSORALLOC));
84 if (instance == (HANDLE)NULL) {
85 instance = hSysRes;
86 switch((LONG)cursor_name) {
87 case IDC_ARROW:
88 lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
89 GlobalUnlock(hCursor);
90 return hCursor;
91 case IDC_CROSS:
92 lpcur->xcursor = XCreateFontCursor(display, XC_crosshair);
93 GlobalUnlock(hCursor);
94 return hCursor;
95 case IDC_IBEAM:
96 lpcur->xcursor = XCreateFontCursor(display, XC_xterm);
97 GlobalUnlock(hCursor);
98 return hCursor;
99 case IDC_WAIT:
100 lpcur->xcursor = XCreateFontCursor(display, XC_watch);
101 GlobalUnlock(hCursor);
102 return hCursor;
103 case IDC_SIZENS:
104 lpcur->xcursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
105 GlobalUnlock(hCursor);
106 return hCursor;
107 case IDC_SIZEWE:
108 lpcur->xcursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
109 GlobalUnlock(hCursor);
110 return hCursor;
111 case IDC_SIZENWSE:
112 case IDC_SIZENESW:
113 lpcur->xcursor = XCreateFontCursor(display, XC_fleur);
114 GlobalUnlock(hCursor);
115 return hCursor;
116 default:
117 break;
121 #if 1
122 lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
123 GlobalUnlock(hCursor);
124 return hCursor;
125 #endif
127 if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
128 rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR,
129 &image_size);
130 if (rsc_mem == (HANDLE)NULL) {
131 fprintf(stderr,"LoadCursor / Cursor %p not Found !\n", cursor_name);
132 ReleaseDC(GetDesktopWindow(), hdc);
133 return 0;
135 lp = (WORD *)GlobalLock(rsc_mem);
136 if (lp == NULL) {
137 GlobalFree(rsc_mem);
138 ReleaseDC(GetDesktopWindow(), hdc);
139 return 0;
141 lpcurdesc = (CURSORDESCRIP *)(lp + 3);
142 dprintf_cursor(stddeb,"LoadCursor / image_size=%d\n", image_size);
143 dprintf_cursor(stddeb,"LoadCursor / curReserved=%X\n", *lp);
144 dprintf_cursor(stddeb,"LoadCursor / curResourceType=%X\n", *(lp + 1));
145 dprintf_cursor(stddeb,"LoadCursor / curResourceCount=%X\n", *(lp + 2));
146 dprintf_cursor(stddeb,"LoadCursor / cursor Width=%d\n",
147 (int)lpcurdesc->Width);
148 dprintf_cursor(stddeb,"LoadCursor / cursor Height=%d\n",
149 (int)lpcurdesc->Height);
150 dprintf_cursor(stddeb,"LoadCursor / cursor curXHotspot=%d\n",
151 (int)lpcurdesc->curXHotspot);
152 dprintf_cursor(stddeb,"LoadCursor / cursor curYHotspot=%d\n",
153 (int)lpcurdesc->curYHotspot);
154 dprintf_cursor(stddeb,"LoadCursor / cursor curDIBSize=%lX\n",
155 (DWORD)lpcurdesc->curDIBSize);
156 dprintf_cursor(stddeb,"LoadCursor / cursor curDIBOffset=%lX\n",
157 (DWORD)lpcurdesc->curDIBOffset);
158 lpcur->descriptor = *lpcurdesc;
159 GlobalUnlock(rsc_mem);
160 GlobalFree(rsc_mem);
161 rsc_mem = RSC_LoadResource(instance,
162 MAKEINTRESOURCE(lpcurdesc->curDIBOffset),
163 NE_RSCTYPE_CURSOR, &image_size);
164 if (rsc_mem == (HANDLE)NULL) {
165 fprintf(stderr,
166 "LoadCursor / Cursor %p Bitmap not Found !\n", cursor_name);
167 ReleaseDC(GetDesktopWindow(), hdc);
168 return 0;
170 lp = (WORD *)GlobalLock(rsc_mem);
171 if (lp == NULL) {
172 GlobalFree(rsc_mem);
173 ReleaseDC(GetDesktopWindow(), hdc);
174 return 0;
176 lp++;
177 for (j = 0; j < 16; j++)
178 dprintf_cursor(stddeb,"%04X ", *(lp + j));
180 if (*lp == sizeof(BITMAPINFOHEADER))
181 lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
182 else
184 lpcur->hBitmap = 0;
185 /* lp += sizeof(BITMAP); */
186 for (i = 0; i < 81; i++) {
187 char temp = *((char *)lp + 162 + i);
188 *((char *)lp + 162 + i) = *((char *)lp + 324 - i);
189 *((char *)lp + 324 - i) = temp;
191 lpcur->pixshape = XCreatePixmapFromBitmapData(
192 display, DefaultRootWindow(display),
193 ((char *)lp + 211), 32, 32,
195 lpcurdesc->Width / 2, lpcurdesc->Height / 4,
197 WhitePixel(display, DefaultScreen(display)),
198 BlackPixel(display, DefaultScreen(display)), 1);
199 lpcur->pixmask = XCreatePixmapFromBitmapData(
200 display, DefaultRootWindow(display),
201 ((char *)lp + 211), 32, 32,
202 WhitePixel(display, DefaultScreen(display)),
203 BlackPixel(display, DefaultScreen(display)), 1);
204 memset(&bkcolor, 0, sizeof(XColor));
205 memset(&fgcolor, 0, sizeof(XColor));
206 bkcolor.pixel = WhitePixel(display, DefaultScreen(display));
207 fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
208 dprintf_cursor(stddeb,"LoadCursor / before XCreatePixmapCursor !\n");
209 lpcur->xcursor = XCreatePixmapCursor(display,
210 lpcur->pixshape, lpcur->pixmask,
211 &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot,
212 lpcur->descriptor.curYHotspot);
213 GlobalUnlock(rsc_mem);
214 GlobalFree(rsc_mem);
216 hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot,
217 lpcur->descriptor.curYHotspot, 32, 32,
218 (LPSTR)lp + 211, , (LPSTR)lp + 211);
220 XFreePixmap(display, lpcur->pixshape);
221 XFreePixmap(display, lpcur->pixmask);
222 ReleaseDC(GetDesktopWindow(), hdc);
223 GlobalUnlock(hCursor);
224 return hCursor;
229 /**********************************************************************
230 * CreateCursor [USER.406]
232 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot,
233 short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
235 XColor bkcolor;
236 XColor fgcolor;
237 HCURSOR hCursor;
238 CURSORALLOC *lpcur;
239 HDC hdc;
241 dprintf_resource(stddeb,"CreateCursor: inst=%04x nXhotspot=%d nYhotspot=%d nWidth=%d nHeight=%d\n",
242 instance, nXhotspot, nYhotspot, nWidth, nHeight);
243 dprintf_resource(stddeb,"CreateCursor: inst=%04x lpANDbitPlane=%p lpXORbitPlane=%p\n",
244 instance, lpANDbitPlane, lpXORbitPlane);
246 if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
247 hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L);
248 if (hCursor == (HCURSOR)NULL) {
249 ReleaseDC(GetDesktopWindow(), hdc);
250 return 0;
252 dprintf_cursor(stddeb,"CreateCursor Alloc hCursor=%X\n", hCursor);
253 lpcur = (CURSORALLOC *)GlobalLock(hCursor);
254 memset(lpcur, 0, sizeof(CURSORALLOC));
255 lpcur->descriptor.curXHotspot = nXhotspot;
256 lpcur->descriptor.curYHotspot = nYhotspot;
257 lpcur->pixshape = XCreatePixmapFromBitmapData(
258 display, DefaultRootWindow(display),
259 lpXORbitPlane, nWidth, nHeight,
260 WhitePixel(display, DefaultScreen(display)),
261 BlackPixel(display, DefaultScreen(display)), 1);
262 lpcur->pixmask = XCreatePixmapFromBitmapData(
263 display, DefaultRootWindow(display),
264 lpANDbitPlane, nWidth, nHeight,
265 WhitePixel(display, DefaultScreen(display)),
266 BlackPixel(display, DefaultScreen(display)), 1);
267 memset(&bkcolor, 0, sizeof(XColor));
268 memset(&fgcolor, 0, sizeof(XColor));
269 bkcolor.pixel = WhitePixel(display, DefaultScreen(display));
270 fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
271 lpcur->xcursor = XCreatePixmapCursor(display,
272 lpcur->pixshape, lpcur->pixmask,
273 &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot,
274 lpcur->descriptor.curYHotspot);
275 XFreePixmap(display, lpcur->pixshape);
276 XFreePixmap(display, lpcur->pixmask);
277 ReleaseDC(GetDesktopWindow(), hdc);
278 GlobalUnlock(hCursor);
279 return hCursor;
284 /**********************************************************************
285 * DestroyCursor [USER.458]
287 BOOL DestroyCursor(HCURSOR hCursor)
289 CURSORALLOC *lpcur;
290 if (hCursor == (HCURSOR)NULL) return FALSE;
291 lpcur = (CURSORALLOC *)GlobalLock(hCursor);
292 if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
293 GlobalUnlock(hCursor);
294 GlobalFree(hCursor);
295 return TRUE;
299 /**********************************************************************
300 * CURSOR_SetCursor
302 * Internal helper function for SetCursor() and ShowCursor().
304 static void CURSOR_SetCursor( HCURSOR hCursor )
306 CURSORALLOC *lpcur;
308 if (!(lpcur = (CURSORALLOC *)GlobalLock(hCursor))) return;
309 if (rootWindow != DefaultRootWindow(display))
311 XDefineCursor( display, rootWindow, lpcur->xcursor );
313 else
315 HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
316 while(hwnd)
318 Window win = WIN_GetXWindow( hwnd );
319 if (win) XDefineCursor( display, win, lpcur->xcursor );
320 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
323 GlobalUnlock( hCursor );
326 /**********************************************************************
327 * SetCursor [USER.69]
329 HCURSOR SetCursor(HCURSOR hCursor)
331 HCURSOR hOldCursor;
333 dprintf_cursor(stddeb,"SetCursor / hCursor=%04X !\n", hCursor);
334 hOldCursor = hActiveCursor;
335 hActiveCursor = hCursor;
336 if ((hCursor != hOldCursor) || (ShowCursCount < 0))
338 CURSOR_SetCursor( hCursor );
340 ShowCursCount = 0;
341 return hOldCursor;
345 /**********************************************************************
346 * GetCursor [USER.247]
348 HCURSOR GetCursor(void)
350 return hActiveCursor;
354 /**********************************************************************
355 * SetCursorPos [USER.70]
357 void SetCursorPos(short x, short y)
359 dprintf_cursor(stddeb,"SetCursorPos // x=%d y=%d\n", x, y);
360 XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
364 /**********************************************************************
365 * GetCursorPos [USER.17]
367 void GetCursorPos(LPPOINT lpRetPoint)
369 Window root, child;
370 int rootX, rootY;
371 int childX, childY;
372 unsigned int mousebut;
374 if (!lpRetPoint) return;
375 if (!XQueryPointer( display, rootWindow, &root, &child,
376 &rootX, &rootY, &childX, &childY, &mousebut ))
377 lpRetPoint->x = lpRetPoint->y = 0;
378 else
380 lpRetPoint->x = rootX + desktopX;
381 lpRetPoint->y = rootY + desktopY;
383 dprintf_cursor(stddeb,
384 "GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
388 /**********************************************************************
389 * ShowCursor [USER.71]
391 int ShowCursor(BOOL bShow)
393 dprintf_cursor(stddeb, "ShowCursor(%d), count=%d\n", bShow, ShowCursCount);
395 if (bShow)
397 if (++ShowCursCount == 0) /* Time to show it */
398 CURSOR_SetCursor( hActiveCursor );
400 else /* Hide it */
402 if (--ShowCursCount == -1) /* Time to hide it */
404 if (!hEmptyCursor)
405 hEmptyCursor = CreateCursor( 0, 1, 1, 1, 1,
406 "\xFF\xFF", "\xFF\xFF" );
407 CURSOR_SetCursor( hEmptyCursor );
410 return 0;
414 /**********************************************************************
415 * ClipCursor [USER.16]
417 void ClipCursor(LPRECT lpNewClipRect)
419 CopyRect(&ClipCursorRect, lpNewClipRect);
423 /**********************************************************************
424 * GetClipCursor [USER.309]
426 void GetClipCursor(LPRECT lpRetClipRect)
428 if (lpRetClipRect != NULL)
429 CopyRect(lpRetClipRect, &ClipCursorRect);