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