New file, some helper functions for icon cache.
[wine/multimedia.git] / windows / display.c
blob4e82512883de419ac53115f1b8b1f48073194b09
1 /*
2 * DISPLAY driver
4 * Copyright 1998 Ulrich Weigand
6 */
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include "ts_xlib.h"
12 #include "ts_xresource.h"
13 #include "ts_xutil.h"
15 #include "windows.h"
16 #include "win.h"
17 #include "gdi.h"
18 #include "display.h"
19 #include "callback.h"
20 #include "heap.h"
21 #include "debug.h"
22 #include "debugtools.h"
24 Cursor DISPLAY_XCursor = None; /* Current X cursor */
26 BOOL32 DISPLAY_DisableWarpPointer = FALSE; /* hack; see DISPLAY_MoveCursor */
29 /***********************************************************************
30 * DISPLAY_Inquire (DISPLAY.101)
32 WORD WINAPI DISPLAY_Inquire(LPCURSORINFO lpCursorInfo)
34 lpCursorInfo->wXMickeys = 1;
35 lpCursorInfo->wYMickeys = 1;
37 return sizeof(CURSORINFO);
40 /***********************************************************************
41 * DISPLAY_DoSetCursor
43 static BOOL32 DISPLAY_DoSetCursor( CURSORICONINFO *ptr )
45 Pixmap pixmapBits, pixmapMask, pixmapAll;
46 XColor fg, bg;
47 Cursor cursor = None;
49 if (!ptr) /* Create an empty cursor */
51 static const char data[] = { 0 };
53 bg.red = bg.green = bg.blue = 0x0000;
54 pixmapBits = XCreateBitmapFromData( display, rootWindow, data, 1, 1 );
55 if (pixmapBits)
57 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
58 &bg, &bg, 0, 0 );
59 XFreePixmap( display, pixmapBits );
62 else /* Create the X cursor from the bits */
64 XImage *image;
66 if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
68 WARN(cursor, "Cursor has more than 1 bpp!\n" );
69 return FALSE;
72 /* Create a pixmap and transfer all the bits to it */
74 /* NOTE: Following hack works, but only because XFree depth
75 * 1 images really use 1 bit/pixel (and so the same layout
76 * as the Windows cursor data). Perhaps use a more generic
77 * algorithm here.
79 pixmapAll = XCreatePixmap( display, rootWindow,
80 ptr->nWidth, ptr->nHeight * 2, 1 );
81 image = XCreateImage( display, DefaultVisualOfScreen(screen),
82 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
83 ptr->nHeight * 2, 16, ptr->nWidthBytes);
84 if (image)
86 image->byte_order = MSBFirst;
87 image->bitmap_bit_order = MSBFirst;
88 image->bitmap_unit = 16;
89 _XInitImageFuncPtrs(image);
90 if (pixmapAll)
91 XPutImage( display, pixmapAll, BITMAP_monoGC, image,
92 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
93 image->data = NULL;
94 XDestroyImage( image );
97 /* Now create the 2 pixmaps for bits and mask */
99 pixmapBits = XCreatePixmap( display, rootWindow,
100 ptr->nWidth, ptr->nHeight, 1 );
101 pixmapMask = XCreatePixmap( display, rootWindow,
102 ptr->nWidth, ptr->nHeight, 1 );
104 /* Make sure everything went OK so far */
106 if (pixmapBits && pixmapMask && pixmapAll)
108 /* We have to do some magic here, as cursors are not fully
109 * compatible between Windows and X11. Under X11, there
110 * are only 3 possible color cursor: black, white and
111 * masked. So we map the 4th Windows color (invert the
112 * bits on the screen) to black. This require some boolean
113 * arithmetic:
115 * Windows | X11
116 * Xor And Result | Bits Mask Result
117 * 0 0 black | 0 1 background
118 * 0 1 no change | X 0 no change
119 * 1 0 white | 1 1 foreground
120 * 1 1 inverted | 0 1 background
122 * which gives:
123 * Bits = 'Xor' and not 'And'
124 * Mask = 'Xor' or not 'And'
126 * FIXME: apparently some servers do support 'inverted' color.
127 * I don't know if it's correct per the X spec, but maybe
128 * we ought to take advantage of it. -- AJ
130 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
131 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
132 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
133 0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
134 XSetFunction( display, BITMAP_monoGC, GXandReverse );
135 XCopyArea( display, pixmapAll, pixmapBits, BITMAP_monoGC,
136 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
137 XSetFunction( display, BITMAP_monoGC, GXorReverse );
138 XCopyArea( display, pixmapAll, pixmapMask, BITMAP_monoGC,
139 0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
140 XSetFunction( display, BITMAP_monoGC, GXcopy );
141 fg.red = fg.green = fg.blue = 0xffff;
142 bg.red = bg.green = bg.blue = 0x0000;
143 cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
144 &fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
147 /* Now free everything */
149 if (pixmapAll) XFreePixmap( display, pixmapAll );
150 if (pixmapBits) XFreePixmap( display, pixmapBits );
151 if (pixmapMask) XFreePixmap( display, pixmapMask );
154 if (cursor == None) return FALSE;
155 if (DISPLAY_XCursor != None) XFreeCursor( display, DISPLAY_XCursor );
156 DISPLAY_XCursor = cursor;
158 if (rootWindow != DefaultRootWindow(display) || !WIN_GetDesktop())
160 /* Set the cursor on the desktop window */
161 XDefineCursor( display, rootWindow, cursor );
163 else
165 /* FIXME: this won't work correctly with native USER !*/
167 /* Set the same cursor for all top-level windows */
168 HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD );
169 while(hwnd)
171 Window win = WIN_GetXWindow( hwnd );
172 if (win && win!=DefaultRootWindow(display))
173 XDefineCursor( display, win, cursor );
174 hwnd = GetWindow32( hwnd, GW_HWNDNEXT );
177 return TRUE;
180 /***********************************************************************
181 * DISPLAY_SetCursor (DISPLAY.102)
183 VOID WINAPI DISPLAY_SetCursor( CURSORICONINFO *lpCursor )
185 EnterCriticalSection( &X11DRV_CritSection );
186 CALL_LARGE_STACK( DISPLAY_DoSetCursor, lpCursor );
187 LeaveCriticalSection( &X11DRV_CritSection );
190 /***********************************************************************
191 * DISPLAY_MoveCursor (DISPLAY.103)
193 VOID WINAPI DISPLAY_MoveCursor( WORD wAbsX, WORD wAbsY )
196 * We do not want the to create MotionNotify events here,
197 * otherwise we will get an endless recursion:
198 * XMotionEvent -> MOUSEEVENTF_MOVE -> mouse_event -> DisplayMoveCursor
199 * -> XWarpPointer -> XMotionEvent -> ...
201 * Unfortunately, the XWarpPointer call does create a MotionNotify
202 * event. So, we use a hack: before MOUSE_SendEvent calls the mouse event
203 * procedure, it sets a global flag. If this flag is set, we skip the
204 * XWarpPointer call. If we are *not* called from within MOUSE_SendEvent,
205 * we will call XWarpPointer, which will create a MotionNotify event.
206 * Strictly speaking, this is also wrong, but that should normally not
207 * have any negative effects ...
209 * But first of all, we check whether we already are at the position
210 * are supposed to move to; if so, we don't need to do anything.
213 Window root, child;
214 int rootX, rootY, winX, winY;
215 unsigned int xstate;
217 if (DISPLAY_DisableWarpPointer) return;
219 if (!TSXQueryPointer( display, rootWindow, &root, &child,
220 &rootX, &rootY, &winX, &winY, &xstate ))
221 return;
223 if ( winX == wAbsX && winY == wAbsY )
224 return;
226 TRACE( cursor, "(%d,%d): moving from (%d,%d)\n", wAbsX, wAbsY, winX, winY );
228 TSXWarpPointer( display, rootWindow, rootWindow, 0, 0, 0, 0, wAbsX, wAbsY );
231 /***********************************************************************
232 * DISPLAY_CheckCursor (DISPLAY.104)
234 VOID WINAPI DISPLAY_CheckCursor()
236 FIXME( cursor, "stub\n" );
239 /***********************************************************************
240 * UserRepaintDisable (DISPLAY.500)
242 VOID WINAPI UserRepaintDisable( BOOL16 disable )
244 TRACE( cursor, "(%d): stub\n", disable );