winex11.drv: Use unicode filenames for WM_DROPFILES.
[wine] / dlls / winex11.drv / mouse.c
1 /*
2  * X11 mouse driver
3  *
4  * Copyright 1998 Ulrich Weigand
5  * Copyright 2007 Henri Verbeet
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <X11/Xlib.h>
26 #include <stdarg.h>
27
28 #ifdef SONAME_LIBXCURSOR
29 # include <X11/Xcursor/Xcursor.h>
30 static void *xcursor_handle;
31 # define MAKE_FUNCPTR(f) static typeof(f) * p##f
32 MAKE_FUNCPTR(XcursorImageCreate);
33 MAKE_FUNCPTR(XcursorImageDestroy);
34 MAKE_FUNCPTR(XcursorImageLoadCursor);
35 # undef MAKE_FUNCPTR
36 #endif /* SONAME_LIBXCURSOR */
37
38 #define NONAMELESSUNION
39 #define NONAMELESSSTRUCT
40 #include "windef.h"
41 #include "winbase.h"
42 #include "wine/winuser16.h"
43
44 #include "x11drv.h"
45 #include "wine/server.h"
46 #include "wine/library.h"
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(cursor);
50
51 /**********************************************************************/
52
53 #ifndef Button6Mask
54 #define Button6Mask (1<<13)
55 #endif
56 #ifndef Button7Mask
57 #define Button7Mask (1<<14)
58 #endif
59
60 #define NB_BUTTONS   9     /* Windows can handle 5 buttons and the wheel too */
61
62 static const UINT button_down_flags[NB_BUTTONS] =
63 {
64     MOUSEEVENTF_LEFTDOWN,
65     MOUSEEVENTF_MIDDLEDOWN,
66     MOUSEEVENTF_RIGHTDOWN,
67     MOUSEEVENTF_WHEEL,
68     MOUSEEVENTF_WHEEL,
69     MOUSEEVENTF_XDOWN,  /* FIXME: horizontal wheel */
70     MOUSEEVENTF_XDOWN,
71     MOUSEEVENTF_XDOWN,
72     MOUSEEVENTF_XDOWN
73 };
74
75 static const UINT button_up_flags[NB_BUTTONS] =
76 {
77     MOUSEEVENTF_LEFTUP,
78     MOUSEEVENTF_MIDDLEUP,
79     MOUSEEVENTF_RIGHTUP,
80     0,
81     0,
82     MOUSEEVENTF_XUP,
83     MOUSEEVENTF_XUP,
84     MOUSEEVENTF_XUP,
85     MOUSEEVENTF_XUP
86 };
87
88 POINT cursor_pos;
89 static HWND cursor_window;
90 static DWORD last_time_modified;
91 static RECT cursor_clip; /* Cursor clipping rect */
92 static XContext cursor_context;
93
94 BOOL CDECL X11DRV_SetCursorPos( INT x, INT y );
95
96
97 /***********************************************************************
98  *              X11DRV_Xcursor_Init
99  *
100  * Load the Xcursor library for use.
101  */
102 void X11DRV_Xcursor_Init(void)
103 {
104 #ifdef SONAME_LIBXCURSOR
105     xcursor_handle = wine_dlopen(SONAME_LIBXCURSOR, RTLD_NOW, NULL, 0);
106     if (!xcursor_handle)  /* wine_dlopen failed. */
107     {
108         WARN("Xcursor failed to load.  Using fallback code.\n");
109         return;
110     }
111 #define LOAD_FUNCPTR(f) \
112         p##f = wine_dlsym(xcursor_handle, #f, NULL, 0)
113
114     LOAD_FUNCPTR(XcursorImageCreate);
115     LOAD_FUNCPTR(XcursorImageDestroy);
116     LOAD_FUNCPTR(XcursorImageLoadCursor);
117 #undef LOAD_FUNCPTR
118 #endif /* SONAME_LIBXCURSOR */
119 }
120
121
122 /***********************************************************************
123  *              get_coords
124  *
125  * get the coordinates of a mouse event
126  */
127 static inline void get_coords( HWND hwnd, Window window, int x, int y, POINT *pt )
128 {
129     struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
130
131     if (!data) return;
132
133     if (window == data->client_window)
134     {
135         pt->x = x + data->client_rect.left;
136         pt->y = y + data->client_rect.top;
137     }
138     else
139     {
140         pt->x = x + data->whole_rect.left;
141         pt->y = y + data->whole_rect.top;
142     }
143 }
144
145 /***********************************************************************
146  *              clip_point_to_rect
147  *
148  * Clip point to the provided rectangle
149  */
150 static inline void clip_point_to_rect( LPCRECT rect, LPPOINT pt )
151 {
152     if      (pt->x <  rect->left)   pt->x = rect->left;
153     else if (pt->x >= rect->right)  pt->x = rect->right - 1;
154     if      (pt->y <  rect->top)    pt->y = rect->top;
155     else if (pt->y >= rect->bottom) pt->y = rect->bottom - 1;
156 }
157
158 /***********************************************************************
159  *              update_button_state
160  *
161  * Update the button state with what X provides us
162  */
163 static inline void update_button_state( unsigned int state )
164 {
165     key_state_table[VK_LBUTTON] = (state & Button1Mask ? 0x80 : 0);
166     key_state_table[VK_MBUTTON] = (state & Button2Mask ? 0x80 : 0);
167     key_state_table[VK_RBUTTON] = (state & Button3Mask ? 0x80 : 0);
168     /* X-buttons are not reported from XQueryPointer */
169 }
170
171 /***********************************************************************
172  *              get_empty_cursor
173  */
174 static Cursor get_empty_cursor(void)
175 {
176     static Cursor cursor;
177     static const char data[] = { 0 };
178
179     if (!cursor)
180     {
181         XColor bg;
182         Pixmap pixmap;
183
184         bg.red = bg.green = bg.blue = 0x0000;
185         pixmap = XCreateBitmapFromData( gdi_display, root_window, data, 1, 1 );
186         if (pixmap)
187         {
188             cursor = XCreatePixmapCursor( gdi_display, pixmap, pixmap, &bg, &bg, 0, 0 );
189             XFreePixmap( gdi_display, pixmap );
190         }
191     }
192     return cursor;
193 }
194
195 /***********************************************************************
196  *              get_x11_cursor
197  */
198 Cursor get_x11_cursor( HCURSOR handle )
199 {
200     Cursor cursor;
201
202     if (!handle) return get_empty_cursor();
203
204     if (cursor_context && !XFindContext( gdi_display, (XID)handle, cursor_context, (char **)&cursor ))
205         return cursor;
206     return 0;
207 }
208
209 /***********************************************************************
210  *              set_window_cursor
211  */
212 void set_window_cursor( HWND hwnd, HCURSOR handle )
213 {
214     struct x11drv_win_data *data;
215     Cursor cursor;
216
217     if (!(data = X11DRV_get_win_data( hwnd ))) return;
218
219     wine_tsx11_lock();
220     if ((cursor = get_x11_cursor( handle )))
221     {
222         TRACE( "%p xid %lx\n", handle, cursor );
223         XDefineCursor( gdi_display, data->whole_window, cursor );
224         /* Make the change take effect immediately */
225         XFlush( gdi_display );
226         data->cursor = handle;
227     }
228     wine_tsx11_unlock();
229 }
230
231 /***********************************************************************
232  *              update_mouse_state
233  *
234  * Update the various window states on a mouse event.
235  */
236 static void update_mouse_state( HWND hwnd, Window window, int x, int y, unsigned int state, POINT *pt )
237 {
238     struct x11drv_thread_data *data = x11drv_thread_data();
239
240     get_coords( hwnd, window, x, y, pt );
241
242     cursor_window = hwnd;
243
244     /* update the wine server Z-order */
245
246     if (window != data->grab_window &&
247         /* ignore event if a button is pressed, since the mouse is then grabbed too */
248         !(state & (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask|Button6Mask|Button7Mask)))
249     {
250         SERVER_START_REQ( update_window_zorder )
251         {
252             req->window      = wine_server_user_handle( hwnd );
253             req->rect.left   = pt->x;
254             req->rect.top    = pt->y;
255             req->rect.right  = pt->x + 1;
256             req->rect.bottom = pt->y + 1;
257             wine_server_call( req );
258         }
259         SERVER_END_REQ;
260     }
261 }
262
263
264 /***********************************************************************
265  *           get_key_state
266  */
267 static WORD get_key_state(void)
268 {
269     WORD ret = 0;
270
271     if (GetSystemMetrics( SM_SWAPBUTTON ))
272     {
273         if (key_state_table[VK_RBUTTON] & 0x80) ret |= MK_LBUTTON;
274         if (key_state_table[VK_LBUTTON] & 0x80) ret |= MK_RBUTTON;
275     }
276     else
277     {
278         if (key_state_table[VK_LBUTTON] & 0x80) ret |= MK_LBUTTON;
279         if (key_state_table[VK_RBUTTON] & 0x80) ret |= MK_RBUTTON;
280     }
281     if (key_state_table[VK_MBUTTON] & 0x80)  ret |= MK_MBUTTON;
282     if (key_state_table[VK_SHIFT] & 0x80)    ret |= MK_SHIFT;
283     if (key_state_table[VK_CONTROL] & 0x80)  ret |= MK_CONTROL;
284     if (key_state_table[VK_XBUTTON1] & 0x80) ret |= MK_XBUTTON1;
285     if (key_state_table[VK_XBUTTON2] & 0x80) ret |= MK_XBUTTON2;
286     return ret;
287 }
288
289
290 /***********************************************************************
291  *           queue_raw_mouse_message
292  */
293 static void queue_raw_mouse_message( UINT message, HWND hwnd, DWORD x, DWORD y,
294                                      DWORD data, DWORD time, DWORD extra_info, UINT injected_flags )
295 {
296     MSLLHOOKSTRUCT hook;
297     HCURSOR cursor;
298
299     hook.pt.x        = x;
300     hook.pt.y        = y;
301     hook.mouseData   = MAKELONG( 0, data );
302     hook.flags       = injected_flags;
303     hook.time        = time;
304     hook.dwExtraInfo = extra_info;
305
306     last_time_modified = GetTickCount();
307     if (HOOK_CallHooks( WH_MOUSE_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
308
309     SERVER_START_REQ( send_hardware_message )
310     {
311         req->id       = (injected_flags & LLMHF_INJECTED) ? 0 : GetCurrentThreadId();
312         req->win      = wine_server_user_handle( hwnd );
313         req->msg      = message;
314         req->wparam   = MAKEWPARAM( get_key_state(), data );
315         req->lparam   = 0;
316         req->x        = x;
317         req->y        = y;
318         req->time     = time;
319         req->info     = extra_info;
320         wine_server_call( req );
321         cursor = (reply->count >= 0) ? wine_server_ptr_handle(reply->cursor) : 0;
322     }
323     SERVER_END_REQ;
324
325     if (hwnd)
326     {
327         Cursor xcursor;
328         struct x11drv_win_data *data = X11DRV_get_win_data( hwnd );
329         if (data && cursor != data->cursor)
330         {
331             wine_tsx11_lock();
332             if ((xcursor = get_x11_cursor( cursor )))
333                 XDefineCursor( gdi_display, data->whole_window, xcursor );
334             data->cursor = cursor;
335             wine_tsx11_unlock();
336         }
337     }
338 }
339
340
341 /***********************************************************************
342  *              X11DRV_send_mouse_input
343  */
344 void X11DRV_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y,
345                               DWORD data, DWORD time, DWORD extra_info, UINT injected_flags )
346 {
347     POINT pt;
348
349     if (flags & MOUSEEVENTF_MOVE && flags & MOUSEEVENTF_ABSOLUTE)
350     {
351         if (injected_flags & LLMHF_INJECTED)
352         {
353             pt.x = (x * screen_width) >> 16;
354             pt.y = (y * screen_height) >> 16;
355         }
356         else
357         {
358             pt.x = x;
359             pt.y = y;
360             wine_tsx11_lock();
361             if (cursor_pos.x == x && cursor_pos.y == y &&
362                 (flags & ~(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE)))
363                 flags &= ~MOUSEEVENTF_MOVE;
364             wine_tsx11_unlock();
365         }
366     }
367     else if (flags & MOUSEEVENTF_MOVE)
368     {
369         int accel[3], xMult = 1, yMult = 1;
370
371         /* dx and dy can be negative numbers for relative movements */
372         SystemParametersInfoW(SPI_GETMOUSE, 0, accel, 0);
373
374         if (abs(x) > accel[0] && accel[2] != 0)
375         {
376             xMult = 2;
377             if ((abs(x) > accel[1]) && (accel[2] == 2)) xMult = 4;
378         }
379         if (abs(y) > accel[0] && accel[2] != 0)
380         {
381             yMult = 2;
382             if ((abs(y) > accel[1]) && (accel[2] == 2)) yMult = 4;
383         }
384
385         wine_tsx11_lock();
386         pt.x = cursor_pos.x + (long)x * xMult;
387         pt.y = cursor_pos.y + (long)y * yMult;
388         wine_tsx11_unlock();
389     }
390     else
391     {
392         wine_tsx11_lock();
393         pt = cursor_pos;
394         wine_tsx11_unlock();
395     }
396
397     if (flags & MOUSEEVENTF_MOVE)
398     {
399         queue_raw_mouse_message( WM_MOUSEMOVE, hwnd, pt.x, pt.y, data, time,
400                                  extra_info, injected_flags );
401         if ((injected_flags & LLMHF_INJECTED) &&
402             ((flags & MOUSEEVENTF_ABSOLUTE) || x || y))  /* we have to actually move the cursor */
403         {
404             X11DRV_SetCursorPos( pt.x, pt.y );
405         }
406         else
407         {
408             wine_tsx11_lock();
409             clip_point_to_rect( &cursor_clip, &pt);
410             cursor_pos = pt;
411             wine_tsx11_unlock();
412         }
413     }
414     if (flags & MOUSEEVENTF_LEFTDOWN)
415     {
416         key_state_table[VK_LBUTTON] |= 0xc0;
417         queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONDOWN : WM_LBUTTONDOWN,
418                                  hwnd, pt.x, pt.y, data, time, extra_info, injected_flags );
419     }
420     if (flags & MOUSEEVENTF_LEFTUP)
421     {
422         key_state_table[VK_LBUTTON] &= ~0x80;
423         queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONUP : WM_LBUTTONUP,
424                                  hwnd, pt.x, pt.y, data, time, extra_info, injected_flags );
425     }
426     if (flags & MOUSEEVENTF_RIGHTDOWN)
427     {
428         key_state_table[VK_RBUTTON] |= 0xc0;
429         queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONDOWN : WM_RBUTTONDOWN,
430                                  hwnd, pt.x, pt.y, data, time, extra_info, injected_flags );
431     }
432     if (flags & MOUSEEVENTF_RIGHTUP)
433     {
434         key_state_table[VK_RBUTTON] &= ~0x80;
435         queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONUP : WM_RBUTTONUP,
436                                  hwnd, pt.x, pt.y, data, time, extra_info, injected_flags );
437     }
438     if (flags & MOUSEEVENTF_MIDDLEDOWN)
439     {
440         key_state_table[VK_MBUTTON] |= 0xc0;
441         queue_raw_mouse_message( WM_MBUTTONDOWN, hwnd, pt.x, pt.y, data, time,
442                                  extra_info, injected_flags );
443     }
444     if (flags & MOUSEEVENTF_MIDDLEUP)
445     {
446         key_state_table[VK_MBUTTON] &= ~0x80;
447         queue_raw_mouse_message( WM_MBUTTONUP, hwnd, pt.x, pt.y, data, time,
448                                  extra_info, injected_flags );
449     }
450     if (flags & MOUSEEVENTF_WHEEL)
451     {
452         queue_raw_mouse_message( WM_MOUSEWHEEL, hwnd, pt.x, pt.y, data, time,
453                                  extra_info, injected_flags );
454     }
455     if (flags & MOUSEEVENTF_XDOWN)
456     {
457         key_state_table[VK_XBUTTON1 + data - 1] |= 0xc0;
458         queue_raw_mouse_message( WM_XBUTTONDOWN, hwnd, pt.x, pt.y, data, time,
459                                  extra_info, injected_flags );
460     }
461     if (flags & MOUSEEVENTF_XUP)
462     {
463         key_state_table[VK_XBUTTON1 + data - 1] &= ~0x80;
464         queue_raw_mouse_message( WM_XBUTTONUP, hwnd, pt.x, pt.y, data, time,
465                                  extra_info, injected_flags );
466     }
467 }
468
469
470 /***********************************************************************
471  *              check_alpha_zero
472  *
473  * Generally 32 bit bitmaps have an alpha channel which is used in favor of the
474  * AND mask.  However, if all pixels have alpha = 0x00, the bitmap is treated
475  * like one without alpha and the masks are used.  As soon as one pixel has
476  * alpha != 0x00, and the mask ignored as described in the docs.
477  *
478  * This is most likely for applications which create the bitmaps with
479  * CreateDIBitmap, which creates a device dependent bitmap, so the format that
480  * arrives when loading depends on the screen's bpp.  Apps that were written at
481  * 8 / 16 bpp times do not know about the 32 bit alpha, so they would get a
482  * completely transparent cursor on 32 bit displays.
483  *
484  * Non-32 bit bitmaps always use the AND mask.
485  */
486 static BOOL check_alpha_zero(CURSORICONINFO *ptr, unsigned char *xor_bits)
487 {
488     int x, y;
489     unsigned char *xor_ptr;
490
491     if (ptr->bBitsPerPixel == 32)
492     {
493         for (y = 0; y < ptr->nHeight; ++y)
494         {
495             xor_ptr = xor_bits + (y * ptr->nWidthBytes);
496             for (x = 0; x < ptr->nWidth; ++x)
497             {
498                 if (xor_ptr[3] != 0x00)
499                 {
500                     return FALSE;
501                 }
502                 xor_ptr+=4;
503             }
504         }
505     }
506
507     return TRUE;
508 }
509
510
511 #ifdef SONAME_LIBXCURSOR
512
513 /***********************************************************************
514  *              create_cursor_image
515  *
516  * Create an XcursorImage from a CURSORICONINFO
517  */
518 static XcursorImage *create_cursor_image( CURSORICONINFO *ptr )
519 {
520     static const unsigned char convert_5to8[] =
521     {
522         0x00, 0x08, 0x10, 0x19, 0x21, 0x29, 0x31, 0x3a,
523         0x42, 0x4a, 0x52, 0x5a, 0x63, 0x6b, 0x73, 0x7b,
524         0x84, 0x8c, 0x94, 0x9c, 0xa5, 0xad, 0xb5, 0xbd,
525         0xc5, 0xce, 0xd6, 0xde, 0xe6, 0xef, 0xf7, 0xff,
526     };
527     static const unsigned char convert_6to8[] =
528     {
529         0x00, 0x04, 0x08, 0x0c, 0x10, 0x14, 0x18, 0x1c,
530         0x20, 0x24, 0x28, 0x2d, 0x31, 0x35, 0x39, 0x3d,
531         0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d,
532         0x61, 0x65, 0x69, 0x6d, 0x71, 0x75, 0x79, 0x7d,
533         0x82, 0x86, 0x8a, 0x8e, 0x92, 0x96, 0x9a, 0x9e,
534         0xa2, 0xa6, 0xaa, 0xae, 0xb2, 0xb6, 0xba, 0xbe,
535         0xc2, 0xc6, 0xca, 0xce, 0xd2, 0xd7, 0xdb, 0xdf,
536         0xe3, 0xe7, 0xeb, 0xef, 0xf3, 0xf7, 0xfb, 0xff,
537     };
538     int x;
539     int y;
540     int and_size;
541     unsigned char *and_bits, *and_ptr, *xor_bits, *xor_ptr;
542     int and_width_bytes, xor_width_bytes;
543     XcursorPixel *pixel_ptr;
544     XcursorImage *image;
545     unsigned char tmp;
546     BOOL alpha_zero;
547
548     and_width_bytes = 2 * ((ptr->nWidth+15) / 16);
549     xor_width_bytes = ptr->nWidthBytes;
550
551     and_size = ptr->nHeight * and_width_bytes;
552     and_ptr = and_bits = (unsigned char *)(ptr + 1);
553
554     xor_ptr = xor_bits = and_ptr + and_size;
555
556     image = pXcursorImageCreate( ptr->nWidth, ptr->nHeight );
557     if (!image) return NULL;
558
559     pixel_ptr = image->pixels;
560
561     alpha_zero = check_alpha_zero(ptr, xor_bits);
562
563     /* On windows, to calculate the color for a pixel, first an AND is done
564      * with the background and the "and" bitmap, then an XOR with the "xor"
565      * bitmap. This means that when the data in the "and" bitmap is 0, the
566      * pixel will get the color as specified in the "xor" bitmap.
567      * However, if the data in the "and" bitmap is 1, the result will be the
568      * background XOR'ed with the value in the "xor" bitmap. In case the "xor"
569      * data is completely black (0x000000) the pixel will become transparent,
570      * in case it's white (0xffffff) the pixel will become the inverse of the
571      * background color.
572      *
573      * Since we can't support inverting colors, we map the grayscale value of
574      * the "xor" data to the alpha channel, and xor the color with either
575      * black or white.
576      */
577     for (y = 0; y < ptr->nHeight; ++y)
578     {
579         and_ptr = and_bits + (y * and_width_bytes);
580         xor_ptr = xor_bits + (y * xor_width_bytes);
581
582         for (x = 0; x < ptr->nWidth; ++x)
583         {
584             /* Xcursor pixel data is in ARGB format, with A in the high byte */
585             switch (ptr->bBitsPerPixel)
586             {
587                 case 32:
588                     /* BGRA, 8 bits each */
589                     *pixel_ptr = *xor_ptr++;
590                     *pixel_ptr |= *xor_ptr++ << 8;
591                     *pixel_ptr |= *xor_ptr++ << 16;
592                     *pixel_ptr |= *xor_ptr++ << 24;
593                     break;
594
595                 case 24:
596                     /* BGR, 8 bits each */
597                     *pixel_ptr = *xor_ptr++;
598                     *pixel_ptr |= *xor_ptr++ << 8;
599                     *pixel_ptr |= *xor_ptr++ << 16;
600                     break;
601
602                 case 16:
603                     /* BGR, 5 red, 6 green, 5 blue */
604                     /* [gggbbbbb][rrrrrggg] -> [xxxxxxxx][rrrrrrrr][gggggggg][bbbbbbbb] */
605                     *pixel_ptr = convert_5to8[*xor_ptr & 0x1f];
606                     tmp = (*xor_ptr++ & 0xe0) >> 5;
607                     tmp |= (*xor_ptr & 0x07) << 3;
608                     *pixel_ptr |= convert_6to8[tmp] << 16;
609                     *pixel_ptr |= convert_5to8[*xor_ptr++ >> 3] << 24;
610                     break;
611
612                 case 1:
613                     if (*xor_ptr & (1 << (7 - (x & 7)))) *pixel_ptr = 0xffffff;
614                     else *pixel_ptr = 0;
615                     if ((x & 7) == 7) ++xor_ptr;
616                     break;
617
618                 default:
619                     FIXME("Currently no support for cursors with %d bits per pixel\n", ptr->bBitsPerPixel);
620                     return 0;
621             }
622
623             if (alpha_zero)
624             {
625                 /* Alpha channel */
626                 if (~*and_ptr & (1 << (7 - (x & 7)))) *pixel_ptr |= 0xff << 24;
627                 else if (*pixel_ptr)
628                 {
629                     int alpha = (*pixel_ptr & 0xff) * 0.30f
630                             + ((*pixel_ptr & 0xff00) >> 8) * 0.55f
631                             + ((*pixel_ptr & 0xff0000) >> 16) * 0.15f;
632                     *pixel_ptr ^= ((x + y) % 2) ? 0xffffff : 0x000000;
633                     *pixel_ptr |= alpha << 24;
634                 }
635                 if ((x & 7) == 7) ++and_ptr;
636             }
637             ++pixel_ptr;
638         }
639     }
640
641     return image;
642 }
643
644
645 /***********************************************************************
646  *              create_xcursor_cursor
647  *
648  * Use Xcursor to create an X cursor from a Windows one.
649  */
650 static Cursor create_xcursor_cursor( Display *display, CURSORICONINFO *ptr )
651 {
652     Cursor cursor;
653     XcursorImage *image;
654
655     image = create_cursor_image( ptr );
656     if (!image) return 0;
657
658     /* Make sure hotspot is valid */
659     image->xhot = ptr->ptHotSpot.x;
660     image->yhot = ptr->ptHotSpot.y;
661     if (image->xhot >= image->width ||
662         image->yhot >= image->height)
663     {
664         image->xhot = image->width / 2;
665         image->yhot = image->height / 2;
666     }
667
668     image->delay = 0;
669
670     cursor = pXcursorImageLoadCursor( display, image );
671     pXcursorImageDestroy( image );
672
673     return cursor;
674 }
675
676 #endif /* SONAME_LIBXCURSOR */
677
678
679 /***********************************************************************
680  *              create_cursor
681  *
682  * Create an X cursor from a Windows one.
683  */
684 static Cursor create_cursor( Display *display, CURSORICONINFO *ptr )
685 {
686     Pixmap pixmapBits, pixmapMask, pixmapMaskInv = 0, pixmapAll;
687     XColor fg, bg;
688     Cursor cursor = None;
689     POINT hotspot;
690     char *bitMask32 = NULL;
691     BOOL alpha_zero = TRUE;
692
693     if (!ptr) return get_empty_cursor();
694
695 #ifdef SONAME_LIBXCURSOR
696     if (pXcursorImageLoadCursor) return create_xcursor_cursor( display, ptr );
697 #endif
698
699     /* Create the X cursor from the bits */
700     {
701         XImage *image;
702         GC gc;
703
704         TRACE("Bitmap %dx%d planes=%d bpp=%d bytesperline=%d\n",
705             ptr->nWidth, ptr->nHeight, ptr->bPlanes, ptr->bBitsPerPixel,
706             ptr->nWidthBytes);
707
708         /* Create a pixmap and transfer all the bits to it */
709
710         /* NOTE: Following hack works, but only because XFree depth
711          *       1 images really use 1 bit/pixel (and so the same layout
712          *       as the Windows cursor data). Perhaps use a more generic
713          *       algorithm here.
714          */
715         /* This pixmap will be written with two bitmaps. The first is
716          *  the mask and the second is the image.
717          */
718         if (!(pixmapAll = XCreatePixmap( display, root_window,
719                   ptr->nWidth, ptr->nHeight * 2, 1 )))
720             return 0;
721         if (!(image = XCreateImage( display, visual,
722                 1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
723                 ptr->nHeight * 2, 16, ptr->nWidthBytes/ptr->bBitsPerPixel)))
724         {
725             XFreePixmap( display, pixmapAll );
726             return 0;
727         }
728         gc = XCreateGC( display, pixmapAll, 0, NULL );
729         XSetGraphicsExposures( display, gc, False );
730         image->byte_order = MSBFirst;
731         image->bitmap_bit_order = MSBFirst;
732         image->bitmap_unit = 16;
733         _XInitImageFuncPtrs(image);
734         if (ptr->bPlanes * ptr->bBitsPerPixel == 1)
735         {
736             /* A plain old white on black cursor. */
737             fg.red = fg.green = fg.blue = 0xffff;
738             bg.red = bg.green = bg.blue = 0x0000;
739             XPutImage( display, pixmapAll, gc, image,
740                 0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
741         }
742         else
743         {
744             int     rbits, gbits, bbits, red, green, blue;
745             int     rfg, gfg, bfg, rbg, gbg, bbg;
746             int     rscale, gscale, bscale;
747             int     x, y, xmax, ymax, byteIndex, xorIndex;
748             unsigned char *theMask, *theImage, theChar;
749             int     threshold, fgBits, bgBits, bitShifted;
750             BYTE    pXorBits[128];   /* Up to 32x32 icons */
751
752             switch (ptr->bBitsPerPixel)
753             {
754             case 32:
755                 bitMask32 = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
756                                        ptr->nWidth * ptr->nHeight / 8 );
757                 /* Fallthrough */
758             case 24:
759                 rbits = 8;
760                 gbits = 8;
761                 bbits = 8;
762                 threshold = 0x40;
763                 break;
764             case 16:
765                 rbits = 5;
766                 gbits = 6;
767                 bbits = 5;
768                 threshold = 0x40;
769                 break;
770             default:
771                 FIXME("Currently no support for cursors with %d bits per pixel\n",
772                   ptr->bBitsPerPixel);
773                 XFreePixmap( display, pixmapAll );
774                 XFreeGC( display, gc );
775                 image->data = NULL;
776                 XDestroyImage( image );
777                 return 0;
778             }
779             /* The location of the mask. */
780             theMask = (unsigned char *)(ptr + 1);
781             /* The mask should still be 1 bit per pixel. The color image
782              * should immediately follow the mask.
783              */
784             theImage = &theMask[ptr->nWidth/8 * ptr->nHeight];
785             rfg = gfg = bfg = rbg = gbg = bbg = 0;
786             byteIndex = 0;
787             xorIndex = 0;
788             fgBits = 0;
789             bitShifted = 0x01;
790             xmax = (ptr->nWidth > 32) ? 32 : ptr->nWidth;
791             if (ptr->nWidth > 32) {
792                 ERR("Got a %dx%d cursor. Cannot handle larger than 32x32.\n",
793                   ptr->nWidth, ptr->nHeight);
794             }
795             ymax = (ptr->nHeight > 32) ? 32 : ptr->nHeight;
796             alpha_zero = check_alpha_zero(ptr, theImage);
797
798             memset(pXorBits, 0, 128);
799             for (y=0; y<ymax; y++)
800             {
801                 for (x=0; x<xmax; x++)
802                 {
803                         red = green = blue = 0;
804                         switch (ptr->bBitsPerPixel)
805                         {
806                         case 32:
807                             theChar = theImage[byteIndex++];
808                             blue = theChar;
809                             theChar = theImage[byteIndex++];
810                             green = theChar;
811                             theChar = theImage[byteIndex++];
812                             red = theChar;
813                             theChar = theImage[byteIndex++];
814                             /* If the alpha channel is >5% transparent,
815                              * assume that we can add it to the bitMask32.
816                              */
817                             if (theChar > 0x0D)
818                                 *(bitMask32 + (y*xmax+x)/8) |= 1 << (x & 7);
819                             break;
820                         case 24:
821                             theChar = theImage[byteIndex++];
822                             blue = theChar;
823                             theChar = theImage[byteIndex++];
824                             green = theChar;
825                             theChar = theImage[byteIndex++];
826                             red = theChar;
827                             break;
828                         case 16:
829                             theChar = theImage[byteIndex++];
830                             blue = theChar & 0x1F;
831                             green = (theChar & 0xE0) >> 5;
832                             theChar = theImage[byteIndex++];
833                             green |= (theChar & 0x07) << 3;
834                             red = (theChar & 0xF8) >> 3;
835                             break;
836                         }
837
838                     if (red+green+blue > threshold)
839                     {
840                         rfg += red;
841                         gfg += green;
842                         bfg += blue;
843                         fgBits++;
844                         pXorBits[xorIndex] |= bitShifted;
845                     }
846                     else
847                     {
848                         rbg += red;
849                         gbg += green;
850                         bbg += blue;
851                     }
852                     if (x%8 == 7)
853                     {
854                         bitShifted = 0x01;
855                         xorIndex++;
856                     }
857                     else
858                         bitShifted = bitShifted << 1;
859                 }
860             }
861             rscale = 1 << (16 - rbits);
862             gscale = 1 << (16 - gbits);
863             bscale = 1 << (16 - bbits);
864             if (fgBits)
865             {
866                 fg.red   = rfg * rscale / fgBits;
867                 fg.green = gfg * gscale / fgBits;
868                 fg.blue  = bfg * bscale / fgBits;
869             }
870             else fg.red = fg.green = fg.blue = 0;
871             bgBits = xmax * ymax - fgBits;
872             if (bgBits)
873             {
874                 bg.red   = rbg * rscale / bgBits;
875                 bg.green = gbg * gscale / bgBits;
876                 bg.blue  = bbg * bscale / bgBits;
877             }
878             else bg.red = bg.green = bg.blue = 0;
879             pixmapBits = XCreateBitmapFromData( display, root_window, (char *)pXorBits, xmax, ymax );
880             if (!pixmapBits)
881             {
882                 HeapFree( GetProcessHeap(), 0, bitMask32 );
883                 XFreePixmap( display, pixmapAll );
884                 XFreeGC( display, gc );
885                 image->data = NULL;
886                 XDestroyImage( image );
887                 return 0;
888             }
889
890             /* Put the mask. */
891             XPutImage( display, pixmapAll, gc, image,
892                    0, 0, 0, 0, ptr->nWidth, ptr->nHeight );
893             XSetFunction( display, gc, GXcopy );
894             /* Put the image */
895             XCopyArea( display, pixmapBits, pixmapAll, gc,
896                        0, 0, xmax, ymax, 0, ptr->nHeight );
897             XFreePixmap( display, pixmapBits );
898         }
899         image->data = NULL;
900         XDestroyImage( image );
901
902         /* Now create the 2 pixmaps for bits and mask */
903
904         pixmapBits = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
905         if (alpha_zero)
906         {
907             pixmapMaskInv = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
908             pixmapMask = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
909
910             /* Make sure everything went OK so far */
911             if (pixmapBits && pixmapMask && pixmapMaskInv)
912             {
913                 /* We have to do some magic here, as cursors are not fully
914                  * compatible between Windows and X11. Under X11, there are
915                  * only 3 possible color cursor: black, white and masked. So
916                  * we map the 4th Windows color (invert the bits on the screen)
917                  * to black and an additional white bit on an other place
918                  * (+1,+1). This require some boolean arithmetic:
919                  *
920                  *         Windows          |          X11
921                  * And    Xor      Result   |   Bits     Mask     Result
922                  *  0      0     black      |    0        1     background
923                  *  0      1     white      |    1        1     foreground
924                  *  1      0     no change  |    X        0     no change
925                  *  1      1     inverted   |    0        1     background
926                  *
927                  * which gives:
928                  *  Bits = not 'And' and 'Xor' or 'And2' and 'Xor2'
929                  *  Mask = not 'And' or 'Xor' or 'And2' and 'Xor2'
930                  *
931                  * FIXME: apparently some servers do support 'inverted' color.
932                  * I don't know if it's correct per the X spec, but maybe we
933                  * ought to take advantage of it.  -- AJ
934                  */
935                 XSetFunction( display, gc, GXcopy );
936                 XCopyArea( display, pixmapAll, pixmapBits, gc,
937                            0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
938                 XCopyArea( display, pixmapAll, pixmapMask, gc,
939                            0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
940                 XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
941                            0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
942                 XSetFunction( display, gc, GXand );
943                 XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
944                            0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
945                 XSetFunction( display, gc, GXandReverse );
946                 XCopyArea( display, pixmapAll, pixmapBits, gc,
947                            0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
948                 XSetFunction( display, gc, GXorReverse );
949                 XCopyArea( display, pixmapAll, pixmapMask, gc,
950                            0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
951                 /* Additional white */
952                 XSetFunction( display, gc, GXor );
953                 XCopyArea( display, pixmapMaskInv, pixmapMask, gc,
954                            0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
955                 XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
956                            0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
957                 XSetFunction( display, gc, GXcopy );
958             }
959         }
960         else
961         {
962             pixmapMask = XCreateBitmapFromData( display, root_window,
963                                                 bitMask32, ptr->nWidth,
964                                                 ptr->nHeight );
965         }
966
967         /* Make sure hotspot is valid */
968         hotspot.x = ptr->ptHotSpot.x;
969         hotspot.y = ptr->ptHotSpot.y;
970         if (hotspot.x < 0 || hotspot.x >= ptr->nWidth ||
971             hotspot.y < 0 || hotspot.y >= ptr->nHeight)
972         {
973             hotspot.x = ptr->nWidth / 2;
974             hotspot.y = ptr->nHeight / 2;
975         }
976
977         if (pixmapBits && pixmapMask)
978             cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
979                                           &fg, &bg, hotspot.x, hotspot.y );
980
981         /* Now free everything */
982
983         if (pixmapAll) XFreePixmap( display, pixmapAll );
984         if (pixmapBits) XFreePixmap( display, pixmapBits );
985         if (pixmapMask) XFreePixmap( display, pixmapMask );
986         if (pixmapMaskInv) XFreePixmap( display, pixmapMaskInv );
987         HeapFree( GetProcessHeap(), 0, bitMask32 );
988         XFreeGC( display, gc );
989     }
990     return cursor;
991 }
992
993 /***********************************************************************
994  *              CreateCursorIcon (X11DRV.@)
995  */
996 void CDECL X11DRV_CreateCursorIcon( HCURSOR handle, CURSORICONINFO *info )
997 {
998     static const WORD ICON_HOTSPOT = 0x4242;
999     Cursor cursor;
1000
1001     /* ignore icons (FIXME: shouldn't use magic hotspot value) */
1002     if (info->ptHotSpot.x == ICON_HOTSPOT && info->ptHotSpot.y == ICON_HOTSPOT) return;
1003
1004     wine_tsx11_lock();
1005     cursor = create_cursor( gdi_display, info );
1006     if (cursor)
1007     {
1008         if (!cursor_context) cursor_context = XUniqueContext();
1009         XSaveContext( gdi_display, (XID)handle, cursor_context, (char *)cursor );
1010         TRACE( "cursor %p %ux%u, planes %u, bpp %u -> xid %lx\n",
1011                handle, info->nWidth, info->nHeight, info->bPlanes, info->bBitsPerPixel, cursor );
1012     }
1013     wine_tsx11_unlock();
1014 }
1015
1016 /***********************************************************************
1017  *              DestroyCursorIcon (X11DRV.@)
1018  */
1019 void CDECL X11DRV_DestroyCursorIcon( HCURSOR handle )
1020 {
1021     Cursor cursor;
1022
1023     wine_tsx11_lock();
1024     if ((cursor = get_x11_cursor( handle )))
1025     {
1026         TRACE( "%p xid %lx\n", handle, cursor );
1027         XFreeCursor( gdi_display, cursor );
1028         XDeleteContext( gdi_display, (XID)handle, cursor_context );
1029     }
1030     wine_tsx11_unlock();
1031 }
1032
1033 /***********************************************************************
1034  *              SetCursor (X11DRV.@)
1035  */
1036 void CDECL X11DRV_SetCursor( HCURSOR handle )
1037 {
1038     if (cursor_window) SendNotifyMessageW( cursor_window, WM_X11DRV_SET_CURSOR, 0, (LPARAM)handle );
1039 }
1040
1041 /***********************************************************************
1042  *              SetCursorPos (X11DRV.@)
1043  */
1044 BOOL CDECL X11DRV_SetCursorPos( INT x, INT y )
1045 {
1046     Display *display = thread_init_display();
1047     POINT pt;
1048
1049     TRACE( "warping to (%d,%d)\n", x, y );
1050
1051     wine_tsx11_lock();
1052     if (cursor_pos.x == x && cursor_pos.y == y)
1053     {
1054         wine_tsx11_unlock();
1055         /* We still need to generate WM_MOUSEMOVE */
1056         queue_raw_mouse_message( WM_MOUSEMOVE, NULL, x, y, 0, GetCurrentTime(), 0, 0 );
1057         return TRUE;
1058     }
1059
1060     pt.x = x; pt.y = y;
1061     clip_point_to_rect( &cursor_clip, &pt);
1062     XWarpPointer( display, root_window, root_window, 0, 0, 0, 0,
1063                   pt.x - virtual_screen_rect.left, pt.y - virtual_screen_rect.top );
1064     XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */
1065     cursor_pos = pt;
1066     wine_tsx11_unlock();
1067     return TRUE;
1068 }
1069
1070 /***********************************************************************
1071  *              GetCursorPos (X11DRV.@)
1072  */
1073 BOOL CDECL X11DRV_GetCursorPos(LPPOINT pos)
1074 {
1075     Display *display = thread_init_display();
1076     Window root, child;
1077     int rootX, rootY, winX, winY;
1078     unsigned int xstate;
1079
1080     wine_tsx11_lock();
1081     if ((GetTickCount() - last_time_modified > 100) &&
1082         XQueryPointer( display, root_window, &root, &child,
1083                        &rootX, &rootY, &winX, &winY, &xstate ))
1084     {
1085         update_button_state( xstate );
1086         winX += virtual_screen_rect.left;
1087         winY += virtual_screen_rect.top;
1088         TRACE("pointer at (%d,%d)\n", winX, winY );
1089         cursor_pos.x = winX;
1090         cursor_pos.y = winY;
1091     }
1092     *pos = cursor_pos;
1093     wine_tsx11_unlock();
1094     return TRUE;
1095 }
1096
1097
1098 /***********************************************************************
1099  *              ClipCursor (X11DRV.@)
1100  *
1101  * Set the cursor clipping rectangle.
1102  */
1103 BOOL CDECL X11DRV_ClipCursor( LPCRECT clip )
1104 {
1105     if (!IntersectRect( &cursor_clip, &virtual_screen_rect, clip ))
1106         cursor_clip = virtual_screen_rect;
1107
1108     return TRUE;
1109 }
1110
1111 /***********************************************************************
1112  *           X11DRV_ButtonPress
1113  */
1114 void X11DRV_ButtonPress( HWND hwnd, XEvent *xev )
1115 {
1116     XButtonEvent *event = &xev->xbutton;
1117     int buttonNum = event->button - 1;
1118     WORD wData = 0;
1119     POINT pt;
1120
1121     if (buttonNum >= NB_BUTTONS) return;
1122     if (!hwnd) return;
1123
1124     switch (buttonNum)
1125     {
1126     case 3:
1127         wData = WHEEL_DELTA;
1128         break;
1129     case 4:
1130         wData = -WHEEL_DELTA;
1131         break;
1132     case 5:
1133         wData = XBUTTON1;
1134         break;
1135     case 6:
1136         wData = XBUTTON2;
1137         break;
1138     case 7:
1139         wData = XBUTTON1;
1140         break;
1141     case 8:
1142         wData = XBUTTON2;
1143         break;
1144     }
1145
1146     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
1147
1148     X11DRV_send_mouse_input( hwnd, button_down_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
1149                              pt.x, pt.y, wData, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
1150 }
1151
1152
1153 /***********************************************************************
1154  *           X11DRV_ButtonRelease
1155  */
1156 void X11DRV_ButtonRelease( HWND hwnd, XEvent *xev )
1157 {
1158     XButtonEvent *event = &xev->xbutton;
1159     int buttonNum = event->button - 1;
1160     WORD wData = 0;
1161     POINT pt;
1162
1163     if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return;
1164     if (!hwnd) return;
1165
1166     switch (buttonNum)
1167     {
1168     case 5:
1169         wData = XBUTTON1;
1170         break;
1171     case 6:
1172         wData = XBUTTON2;
1173         break;
1174     case 7:
1175         wData = XBUTTON1;
1176         break;
1177     case 8:
1178         wData = XBUTTON2;
1179         break;
1180     }
1181
1182     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
1183
1184     X11DRV_send_mouse_input( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE,
1185                              pt.x, pt.y, wData, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
1186 }
1187
1188
1189 /***********************************************************************
1190  *           X11DRV_MotionNotify
1191  */
1192 void X11DRV_MotionNotify( HWND hwnd, XEvent *xev )
1193 {
1194     XMotionEvent *event = &xev->xmotion;
1195     POINT pt;
1196
1197     TRACE("hwnd %p, event->is_hint %d\n", hwnd, event->is_hint);
1198
1199     if (!hwnd) return;
1200
1201     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
1202
1203     X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
1204                              pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
1205 }
1206
1207
1208 /***********************************************************************
1209  *           X11DRV_EnterNotify
1210  */
1211 void X11DRV_EnterNotify( HWND hwnd, XEvent *xev )
1212 {
1213     XCrossingEvent *event = &xev->xcrossing;
1214     POINT pt;
1215
1216     TRACE("hwnd %p, event->detail %d\n", hwnd, event->detail);
1217
1218     if (!hwnd) return;
1219     if (event->detail == NotifyVirtual || event->detail == NotifyNonlinearVirtual) return;
1220     if (event->window == x11drv_thread_data()->grab_window) return;
1221
1222     /* simulate a mouse motion event */
1223     update_mouse_state( hwnd, event->window, event->x, event->y, event->state, &pt );
1224
1225     X11DRV_send_mouse_input( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
1226                              pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 );
1227 }