4 * Copyright 1998 Ulrich Weigand
9 #include "ts_xresource.h"
22 #include "debugtools.h"
25 Cursor DISPLAY_XCursor
= None
; /* Current X cursor */
27 BOOL32 DISPLAY_DisableWarpPointer
= FALSE
; /* hack; see DISPLAY_MoveCursor */
30 /***********************************************************************
31 * DISPLAY_Inquire (DISPLAY.101)
33 WORD WINAPI
DISPLAY_Inquire(LPCURSORINFO lpCursorInfo
)
35 lpCursorInfo
->wXMickeys
= 1;
36 lpCursorInfo
->wYMickeys
= 1;
38 return sizeof(CURSORINFO
);
41 /***********************************************************************
44 static BOOL32
DISPLAY_DoSetCursor( CURSORICONINFO
*ptr
)
46 Pixmap pixmapBits
, pixmapMask
, pixmapAll
;
50 if (!ptr
) /* Create an empty cursor */
52 static const char data
[] = { 0 };
54 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
55 pixmapBits
= XCreateBitmapFromData( display
, rootWindow
, data
, 1, 1 );
58 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapBits
,
60 XFreePixmap( display
, pixmapBits
);
63 else /* Create the X cursor from the bits */
67 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
!= 1)
69 WARN(cursor
, "Cursor has more than 1 bpp!\n" );
73 /* Create a pixmap and transfer all the bits to it */
75 /* NOTE: Following hack works, but only because XFree depth
76 * 1 images really use 1 bit/pixel (and so the same layout
77 * as the Windows cursor data). Perhaps use a more generic
80 pixmapAll
= XCreatePixmap( display
, rootWindow
,
81 ptr
->nWidth
, ptr
->nHeight
* 2, 1 );
82 image
= XCreateImage( display
, DefaultVisualOfScreen(screen
),
83 1, ZPixmap
, 0, (char *)(ptr
+ 1), ptr
->nWidth
,
84 ptr
->nHeight
* 2, 16, ptr
->nWidthBytes
);
87 image
->byte_order
= MSBFirst
;
88 image
->bitmap_bit_order
= MSBFirst
;
89 image
->bitmap_unit
= 16;
90 _XInitImageFuncPtrs(image
);
92 XPutImage( display
, pixmapAll
, BITMAP_monoGC
, image
,
93 0, 0, 0, 0, ptr
->nWidth
, ptr
->nHeight
* 2 );
95 XDestroyImage( image
);
98 /* Now create the 2 pixmaps for bits and mask */
100 pixmapBits
= XCreatePixmap( display
, rootWindow
,
101 ptr
->nWidth
, ptr
->nHeight
, 1 );
102 pixmapMask
= XCreatePixmap( display
, rootWindow
,
103 ptr
->nWidth
, ptr
->nHeight
, 1 );
105 /* Make sure everything went OK so far */
107 if (pixmapBits
&& pixmapMask
&& pixmapAll
)
109 /* We have to do some magic here, as cursors are not fully
110 * compatible between Windows and X11. Under X11, there
111 * are only 3 possible color cursor: black, white and
112 * masked. So we map the 4th Windows color (invert the
113 * bits on the screen) to black. This require some boolean
117 * Xor And Result | Bits Mask Result
118 * 0 0 black | 0 1 background
119 * 0 1 no change | X 0 no change
120 * 1 0 white | 1 1 foreground
121 * 1 1 inverted | 0 1 background
124 * Bits = 'Xor' and not 'And'
125 * Mask = 'Xor' or not 'And'
127 * FIXME: apparently some servers do support 'inverted' color.
128 * I don't know if it's correct per the X spec, but maybe
129 * we ought to take advantage of it. -- AJ
131 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
132 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
133 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
134 0, 0, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
135 XSetFunction( display
, BITMAP_monoGC
, GXandReverse
);
136 XCopyArea( display
, pixmapAll
, pixmapBits
, BITMAP_monoGC
,
137 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
138 XSetFunction( display
, BITMAP_monoGC
, GXorReverse
);
139 XCopyArea( display
, pixmapAll
, pixmapMask
, BITMAP_monoGC
,
140 0, ptr
->nHeight
, ptr
->nWidth
, ptr
->nHeight
, 0, 0 );
141 XSetFunction( display
, BITMAP_monoGC
, GXcopy
);
142 fg
.red
= fg
.green
= fg
.blue
= 0xffff;
143 bg
.red
= bg
.green
= bg
.blue
= 0x0000;
144 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapMask
,
145 &fg
, &bg
, ptr
->ptHotSpot
.x
, ptr
->ptHotSpot
.y
);
148 /* Now free everything */
150 if (pixmapAll
) XFreePixmap( display
, pixmapAll
);
151 if (pixmapBits
) XFreePixmap( display
, pixmapBits
);
152 if (pixmapMask
) XFreePixmap( display
, pixmapMask
);
155 if (cursor
== None
) return FALSE
;
156 if (DISPLAY_XCursor
!= None
) XFreeCursor( display
, DISPLAY_XCursor
);
157 DISPLAY_XCursor
= cursor
;
159 if (rootWindow
!= DefaultRootWindow(display
) || !WIN_GetDesktop())
161 /* Set the cursor on the desktop window */
162 XDefineCursor( display
, rootWindow
, cursor
);
166 /* FIXME: this won't work correctly with native USER !*/
168 /* Set the same cursor for all top-level windows */
169 HWND32 hwnd
= GetWindow32( GetDesktopWindow32(), GW_CHILD
);
172 Window win
= X11DRV_WND_GetXWindow( hwnd
);
173 if (win
&& win
!=DefaultRootWindow(display
))
174 XDefineCursor( display
, win
, cursor
);
175 hwnd
= GetWindow32( hwnd
, GW_HWNDNEXT
);
181 /***********************************************************************
182 * DISPLAY_SetCursor (DISPLAY.102)
184 VOID WINAPI
DISPLAY_SetCursor( CURSORICONINFO
*lpCursor
)
186 EnterCriticalSection( &X11DRV_CritSection
);
187 CALL_LARGE_STACK( DISPLAY_DoSetCursor
, lpCursor
);
188 LeaveCriticalSection( &X11DRV_CritSection
);
191 /***********************************************************************
192 * DISPLAY_MoveCursor (DISPLAY.103)
194 VOID WINAPI
DISPLAY_MoveCursor( WORD wAbsX
, WORD wAbsY
)
197 * We do not want the to create MotionNotify events here,
198 * otherwise we will get an endless recursion:
199 * XMotionEvent -> MOUSEEVENTF_MOVE -> mouse_event -> DisplayMoveCursor
200 * -> XWarpPointer -> XMotionEvent -> ...
202 * Unfortunately, the XWarpPointer call does create a MotionNotify
203 * event. So, we use a hack: before MOUSE_SendEvent calls the mouse event
204 * procedure, it sets a global flag. If this flag is set, we skip the
205 * XWarpPointer call. If we are *not* called from within MOUSE_SendEvent,
206 * we will call XWarpPointer, which will create a MotionNotify event.
207 * Strictly speaking, this is also wrong, but that should normally not
208 * have any negative effects ...
210 * But first of all, we check whether we already are at the position
211 * are supposed to move to; if so, we don't need to do anything.
215 int rootX
, rootY
, winX
, winY
;
218 if (DISPLAY_DisableWarpPointer
) return;
220 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
221 &rootX
, &rootY
, &winX
, &winY
, &xstate
))
224 if ( winX
== wAbsX
&& winY
== wAbsY
)
227 TRACE( cursor
, "(%d,%d): moving from (%d,%d)\n", wAbsX
, wAbsY
, winX
, winY
);
229 TSXWarpPointer( display
, rootWindow
, rootWindow
, 0, 0, 0, 0, wAbsX
, wAbsY
);
232 /***********************************************************************
233 * DISPLAY_CheckCursor (DISPLAY.104)
235 VOID WINAPI
DISPLAY_CheckCursor()
237 FIXME( cursor
, "stub\n" );
240 /***********************************************************************
241 * UserRepaintDisable (DISPLAY.500)
243 VOID WINAPI
UserRepaintDisable( BOOL16 disable
)
245 TRACE( cursor
, "(%d): stub\n", disable
);