Release 950216
[wine.git] / windows / cursor.c
blob911637e39bdce2ecd4d303078c9de90295340cc2
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 switch((LONG)cursor_name) {
86 case IDC_ARROW:
87 lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
88 GlobalUnlock(hCursor);
89 return hCursor;
90 case IDC_CROSS:
91 lpcur->xcursor = XCreateFontCursor(display, XC_crosshair);
92 GlobalUnlock(hCursor);
93 return hCursor;
94 case IDC_IBEAM:
95 lpcur->xcursor = XCreateFontCursor(display, XC_xterm);
96 GlobalUnlock(hCursor);
97 return hCursor;
98 case IDC_WAIT:
99 lpcur->xcursor = XCreateFontCursor(display, XC_watch);
100 GlobalUnlock(hCursor);
101 return hCursor;
102 case IDC_SIZENS:
103 lpcur->xcursor = XCreateFontCursor(display, XC_sb_v_double_arrow);
104 GlobalUnlock(hCursor);
105 return hCursor;
106 case IDC_SIZEWE:
107 lpcur->xcursor = XCreateFontCursor(display, XC_sb_h_double_arrow);
108 GlobalUnlock(hCursor);
109 return hCursor;
110 case IDC_SIZENWSE:
111 case IDC_SIZENESW:
112 lpcur->xcursor = XCreateFontCursor(display, XC_fleur);
113 GlobalUnlock(hCursor);
114 return hCursor;
115 default:
116 break;
120 #if 1
121 lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
122 GlobalUnlock(hCursor);
123 return hCursor;
124 #endif
126 if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
127 rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR,
128 &image_size);
129 if (rsc_mem == (HANDLE)NULL) {
130 fprintf(stderr,"LoadCursor / Cursor %p not Found !\n", cursor_name);
131 ReleaseDC(GetDesktopWindow(), hdc);
132 return 0;
134 lp = (WORD *)GlobalLock(rsc_mem);
135 if (lp == NULL) {
136 GlobalFree(rsc_mem);
137 ReleaseDC(GetDesktopWindow(), hdc);
138 return 0;
140 lpcurdesc = (CURSORDESCRIP *)(lp + 3);
141 dprintf_cursor(stddeb,"LoadCursor / image_size=%d\n", image_size);
142 dprintf_cursor(stddeb,"LoadCursor / curReserved=%X\n", *lp);
143 dprintf_cursor(stddeb,"LoadCursor / curResourceType=%X\n", *(lp + 1));
144 dprintf_cursor(stddeb,"LoadCursor / curResourceCount=%X\n", *(lp + 2));
145 dprintf_cursor(stddeb,"LoadCursor / cursor Width=%d\n",
146 (int)lpcurdesc->Width);
147 dprintf_cursor(stddeb,"LoadCursor / cursor Height=%d\n",
148 (int)lpcurdesc->Height);
149 dprintf_cursor(stddeb,"LoadCursor / cursor curXHotspot=%d\n",
150 (int)lpcurdesc->curXHotspot);
151 dprintf_cursor(stddeb,"LoadCursor / cursor curYHotspot=%d\n",
152 (int)lpcurdesc->curYHotspot);
153 dprintf_cursor(stddeb,"LoadCursor / cursor curDIBSize=%lX\n",
154 (DWORD)lpcurdesc->curDIBSize);
155 dprintf_cursor(stddeb,"LoadCursor / cursor curDIBOffset=%lX\n",
156 (DWORD)lpcurdesc->curDIBOffset);
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 fprintf(stderr,
165 "LoadCursor / Cursor %p Bitmap not Found !\n", cursor_name);
166 ReleaseDC(GetDesktopWindow(), hdc);
167 return 0;
169 lp = (WORD *)GlobalLock(rsc_mem);
170 if (lp == NULL) {
171 GlobalFree(rsc_mem);
172 ReleaseDC(GetDesktopWindow(), hdc);
173 return 0;
175 lp++;
176 for (j = 0; j < 16; j++)
177 dprintf_cursor(stddeb,"%04X ", *(lp + j));
179 if (*lp == sizeof(BITMAPINFOHEADER))
180 lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
181 else
183 lpcur->hBitmap = 0;
184 /* lp += sizeof(BITMAP); */
185 for (i = 0; i < 81; i++) {
186 char temp = *((char *)lp + 162 + i);
187 *((char *)lp + 162 + i) = *((char *)lp + 324 - i);
188 *((char *)lp + 324 - i) = temp;
190 lpcur->pixshape = XCreatePixmapFromBitmapData(
191 display, DefaultRootWindow(display),
192 ((char *)lp + 211), 32, 32,
194 lpcurdesc->Width / 2, lpcurdesc->Height / 4,
196 WhitePixel(display, DefaultScreen(display)),
197 BlackPixel(display, DefaultScreen(display)), 1);
198 lpcur->pixmask = XCreatePixmapFromBitmapData(
199 display, DefaultRootWindow(display),
200 ((char *)lp + 211), 32, 32,
201 WhitePixel(display, DefaultScreen(display)),
202 BlackPixel(display, DefaultScreen(display)), 1);
203 memset(&bkcolor, 0, sizeof(XColor));
204 memset(&fgcolor, 0, sizeof(XColor));
205 bkcolor.pixel = WhitePixel(display, DefaultScreen(display));
206 fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
207 dprintf_cursor(stddeb,"LoadCursor / before XCreatePixmapCursor !\n");
208 lpcur->xcursor = XCreatePixmapCursor(display,
209 lpcur->pixshape, lpcur->pixmask,
210 &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot,
211 lpcur->descriptor.curYHotspot);
212 GlobalUnlock(rsc_mem);
213 GlobalFree(rsc_mem);
215 hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot,
216 lpcur->descriptor.curYHotspot, 32, 32,
217 (LPSTR)lp + 211, , (LPSTR)lp + 211);
219 XFreePixmap(display, lpcur->pixshape);
220 XFreePixmap(display, lpcur->pixmask);
221 ReleaseDC(GetDesktopWindow(), hdc);
222 GlobalUnlock(hCursor);
223 return hCursor;
228 /**********************************************************************
229 * CreateCursor [USER.406]
231 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot,
232 short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
234 XColor bkcolor;
235 XColor fgcolor;
236 HCURSOR hCursor;
237 CURSORALLOC *lpcur;
238 HDC hdc;
240 dprintf_resource(stddeb,"CreateCursor: inst=%04x nXhotspot=%d nYhotspot=%d nWidth=%d nHeight=%d\n",
241 instance, nXhotspot, nYhotspot, nWidth, nHeight);
242 dprintf_resource(stddeb,"CreateCursor: inst=%04x lpANDbitPlane=%p lpXORbitPlane=%p\n",
243 instance, lpANDbitPlane, lpXORbitPlane);
245 if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
246 hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L);
247 if (hCursor == (HCURSOR)NULL) {
248 ReleaseDC(GetDesktopWindow(), hdc);
249 return 0;
251 dprintf_cursor(stddeb,"CreateCursor Alloc hCursor=%X\n", hCursor);
252 lpcur = (CURSORALLOC *)GlobalLock(hCursor);
253 memset(lpcur, 0, sizeof(CURSORALLOC));
254 lpcur->descriptor.curXHotspot = nXhotspot;
255 lpcur->descriptor.curYHotspot = nYhotspot;
256 lpcur->pixshape = XCreatePixmapFromBitmapData(
257 display, DefaultRootWindow(display),
258 lpXORbitPlane, nWidth, nHeight,
259 WhitePixel(display, DefaultScreen(display)),
260 BlackPixel(display, DefaultScreen(display)), 1);
261 lpcur->pixmask = XCreatePixmapFromBitmapData(
262 display, DefaultRootWindow(display),
263 lpANDbitPlane, nWidth, nHeight,
264 WhitePixel(display, DefaultScreen(display)),
265 BlackPixel(display, DefaultScreen(display)), 1);
266 memset(&bkcolor, 0, sizeof(XColor));
267 memset(&fgcolor, 0, sizeof(XColor));
268 bkcolor.pixel = WhitePixel(display, DefaultScreen(display));
269 fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
270 lpcur->xcursor = XCreatePixmapCursor(display,
271 lpcur->pixshape, lpcur->pixmask,
272 &fgcolor, &bkcolor, lpcur->descriptor.curXHotspot,
273 lpcur->descriptor.curYHotspot);
274 XFreePixmap(display, lpcur->pixshape);
275 XFreePixmap(display, lpcur->pixmask);
276 ReleaseDC(GetDesktopWindow(), hdc);
277 GlobalUnlock(hCursor);
278 return hCursor;
283 /**********************************************************************
284 * DestroyCursor [USER.458]
286 BOOL DestroyCursor(HCURSOR hCursor)
288 CURSORALLOC *lpcur;
289 if (hCursor == (HCURSOR)NULL) return FALSE;
290 lpcur = (CURSORALLOC *)GlobalLock(hCursor);
291 if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
292 GlobalUnlock(hCursor);
293 GlobalFree(hCursor);
294 return TRUE;
298 /**********************************************************************
299 * CURSOR_SetCursor
301 * Internal helper function for SetCursor() and ShowCursor().
303 static void CURSOR_SetCursor( HCURSOR hCursor )
305 CURSORALLOC *lpcur;
307 if (!(lpcur = (CURSORALLOC *)GlobalLock(hCursor))) return;
308 if (rootWindow != DefaultRootWindow(display))
310 XDefineCursor( display, rootWindow, lpcur->xcursor );
312 else
314 HWND hwnd = GetWindow( GetDesktopWindow(), GW_CHILD );
315 while(hwnd)
317 Window win = WIN_GetXWindow( hwnd );
318 if (win) XDefineCursor( display, win, lpcur->xcursor );
319 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
322 GlobalUnlock( hCursor );
325 /**********************************************************************
326 * SetCursor [USER.69]
328 HCURSOR SetCursor(HCURSOR hCursor)
330 HCURSOR hOldCursor;
332 dprintf_cursor(stddeb,"SetCursor / hCursor=%04X !\n", hCursor);
333 hOldCursor = hActiveCursor;
334 hActiveCursor = hCursor;
335 if ((hCursor != hOldCursor) || (ShowCursCount < 0))
337 CURSOR_SetCursor( hCursor );
339 ShowCursCount = 0;
340 return hOldCursor;
344 /**********************************************************************
345 * GetCursor [USER.247]
347 HCURSOR GetCursor(void)
349 return hActiveCursor;
353 /**********************************************************************
354 * SetCursorPos [USER.70]
356 void SetCursorPos(short x, short y)
358 dprintf_cursor(stddeb,"SetCursorPos // x=%d y=%d\n", x, y);
359 XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
363 /**********************************************************************
364 * GetCursorPos [USER.17]
366 void GetCursorPos(LPPOINT lpRetPoint)
368 Window root, child;
369 int rootX, rootY;
370 int childX, childY;
371 unsigned int mousebut;
373 if (!lpRetPoint) return;
374 if (!XQueryPointer( display, rootWindow, &root, &child,
375 &rootX, &rootY, &childX, &childY, &mousebut ))
376 lpRetPoint->x = lpRetPoint->y = 0;
377 else
379 lpRetPoint->x = rootX + desktopX;
380 lpRetPoint->y = rootY + desktopY;
382 dprintf_cursor(stddeb,
383 "GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
387 /**********************************************************************
388 * ShowCursor [USER.71]
390 int ShowCursor(BOOL bShow)
392 dprintf_cursor(stddeb, "ShowCursor(%d), count=%d\n", bShow, ShowCursCount);
394 if (bShow)
396 if (++ShowCursCount == 0) /* Time to show it */
397 CURSOR_SetCursor( hActiveCursor );
399 else /* Hide it */
401 if (--ShowCursCount == -1) /* Time to hide it */
403 if (!hEmptyCursor)
404 hEmptyCursor = CreateCursor( 0, 1, 1, 1, 1,
405 "\xFF\xFF", "\xFF\xFF" );
406 CURSOR_SetCursor( hEmptyCursor );
409 return 0;
413 /**********************************************************************
414 * ClipCursor [USER.16]
416 void ClipCursor(LPRECT lpNewClipRect)
418 if (!lpNewClipRect) SetRectEmpty( &ClipCursorRect );
419 else CopyRect( &ClipCursorRect, lpNewClipRect );
423 /**********************************************************************
424 * GetClipCursor [USER.309]
426 void GetClipCursor(LPRECT lpRetClipRect)
428 if (lpRetClipRect != NULL)
429 CopyRect(lpRetClipRect, &ClipCursorRect);