4 * Copyright 1998 Ulrich Weigand
12 #include "ts_xresource.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 /***********************************************************************
43 static BOOL32
DISPLAY_DoSetCursor( CURSORICONINFO
*ptr
)
45 Pixmap pixmapBits
, pixmapMask
, pixmapAll
;
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 );
57 cursor
= XCreatePixmapCursor( display
, pixmapBits
, pixmapBits
,
59 XFreePixmap( display
, pixmapBits
);
62 else /* Create the X cursor from the bits */
66 if (ptr
->bPlanes
* ptr
->bBitsPerPixel
!= 1)
68 WARN(cursor
, "Cursor has more than 1 bpp!\n" );
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
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
);
86 image
->byte_order
= MSBFirst
;
87 image
->bitmap_bit_order
= MSBFirst
;
88 image
->bitmap_unit
= 16;
89 _XInitImageFuncPtrs(image
);
91 XPutImage( display
, pixmapAll
, BITMAP_monoGC
, image
,
92 0, 0, 0, 0, ptr
->nWidth
, ptr
->nHeight
* 2 );
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
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
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
);
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
);
171 Window win
= WIN_GetXWindow( hwnd
);
172 if (win
&& win
!=DefaultRootWindow(display
))
173 XDefineCursor( display
, win
, cursor
);
174 hwnd
= GetWindow32( hwnd
, GW_HWNDNEXT
);
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.
214 int rootX
, rootY
, winX
, winY
;
217 if (DISPLAY_DisableWarpPointer
) return;
219 if (!TSXQueryPointer( display
, rootWindow
, &root
, &child
,
220 &rootX
, &rootY
, &winX
, &winY
, &xstate
))
223 if ( winX
== wAbsX
&& winY
== wAbsY
)
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
);