Commit 32fb5805 authored by Alexandre Julliard's avatar Alexandre Julliard

Changed X11 mouse driver to use SendInput, and removed WINE_MOUSEEVENT

hack. Moved mouse.c to dlls/x11drv. Added KeymapNotify event handler, and fixed handling with multiple alt/shift/control keys. Removed dinput functions from USER driver.
parent 7641ce3a
......@@ -29,7 +29,6 @@ struct tagWND;
struct tagCURSORICONINFO;
struct tagCREATESTRUCTA;
struct tagWINDOWPOS;
struct DIDEVICEOBJECTDATA;
#if defined(HAVE_LIBCURSES) || defined(HAVE_LIBNCURSES)
#define WINE_CURSES
......
......@@ -47,15 +47,11 @@ debug_channels (ttydrv)
# USER driver
@ cdecl InitKeyboard() TTYDRV_InitKeyboard
@ cdecl VkKeyScan(long) TTYDRV_VkKeyScan
@ cdecl MapVirtualKey(long long) TTYDRV_MapVirtualKey
@ cdecl GetKeyNameText(long str long) TTYDRV_GetKeyNameText
@ cdecl ToUnicode(long long ptr ptr long long) TTYDRV_ToUnicode
@ cdecl Beep() TTYDRV_Beep
@ cdecl GetDIState(long ptr) TTYDRV_GetDIState
@ cdecl GetDIData(ptr long ptr ptr long) TTYDRV_GetDIData
@ cdecl InitMouse(ptr) TTYDRV_InitMouse
@ cdecl SetCursor(ptr) TTYDRV_SetCursor
@ cdecl GetScreenSaveActive() TTYDRV_GetScreenSaveActive
@ cdecl SetScreenSaveActive(long) TTYDRV_SetScreenSaveActive
......
......@@ -13,13 +13,6 @@ DEFAULT_DEBUG_CHANNEL(ttydrv);
/***********************************************************************
* InitKeyboard (TTYDRV.@)
*/
void TTYDRV_InitKeyboard(void)
{
}
/***********************************************************************
* VkKeyScan (TTYDRV.@)
*/
WORD TTYDRV_VkKeyScan(CHAR cChar)
......@@ -64,30 +57,6 @@ void TTYDRV_Beep(void)
}
/***********************************************************************
* GetDIState (TTYDRV.@)
*/
BOOL TTYDRV_GetDIState(DWORD len, LPVOID ptr)
{
return TRUE;
}
/***********************************************************************
* GetDIData (TTYDRV.@)
*/
BOOL TTYDRV_GetDIData( BYTE *keystate, DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
LPDWORD entries, DWORD flags )
{
return TRUE;
}
/***********************************************************************
* InitMouse (TTYDRV.@)
*/
void TTYDRV_InitMouse(LPMOUSE_EVENT_PROC proc)
{
}
/***********************************************************************
* SetCursor (TTYDRV.@)
*/
void TTYDRV_SetCursor( struct tagCURSORICONINFO *lpCursor )
......
......@@ -10,7 +10,6 @@
#include "debugtools.h"
#include "callback.h"
#include "builtin16.h"
#include "mouse.h"
#include "windef.h"
#include "wingdi.h"
#include "winuser.h"
......@@ -35,6 +34,8 @@ typedef struct _MOUSEINFO
/**********************************************************************/
typedef VOID CALLBACK (*LPMOUSE_EVENT_PROC)(DWORD,DWORD,DWORD,DWORD,DWORD);
static LPMOUSE_EVENT_PROC DefMouseEventProc = NULL;
/***********************************************************************
......@@ -55,16 +56,6 @@ WORD WINAPI MOUSE_Inquire(LPMOUSEINFO mouseInfo)
return sizeof(MOUSEINFO);
}
/***********************************************************************
* Enable (MOUSE.2)
*/
VOID WINAPI MOUSE_Enable(LPMOUSE_EVENT_PROC lpMouseEventProc)
{
THUNK_Free( (FARPROC)DefMouseEventProc );
DefMouseEventProc = lpMouseEventProc;
USER_Driver.pInitMouse( lpMouseEventProc );
}
/**********************************************************************/
static VOID WINAPI MOUSE_CallMouseEventProc( FARPROC16 proc,
......@@ -86,14 +77,13 @@ static VOID WINAPI MOUSE_CallMouseEventProc( FARPROC16 proc,
wine_call_to_16_regs_short( &context, 0 );
}
/**********************************************************************/
VOID WINAPI WIN16_MOUSE_Enable( FARPROC16 proc )
/***********************************************************************
* Enable (MOUSE.2)
*/
VOID WINAPI MOUSE_Enable( FARPROC16 proc )
{
LPMOUSE_EVENT_PROC thunk =
(LPMOUSE_EVENT_PROC)THUNK_Alloc( proc, (RELAY)MOUSE_CallMouseEventProc );
MOUSE_Enable( thunk );
THUNK_Free( (FARPROC)DefMouseEventProc );
DefMouseEventProc = (LPMOUSE_EVENT_PROC)THUNK_Alloc( proc, (RELAY)MOUSE_CallMouseEventProc );
}
/***********************************************************************
......@@ -103,5 +93,4 @@ VOID WINAPI MOUSE_Disable(VOID)
{
THUNK_Free( (FARPROC)DefMouseEventProc );
DefMouseEventProc = 0;
USER_Driver.pInitMouse( 0 );
}
......@@ -4,7 +4,7 @@ owner user32
rsrc resources/mouse.res
1 pascal16 Inquire(ptr) MOUSE_Inquire
2 pascal16 Enable(segptr) WIN16_MOUSE_Enable
2 pascal16 Enable(segptr) MOUSE_Enable
3 pascal16 Disable() MOUSE_Disable
4 stub MOUSEGETINTVECT
5 stub GETSETMOUSEDATA
......
......@@ -67,8 +67,6 @@ static BOOL load_driver(void)
GET_USER_FUNC(GetKeyNameText);
GET_USER_FUNC(ToUnicode);
GET_USER_FUNC(Beep);
GET_USER_FUNC(GetDIState);
GET_USER_FUNC(GetDIData);
GET_USER_FUNC(InitMouse);
GET_USER_FUNC(SetCursor);
GET_USER_FUNC(GetCursorPos);
......@@ -245,10 +243,10 @@ static BOOL process_attach(void)
if (!WIN_CreateDesktopWindow()) return FALSE;
/* Initialize keyboard driver */
USER_Driver.pInitKeyboard( InputKeyStateTable );
if (USER_Driver.pInitKeyboard) USER_Driver.pInitKeyboard( InputKeyStateTable );
/* Initialize mouse driver */
MOUSE_Enable( mouse_event );
if (USER_Driver.pInitMouse) USER_Driver.pInitMouse( InputKeyStateTable );
/* Initialize 16-bit serial communications */
COMM_Init();
......
......@@ -9,6 +9,7 @@ IMPORTS = user32 gdi32 kernel32
C_SRCS = \
desktop.c \
dga2.c \
mouse.c \
scroll.c \
window.c \
winpos.c \
......
/*
* X11 mouse driver
*
* Copyright 1998 Ulrich Weigand
*/
#include "config.h"
#include "ts_xlib.h"
#ifdef HAVE_LIBXXF86DGA2
#include "ts_xf86dga2.h"
#endif
#include "windef.h"
#include "wine/winuser16.h"
#include "x11drv.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(cursor);
/**********************************************************************/
#define NB_BUTTONS 5 /* Windows can handle 3 buttons and the wheel too */
static const UINT button_down_flags[NB_BUTTONS] =
{
MOUSEEVENTF_LEFTDOWN,
MOUSEEVENTF_MIDDLEDOWN,
MOUSEEVENTF_RIGHTDOWN,
MOUSEEVENTF_WHEEL,
MOUSEEVENTF_WHEEL
};
static const UINT button_up_flags[NB_BUTTONS] =
{
MOUSEEVENTF_LEFTUP,
MOUSEEVENTF_MIDDLEUP,
MOUSEEVENTF_RIGHTUP,
0,
0
};
static BYTE *pKeyStateTable;
/***********************************************************************
* get_coords
*
* get the coordinates of a mouse event
*/
static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
{
struct x11drv_win_data *data;
WND *win;
if (!(win = WIN_GetPtr( *hwnd )) || win == WND_OTHER_PROCESS) return;
data = win->pDriverData;
if (window == data->whole_window)
{
x -= data->client_rect.left;
y -= data->client_rect.top;
}
WIN_ReleasePtr( win );
pt->x = x;
pt->y = y;
if (*hwnd != GetDesktopWindow())
{
ClientToScreen( *hwnd, pt );
*hwnd = GetAncestor( *hwnd, GA_ROOT );
}
}
/***********************************************************************
* update_key_state
*
* Update the key state with what X provides us
*/
static void update_key_state( unsigned int state )
{
pKeyStateTable[VK_LBUTTON] = (state & Button1Mask ? 0x80 : 0);
pKeyStateTable[VK_MBUTTON] = (state & Button2Mask ? 0x80 : 0);
pKeyStateTable[VK_RBUTTON] = (state & Button3Mask ? 0x80 : 0);
pKeyStateTable[VK_SHIFT] = (state & ShiftMask ? 0x80 : 0);
pKeyStateTable[VK_CONTROL] = (state & ControlMask ? 0x80 : 0);
}
/***********************************************************************
* send_mouse_event
*/
static void send_mouse_event( HWND hwnd, DWORD flags, DWORD posX, DWORD posY,
DWORD data, Time time )
{
INPUT input;
TRACE("(%04lX,%ld,%ld)\n", flags, posX, posY );
if (flags & MOUSEEVENTF_ABSOLUTE)
{
int width = GetSystemMetrics( SM_CXSCREEN );
int height = GetSystemMetrics( SM_CYSCREEN );
/* Relative mouse movements seem not to be scaled as absolute ones */
posX = (((long)posX << 16) + width-1) / width;
posY = (((long)posY << 16) + height-1) / height;
}
input.type = WINE_INTERNAL_INPUT_MOUSE;
input.u.mi.dx = posX;
input.u.mi.dy = posY;
input.u.mi.mouseData = data;
input.u.mi.dwFlags = flags;
input.u.mi.time = time - X11DRV_server_startticks;
input.u.mi.dwExtraInfo = (ULONG_PTR)hwnd;
SendInput( 1, &input, sizeof(input) );
}
/***********************************************************************
* X11DRV_GetCursor
*/
Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
{
Pixmap pixmapBits, pixmapMask, pixmapMaskInv, pixmapAll;
XColor fg, bg;
Cursor cursor = None;
if (!ptr) /* Create an empty cursor */
{
static const char data[] = { 0 };
bg.red = bg.green = bg.blue = 0x0000;
pixmapBits = XCreateBitmapFromData( display, root_window, data, 1, 1 );
if (pixmapBits)
{
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
&bg, &bg, 0, 0 );
XFreePixmap( display, pixmapBits );
}
}
else /* Create the X cursor from the bits */
{
XImage *image;
GC gc;
if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
{
WARN("Cursor has more than 1 bpp!\n" );
return 0;
}
/* Create a pixmap and transfer all the bits to it */
/* NOTE: Following hack works, but only because XFree depth
* 1 images really use 1 bit/pixel (and so the same layout
* as the Windows cursor data). Perhaps use a more generic
* algorithm here.
*/
if (!(pixmapAll = XCreatePixmap( display, root_window,
ptr->nWidth, ptr->nHeight * 2, 1 ))) return 0;
if (!(image = XCreateImage( display, visual,
1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
ptr->nHeight * 2, 16, ptr->nWidthBytes))) return 0;
gc = XCreateGC( display, pixmapAll, 0, NULL );
XSetGraphicsExposures( display, gc, False );
image->byte_order = MSBFirst;
image->bitmap_bit_order = MSBFirst;
image->bitmap_unit = 16;
_XInitImageFuncPtrs(image);
XPutImage( display, pixmapAll, gc, image,
0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
image->data = NULL;
XDestroyImage( image );
/* Now create the 2 pixmaps for bits and mask */
pixmapBits = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
pixmapMask = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
pixmapMaskInv = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
/* Make sure everything went OK so far */
if (pixmapBits && pixmapMask && pixmapMaskInv)
{
/* We have to do some magic here, as cursors are not fully
* compatible between Windows and X11. Under X11, there
* are only 3 possible color cursor: black, white and
* masked. So we map the 4th Windows color (invert the
* bits on the screen) to black and an additional white bit on
* an other place (+1,+1). This require some boolean arithmetic:
*
* Windows | X11
* And Xor Result | Bits Mask Result
* 0 0 black | 0 1 background
* 0 1 white | 1 1 foreground
* 1 0 no change | X 0 no change
* 1 1 inverted | 0 1 background
*
* which gives:
* Bits = not 'And' and 'Xor' or 'And2' and 'Xor2'
* Mask = not 'And' or 'Xor' or 'And2' and 'Xor2'
*
* FIXME: apparently some servers do support 'inverted' color.
* I don't know if it's correct per the X spec, but maybe
* we ought to take advantage of it. -- AJ
*/
XSetFunction( display, gc, GXcopy );
XCopyArea( display, pixmapAll, pixmapBits, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XCopyArea( display, pixmapAll, pixmapMask, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXand );
XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXandReverse );
XCopyArea( display, pixmapAll, pixmapBits, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXorReverse );
XCopyArea( display, pixmapAll, pixmapMask, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
/* Additional white */
XSetFunction( display, gc, GXor );
XCopyArea( display, pixmapMaskInv, pixmapMask, gc,
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
XSetFunction( display, gc, GXcopy );
fg.red = fg.green = fg.blue = 0xffff;
bg.red = bg.green = bg.blue = 0x0000;
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
&fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
}
/* Now free everything */
if (pixmapAll) XFreePixmap( display, pixmapAll );
if (pixmapBits) XFreePixmap( display, pixmapBits );
if (pixmapMask) XFreePixmap( display, pixmapMask );
if (pixmapMaskInv) XFreePixmap( display, pixmapMaskInv );
XFreeGC( display, gc );
}
return cursor;
}
/* set the cursor of a window; helper for X11DRV_SetCursor */
static BOOL CALLBACK set_win_cursor( HWND hwnd, LPARAM cursor )
{
Window win = X11DRV_get_whole_window( hwnd );
if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
return TRUE;
}
/***********************************************************************
* SetCursor (X11DRV.@)
*/
void X11DRV_SetCursor( CURSORICONINFO *lpCursor )
{
Cursor cursor;
if (root_window != DefaultRootWindow(gdi_display))
{
/* If in desktop mode, set the cursor on the desktop window */
wine_tsx11_lock();
cursor = X11DRV_GetCursor( gdi_display, lpCursor );
if (cursor)
{
XDefineCursor( gdi_display, root_window, cursor );
XFreeCursor( gdi_display, cursor );
}
wine_tsx11_unlock();
}
else /* set the same cursor for all top-level windows of the current thread */
{
Display *display = thread_display();
wine_tsx11_lock();
cursor = X11DRV_GetCursor( display, lpCursor );
wine_tsx11_unlock();
if (cursor)
{
/* EnumThreadWindows( GetCurrentThreadId(), set_win_cursor, (LPARAM)cursor );*/
EnumWindows( set_win_cursor, (LPARAM)cursor );
TSXFreeCursor( display, cursor );
}
}
}
/***********************************************************************
* SetCursorPos (X11DRV.@)
*/
void X11DRV_SetCursorPos( INT x, INT y )
{
Display *display = thread_display();
TRACE( "warping to (%d,%d)\n", x, y );
wine_tsx11_lock();
XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, x, y );
XFlush( display ); /* just in case */
wine_tsx11_unlock();
}
/***********************************************************************
* GetCursorPos (X11DRV.@)
*/
void X11DRV_GetCursorPos(LPPOINT pos)
{
Display *display = thread_display();
Window root, child;
int rootX, rootY, winX, winY;
unsigned int xstate;
if (!TSXQueryPointer( display, root_window, &root, &child,
&rootX, &rootY, &winX, &winY, &xstate ))
return;
TRACE("pointer at (%d,%d)\n", winX, winY );
pos->x = winX;
pos->y = winY;
}
/***********************************************************************
* InitMouse (X11DRV.@)
*/
void X11DRV_InitMouse( BYTE *key_state_table )
{
Window root, child;
int root_x, root_y, child_x, child_y;
unsigned int KeyState;
pKeyStateTable = key_state_table;
/* Get the current mouse position and simulate an absolute mouse
movement to initialize the mouse global variables */
TSXQueryPointer( thread_display(), root_window, &root, &child,
&root_x, &root_y, &child_x, &child_y, &KeyState);
update_key_state( KeyState );
send_mouse_event( 0, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
root_x, root_y, 0, GetTickCount() + X11DRV_server_startticks );
}
/***********************************************************************
* X11DRV_ButtonPress
*/
void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event )
{
int buttonNum = event->button - 1;
WORD wData = 0;
POINT pt;
if (buttonNum >= NB_BUTTONS) return;
get_coords( &hwnd, event->window, event->x, event->y, &pt );
switch (buttonNum)
{
case 3:
wData = WHEEL_DELTA;
break;
case 4:
wData = -WHEEL_DELTA;
break;
}
update_key_state( event->state );
send_mouse_event( hwnd, button_down_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, wData, event->time );
}
/***********************************************************************
* X11DRV_ButtonRelease
*/
void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event )
{
int buttonNum = event->button - 1;
POINT pt;
if (buttonNum >= NB_BUTTONS || !button_up_flags[buttonNum]) return;
get_coords( &hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, button_up_flags[buttonNum] | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
}
/***********************************************************************
* X11DRV_MotionNotify
*/
void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event )
{
POINT pt;
get_coords( &hwnd, event->window, event->x, event->y, &pt );
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
pt.x, pt.y, 0, event->time );
}
#ifdef HAVE_LIBXXF86DGA2
/**********************************************************************
* X11DRV_DGAMotionEvent
*/
void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event )
{
update_key_state( event->state );
send_mouse_event( hwnd, MOUSEEVENTF_MOVE, event->dx, event->dy, 0, event->time );
}
/**********************************************************************
* X11DRV_DGAButtonPressEvent
*/
void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event )
{
int buttonNum = event->button - 1;
if (buttonNum >= NB_BUTTONS) return;
update_key_state( event->state );
send_mouse_event( hwnd, button_down_flags[buttonNum], 0, 0, 0, event->time );
}
/**********************************************************************
* X11DRV_DGAButtonReleaseEvent
*/
void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event )
{
int buttonNum = event->button - 1;
if (buttonNum >= NB_BUTTONS) return;
update_key_state( event->state );
send_mouse_event( hwnd, button_up_flags[buttonNum], 0, 0, 0, event->time );
}
#endif /* HAVE_LIBXXF86DGA2 */
......@@ -117,7 +117,7 @@ static int get_window_attributes( Display *display, WND *win, XSetWindowAttribut
ButtonPressMask | ButtonReleaseMask);
if (is_window_top_level( win ))
{
attr->event_mask |= StructureNotifyMask | FocusChangeMask;
attr->event_mask |= StructureNotifyMask | FocusChangeMask | KeymapStateMask;
attr->cursor = X11DRV_GetCursor( display, GlobalLock16(GetCursor()) );
}
return (CWOverrideRedirect | CWSaveUnder | CWEventMask | CWColormap | CWCursor);
......
......@@ -66,8 +66,6 @@ debug_channels (bitblt bitmap clipboard cursor dinput event font gdi graphics
@ cdecl GetKeyNameText(long str long) X11DRV_GetKeyNameText
@ cdecl ToUnicode(long long ptr ptr long long) X11DRV_ToUnicode
@ cdecl Beep() X11DRV_Beep
@ cdecl GetDIState(long ptr) X11DRV_GetDIState
@ cdecl GetDIData(ptr long ptr ptr long) X11DRV_GetDIData
@ cdecl InitMouse(ptr) X11DRV_InitMouse
@ cdecl SetCursor(ptr) X11DRV_SetCursor
@ cdecl GetCursorPos(ptr) X11DRV_GetCursorPos
......
/*
* MOUSE driver interface
*
* Copyright 1998 Ulrich Weigand
*/
#ifndef __WINE_MOUSE_H
#define __WINE_MOUSE_H
#include "windef.h"
#include "user.h"
/* Wine internals */
#define WINE_MOUSEEVENT_MAGIC ( ('M'<<24)|('A'<<16)|('U'<<8)|'S' )
typedef struct _WINE_MOUSEEVENT
{
DWORD magic;
DWORD keyState;
DWORD time;
HWND hWnd;
} WINE_MOUSEEVENT;
#endif /* __WINE_MOUSE_H */
......@@ -31,9 +31,6 @@ extern WORD USER_HeapSel;
#define USUD_FIRSTCLASS 0x0005
struct tagCURSORICONINFO;
struct DIDEVICEOBJECTDATA;
typedef VOID CALLBACK (*LPMOUSE_EVENT_PROC)(DWORD,DWORD,DWORD,DWORD,DWORD);
/* internal messages codes */
enum wine_internal_message
......@@ -44,6 +41,10 @@ enum wine_internal_message
WM_WINE_SETPARENT
};
/* internal SendInput codes (FIXME) */
#define WINE_INTERNAL_INPUT_MOUSE (16+INPUT_MOUSE)
#define WINE_INTERNAL_INPUT_KEYBOARD (16+INPUT_KEYBOARD)
typedef struct tagUSER_DRIVER {
/* keyboard functions */
void (*pInitKeyboard)(LPBYTE);
......@@ -52,10 +53,8 @@ typedef struct tagUSER_DRIVER {
INT (*pGetKeyNameText)(LONG,LPSTR,INT);
INT (*pToUnicode)(UINT, UINT, LPBYTE, LPWSTR, int, UINT);
void (*pBeep)(void);
BOOL (*pGetDIState)(DWORD, LPVOID);
BOOL (*pGetDIData)(BYTE *, DWORD, struct DIDEVICEOBJECTDATA *, LPDWORD, DWORD);
/* mouse functions */
void (*pInitMouse)(LPMOUSE_EVENT_PROC);
void (*pInitMouse)(LPBYTE);
void (*pSetCursor)(struct tagCURSORICONINFO *);
void (*pGetCursorPos)(LPPOINT);
void (*pSetCursorPos)(INT,INT);
......@@ -108,9 +107,6 @@ extern void USER_CheckNotLock(void);
extern BOOL USER_IsExitingThread( DWORD tid );
VOID WINAPI MOUSE_Enable(LPMOUSE_EVENT_PROC lpMouseEventProc);
VOID WINAPI MOUSE_Disable(VOID);
/* Wine look */
typedef enum
......
......@@ -30,7 +30,6 @@ struct tagDC;
struct tagDeviceCaps;
struct tagPALETTEOBJ;
struct tagWINDOWPOS;
struct DIDEVICEOBJECTDATA;
/* X physical pen */
typedef struct
......@@ -349,8 +348,6 @@ extern BOOL X11DRV_GetClipboardData(UINT wFormat);
/* X11 event driver */
extern WORD X11DRV_EVENT_XStateToKeyState( int state ) ;
typedef enum {
X11DRV_INPUT_RELATIVE,
X11DRV_INPUT_ABSOLUTE
......@@ -361,14 +358,6 @@ extern INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type);
void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base) ;
#endif
/* X11 mouse driver */
extern void X11DRV_InitMouse(LPMOUSE_EVENT_PROC);
extern void X11DRV_SetCursor(struct tagCURSORICONINFO *lpCursor);
extern void X11DRV_MoveCursor(WORD wAbsX, WORD wAbsY);
extern void X11DRV_SendEvent( DWORD mouseStatus, DWORD posX, DWORD posY,
WORD keyState, DWORD data, DWORD time, HWND hWnd );
/* x11drv private window data */
struct x11drv_win_data
{
......
......@@ -26,7 +26,6 @@
#include "win.h"
#include "hook.h"
#include "input.h"
#include "mouse.h"
#include "message.h"
#include "queue.h"
#include "debugtools.h"
......@@ -46,13 +45,6 @@ BYTE AsyncKeyStateTable[256];
/* Storage for the USER-maintained mouse positions */
static DWORD PosX, PosY;
#define GET_KEYSTATE() \
((InputKeyStateTable[SwappedButtons ? VK_RBUTTON : VK_LBUTTON] & 0x80 ? MK_LBUTTON : 0) | \
(InputKeyStateTable[SwappedButtons ? VK_LBUTTON : VK_RBUTTON] & 0x80 ? MK_RBUTTON : 0) | \
(InputKeyStateTable[VK_MBUTTON] & 0x80 ? MK_MBUTTON : 0) | \
(InputKeyStateTable[VK_SHIFT] & 0x80 ? MK_SHIFT : 0) | \
(InputKeyStateTable[VK_CONTROL] & 0x80 ? MK_CONTROL : 0))
typedef union
{
struct
......@@ -71,6 +63,32 @@ typedef union
/***********************************************************************
* get_key_state
*/
static WORD get_key_state(void)
{
WORD ret = 0;
if (SwappedButtons)
{
if (InputKeyStateTable[VK_RBUTTON] & 0x80) ret |= MK_LBUTTON;
if (InputKeyStateTable[VK_LBUTTON] & 0x80) ret |= MK_RBUTTON;
}
else
{
if (InputKeyStateTable[VK_LBUTTON] & 0x80) ret |= MK_LBUTTON;
if (InputKeyStateTable[VK_RBUTTON] & 0x80) ret |= MK_RBUTTON;
}
if (InputKeyStateTable[VK_MBUTTON] & 0x80) ret |= MK_MBUTTON;
if (InputKeyStateTable[VK_SHIFT] & 0x80) ret |= MK_SHIFT;
if (InputKeyStateTable[VK_CONTROL] & 0x80) ret |= MK_CONTROL;
if (InputKeyStateTable[VK_XBUTTON1] & 0x80) ret |= MK_XBUTTON1;
if (InputKeyStateTable[VK_XBUTTON2] & 0x80) ret |= MK_XBUTTON2;
return ret;
}
/***********************************************************************
* queue_raw_hardware_message
*
* Add a message to the raw hardware queue.
......@@ -103,7 +121,7 @@ static void queue_raw_hardware_message( UINT message, WPARAM wParam, LPARAM lPar
*
* Put a keyboard event into a thread queue
*/
static void queue_kbd_event( const KEYBDINPUT *ki )
static void queue_kbd_event( const KEYBDINPUT *ki, UINT injected_flags )
{
UINT message;
KEYLP keylp;
......@@ -147,7 +165,7 @@ static void queue_kbd_event( const KEYBDINPUT *ki )
hook.vkCode = ki->wVk;
hook.scanCode = ki->wScan;
hook.flags = keylp.lp2 >> 24; /* FIXME: LLKHF_INJECTED flag */
hook.flags = (keylp.lp2 >> 24) | injected_flags;
hook.time = ki->time;
hook.dwExtraInfo = ki->dwExtraInfo;
if (!HOOK_CallHooksW( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook ))
......@@ -159,27 +177,27 @@ static void queue_kbd_event( const KEYBDINPUT *ki )
/***********************************************************************
* queue_raw_mouse_message
*/
static void queue_raw_mouse_message( UINT message, WPARAM wParam, LPARAM lParam,
int xPos, int yPos, DWORD time, ULONG_PTR extra_info )
static void queue_raw_mouse_message( UINT message, UINT flags, INT x, INT y, const MOUSEINPUT *mi )
{
MSLLHOOKSTRUCT hook;
hook.pt.x = xPos;
hook.pt.y = yPos;
hook.mouseData = wParam;
hook.flags = 0; /* FIXME: LLMHF_INJECTED flag */
hook.time = time;
hook.dwExtraInfo = extra_info;
hook.pt.x = x;
hook.pt.y = y;
hook.mouseData = MAKELONG( 0, mi->mouseData );
hook.flags = flags;
hook.time = mi->time;
hook.dwExtraInfo = mi->dwExtraInfo;
if (!HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, message, (LPARAM)&hook ))
queue_raw_hardware_message( message, wParam, lParam, xPos, yPos, time, extra_info );
queue_raw_hardware_message( message, MAKEWPARAM( get_key_state(), mi->mouseData ),
0, x, y, mi->time, mi->dwExtraInfo );
}
/***********************************************************************
* queue_mouse_event
*/
static void queue_mouse_event( const MOUSEINPUT *mi, WORD keystate )
static void queue_mouse_event( const MOUSEINPUT *mi, UINT flags )
{
if (mi->dwFlags & MOUSEEVENTF_ABSOLUTE)
{
......@@ -208,53 +226,51 @@ static void queue_mouse_event( const MOUSEINPUT *mi, WORD keystate )
if (mi->dwFlags & MOUSEEVENTF_MOVE)
{
queue_raw_mouse_message( WM_MOUSEMOVE, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( WM_MOUSEMOVE, flags, PosX, PosY, mi );
}
if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN))
if (mi->dwFlags & MOUSEEVENTF_LEFTDOWN)
{
InputKeyStateTable[VK_LBUTTON] |= 0x80;
AsyncKeyStateTable[VK_LBUTTON] |= 0x80;
queue_raw_mouse_message( WM_LBUTTONDOWN, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( SwappedButtons ? WM_RBUTTONDOWN : WM_LBUTTONDOWN,
flags, PosX, PosY, mi );
}
if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP))
if (mi->dwFlags & MOUSEEVENTF_LEFTUP)
{
InputKeyStateTable[VK_LBUTTON] &= ~0x80;
queue_raw_mouse_message( WM_LBUTTONUP, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( SwappedButtons ? WM_RBUTTONUP : WM_LBUTTONUP,
flags, PosX, PosY, mi );
}
if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN))
if (mi->dwFlags & MOUSEEVENTF_RIGHTDOWN)
{
InputKeyStateTable[VK_RBUTTON] |= 0x80;
AsyncKeyStateTable[VK_RBUTTON] |= 0x80;
queue_raw_mouse_message( WM_RBUTTONDOWN, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( SwappedButtons ? WM_LBUTTONDOWN : WM_RBUTTONDOWN,
flags, PosX, PosY, mi );
}
if (mi->dwFlags & (!SwappedButtons? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP))
if (mi->dwFlags & MOUSEEVENTF_RIGHTUP)
{
InputKeyStateTable[VK_RBUTTON] &= ~0x80;
queue_raw_mouse_message( WM_RBUTTONUP, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( SwappedButtons ? WM_LBUTTONUP : WM_RBUTTONUP,
flags, PosX, PosY, mi );
}
if (mi->dwFlags & MOUSEEVENTF_MIDDLEDOWN)
{
InputKeyStateTable[VK_MBUTTON] |= 0x80;
AsyncKeyStateTable[VK_MBUTTON] |= 0x80;
queue_raw_mouse_message( WM_MBUTTONDOWN, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( WM_MBUTTONDOWN, flags, PosX, PosY, mi );
}
if (mi->dwFlags & MOUSEEVENTF_MIDDLEUP)
{
InputKeyStateTable[VK_MBUTTON] &= ~0x80;
queue_raw_mouse_message( WM_MBUTTONUP, keystate, 0, PosX, PosY,
mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( WM_MBUTTONUP, flags, PosX, PosY, mi );
}
if (mi->dwFlags & MOUSEEVENTF_WHEEL)
{
queue_raw_mouse_message( WM_MOUSEWHEEL, MAKELONG( keystate, mi->mouseData), 0,
PosX, PosY, mi->time, mi->dwExtraInfo );
queue_raw_mouse_message( WM_MOUSEWHEEL, flags, PosX, PosY, mi );
}
if (flags & LLMHF_INJECTED) /* we have to actually move the cursor */
SetCursorPos( PosX, PosY );
}
......@@ -272,10 +288,16 @@ UINT WINAPI SendInput( UINT count, LPINPUT inputs, int size )
switch(inputs->type)
{
case INPUT_MOUSE:
queue_mouse_event( &inputs->u.mi, GET_KEYSTATE() );
queue_mouse_event( &inputs->u.mi, LLMHF_INJECTED );
break;
case WINE_INTERNAL_INPUT_MOUSE:
queue_mouse_event( &inputs->u.mi, 0 );
break;
case INPUT_KEYBOARD:
queue_kbd_event( &inputs->u.ki );
queue_kbd_event( &inputs->u.ki, LLKHF_INJECTED );
break;
case WINE_INTERNAL_INPUT_KEYBOARD:
queue_kbd_event( &inputs->u.ki, 0 );
break;
case INPUT_HARDWARE:
FIXME( "INPUT_HARDWARE not supported\n" );
......@@ -326,49 +348,15 @@ void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
DWORD dwData, DWORD dwExtraInfo )
{
INPUT input;
WORD keyState;
input.type = INPUT_MOUSE;
input.u.mi.dx = dx;
input.u.mi.dy = dy;
input.u.mi.mouseData = dwData;
input.u.mi.dwFlags = dwFlags;
/*
* If we are called by the Wine mouse driver, use the additional
* info pointed to by the dwExtraInfo argument.
* Otherwise, we need to determine that info ourselves (probably
* less accurate, but we can't help that ...).
*/
if (dwExtraInfo && !IsBadReadPtr( (LPVOID)dwExtraInfo, sizeof(WINE_MOUSEEVENT) )
&& ((WINE_MOUSEEVENT *)dwExtraInfo)->magic == WINE_MOUSEEVENT_MAGIC )
{
WINE_MOUSEEVENT *wme = (WINE_MOUSEEVENT *)dwExtraInfo;
keyState = wme->keyState;
if (keyState != GET_KEYSTATE())
{
/* We need to update the keystate with what X provides us */
InputKeyStateTable[SwappedButtons ? VK_RBUTTON : VK_LBUTTON] = (keyState & MK_LBUTTON ? 0x80 : 0);
InputKeyStateTable[SwappedButtons ? VK_LBUTTON : VK_RBUTTON] = (keyState & MK_RBUTTON ? 0x80 : 0);
InputKeyStateTable[VK_MBUTTON] = (keyState & MK_MBUTTON ? 0x80 : 0);
InputKeyStateTable[VK_SHIFT] = (keyState & MK_SHIFT ? 0x80 : 0);
InputKeyStateTable[VK_CONTROL] = (keyState & MK_CONTROL ? 0x80 : 0);
}
input.u.mi.time = wme->time;
input.u.mi.dwExtraInfo = (ULONG_PTR)wme->hWnd;
queue_mouse_event( &input.u.mi, keyState );
}
else
{
input.u.mi.time = GetCurrentTime();
input.u.mi.dwExtraInfo = dwExtraInfo;
SendInput( 1, &input, sizeof(input) );
if ( dwFlags & MOUSEEVENTF_MOVE ) /* we have to actually move the cursor */
SetCursorPos( PosX, PosY );
}
input.u.mi.time = GetCurrentTime();
input.u.mi.dwExtraInfo = dwExtraInfo;
SendInput( 1, &input, sizeof(input) );
}
......
......@@ -8,8 +8,7 @@ MODULE = x11drv
C_SRCS = \
clipboard.c \
event.c \
keyboard.c \
mouse.c
keyboard.c
PROGRAMS = wineclipsrv
......
......@@ -26,7 +26,6 @@
#include "dce.h"
#include "debugtools.h"
#include "input.h"
#include "mouse.h"
#include "options.h"
#include "win.h"
#include "winpos.h"
......@@ -46,11 +45,6 @@ extern Atom wmDeleteWindow;
extern Atom dndProtocol;
extern Atom dndSelection;
extern void X11DRV_KEYBOARD_UpdateState(void);
#define NB_BUTTONS 5 /* Windows can handle 3 buttons and the wheel too */
#define DndNotDnd -1 /* OffiX drag&drop */
#define DndUnknown 0
#define DndRawData 1
......@@ -85,9 +79,6 @@ static void EVENT_ProcessEvent( XEvent *event );
static BOOL X11DRV_CheckFocus(void);
/* Event handlers */
static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event );
static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event );
static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event );
static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
static void EVENT_SelectionRequest( HWND hWnd, XSelectionRequestEvent *event, BOOL bIsMultiple );
......@@ -95,7 +86,11 @@ static void EVENT_SelectionClear( HWND hWnd, XSelectionClearEvent *event);
static void EVENT_PropertyNotify( XPropertyEvent *event );
static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
extern void X11DRV_ButtonPress( HWND hwnd, XButtonEvent *event );
extern void X11DRV_ButtonRelease( HWND hwnd, XButtonEvent *event );
extern void X11DRV_MotionNotify( HWND hwnd, XMotionEvent *event );
extern void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event );
extern void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event );
extern void X11DRV_Expose( HWND hwnd, XExposeEvent *event );
extern void X11DRV_MapNotify( HWND hwnd, XMapEvent *event );
extern void X11DRV_UnmapNotify( HWND hwnd, XUnmapEvent *event );
......@@ -112,9 +107,9 @@ static int DGAKeyReleaseEventType;
static BOOL DGAUsed = FALSE;
static HWND DGAhwnd = 0;
static void EVENT_DGAMotionEvent( XDGAMotionEvent *event );
static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event );
static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event );
extern void X11DRV_DGAMotionEvent( HWND hwnd, XDGAMotionEvent *event );
extern void X11DRV_DGAButtonPressEvent( HWND hwnd, XDGAButtonEvent *event );
extern void X11DRV_DGAButtonReleaseEvent( HWND hwnd, XDGAButtonEvent *event );
#endif
/* Static used for the current input method */
......@@ -213,17 +208,17 @@ static void EVENT_ProcessEvent( XEvent *event )
if (DGAUsed) {
if (event->type == DGAMotionEventType) {
TRACE("DGAMotionEvent received.\n");
EVENT_DGAMotionEvent((XDGAMotionEvent *) event);
X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
return;
}
if (event->type == DGAButtonPressEventType) {
TRACE("DGAButtonPressEvent received.\n");
EVENT_DGAButtonPressEvent((XDGAButtonEvent *) event);
X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
return;
}
if (event->type == DGAButtonReleaseEventType) {
TRACE("DGAButtonReleaseEvent received.\n");
EVENT_DGAButtonReleaseEvent((XDGAButtonEvent *) event);
X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
return;
}
if ((event->type == DGAKeyPressEventType) ||
......@@ -277,17 +272,17 @@ static void EVENT_ProcessEvent( XEvent *event )
/* FIXME: should generate a motion event if event point is different from current pos */
X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
break;
case ButtonPress:
EVENT_ButtonPress( hWnd, (XButtonEvent*)event );
X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
break;
case ButtonRelease:
EVENT_ButtonRelease( hWnd, (XButtonEvent*)event );
X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
break;
case MotionNotify:
EVENT_MotionNotify( hWnd, (XMotionEvent*)event );
X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
break;
case FocusIn:
......@@ -337,6 +332,10 @@ static void EVENT_ProcessEvent( XEvent *event )
X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
break;
case KeymapNotify:
X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
break;
case MappingNotify:
X11DRV_MappingNotify( (XMappingEvent *) event );
break;
......@@ -349,162 +348,6 @@ static void EVENT_ProcessEvent( XEvent *event )
TRACE( "returns.\n" );
}
/***********************************************************************
* X11DRV_EVENT_XStateToKeyState
*
* Translate a X event state (Button1Mask, ShiftMask, etc...) to
* a Windows key state (MK_SHIFT, MK_CONTROL, etc...)
*/
WORD X11DRV_EVENT_XStateToKeyState( int state )
{
int kstate = 0;
if (state & Button1Mask) kstate |= MK_LBUTTON;
if (state & Button2Mask) kstate |= MK_MBUTTON;
if (state & Button3Mask) kstate |= MK_RBUTTON;
if (state & ShiftMask) kstate |= MK_SHIFT;
if (state & ControlMask) kstate |= MK_CONTROL;
return kstate;
}
/* get the coordinates of a mouse event */
static void get_coords( HWND *hwnd, Window window, int x, int y, POINT *pt )
{
struct x11drv_win_data *data;
WND *win;
if (!(win = WIN_FindWndPtr( *hwnd ))) return;
data = win->pDriverData;
if (window == data->whole_window)
{
x -= data->client_rect.left;
y -= data->client_rect.top;
}
WIN_ReleaseWndPtr( win );
pt->x = x;
pt->y = y;
if (*hwnd != GetDesktopWindow())
{
ClientToScreen( *hwnd, pt );
*hwnd = GetAncestor( *hwnd, GA_ROOT );
}
}
/***********************************************************************
* EVENT_MotionNotify
*/
static void EVENT_MotionNotify( HWND hWnd, XMotionEvent *event )
{
POINT pt;
if (current_input_type == X11DRV_INPUT_ABSOLUTE)
{
get_coords( &hWnd, event->window, event->x, event->y, &pt );
X11DRV_SendEvent( MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
X11DRV_EVENT_XStateToKeyState( event->state ), 0,
event->time - X11DRV_server_startticks, hWnd);
}
else
{
X11DRV_SendEvent( MOUSEEVENTF_MOVE,
event->x_root, event->y_root,
X11DRV_EVENT_XStateToKeyState( event->state ), 0,
event->time - X11DRV_server_startticks, hWnd);
}
}
/***********************************************************************
* EVENT_ButtonPress
*/
static void EVENT_ButtonPress( HWND hWnd, XButtonEvent *event )
{
static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN,
MOUSEEVENTF_RIGHTDOWN, MOUSEEVENTF_WHEEL,
MOUSEEVENTF_WHEEL};
int buttonNum = event->button - 1;
WORD keystate, wData = 0;
POINT pt;
if (buttonNum >= NB_BUTTONS) return;
get_coords( &hWnd, event->window, event->x, event->y, &pt );
/* Get the compatible keystate */
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
/*
* Make sure that the state of the button that was just
* pressed is "down".
*/
switch (buttonNum)
{
case 0:
keystate |= MK_LBUTTON;
break;
case 1:
keystate |= MK_MBUTTON;
break;
case 2:
keystate |= MK_RBUTTON;
break;
case 3:
wData = WHEEL_DELTA;
break;
case 4:
wData = -WHEEL_DELTA;
break;
}
X11DRV_SendEvent( statusCodes[buttonNum] | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
keystate, wData, event->time - X11DRV_server_startticks, hWnd);
}
/***********************************************************************
* EVENT_ButtonRelease
*/
static void EVENT_ButtonRelease( HWND hWnd, XButtonEvent *event )
{
static const WORD statusCodes[NB_BUTTONS] = { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP,
MOUSEEVENTF_RIGHTUP, 0, 0 };
int buttonNum = event->button - 1;
WORD keystate;
POINT pt;
if (buttonNum >= NB_BUTTONS) return;
get_coords( &hWnd, event->window, event->x, event->y, &pt );
/* Get the compatible keystate */
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
/*
* Make sure that the state of the button that was just
* released is "up".
*/
switch (buttonNum)
{
case 0:
keystate &= ~MK_LBUTTON;
break;
case 1:
keystate &= ~MK_MBUTTON;
break;
case 2:
keystate &= ~MK_RBUTTON;
break;
default:
return;
}
X11DRV_SendEvent( statusCodes[buttonNum] | MOUSEEVENTF_ABSOLUTE, pt.x, pt.y,
keystate, 0, event->time - X11DRV_server_startticks, hWnd);
}
/**********************************************************************
* EVENT_FocusIn
......@@ -543,10 +386,7 @@ static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event )
}
if (event->detail != NotifyPointer && hWnd != GetForegroundWindow())
{
SetForegroundWindow( hWnd );
X11DRV_KEYBOARD_UpdateState();
}
}
......@@ -1470,71 +1310,4 @@ void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
DGAKeyReleaseEventType = event_base + KeyRelease;
}
}
/* DGA2 event handlers */
static void EVENT_DGAMotionEvent( XDGAMotionEvent *event )
{
X11DRV_SendEvent( MOUSEEVENTF_MOVE, event->dx, event->dy,
X11DRV_EVENT_XStateToKeyState( event->state ), 0,
event->time - X11DRV_server_startticks, DGAhwnd );
}
static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event )
{
static WORD statusCodes[NB_BUTTONS] =
{ MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN };
int buttonNum = event->button - 1;
WORD keystate;
if (buttonNum >= NB_BUTTONS) return;
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
switch (buttonNum)
{
case 0:
keystate |= MK_LBUTTON;
break;
case 1:
keystate |= MK_MBUTTON;
break;
case 2:
keystate |= MK_RBUTTON;
break;
}
X11DRV_SendEvent( statusCodes[buttonNum], 0, 0, keystate, 0,
event->time - X11DRV_server_startticks, DGAhwnd );
}
static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event )
{
static WORD statusCodes[NB_BUTTONS] =
{ MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP };
int buttonNum = event->button - 1;
WORD keystate;
if (buttonNum >= NB_BUTTONS) return;
keystate = X11DRV_EVENT_XStateToKeyState( event->state );
switch (buttonNum)
{
case 0:
keystate &= ~MK_LBUTTON;
break;
case 1:
keystate &= ~MK_MBUTTON;
break;
case 2:
keystate &= ~MK_RBUTTON;
break;
}
X11DRV_SendEvent( statusCodes[buttonNum], 0, 0, keystate, 0,
event->time - X11DRV_server_startticks, DGAhwnd );
}
#endif
......@@ -27,12 +27,10 @@
#include "windef.h"
#include "wingdi.h"
#include "wine/winuser16.h"
#include "dinput.h"
#include "debugtools.h"
#include "user.h"
#include "winnls.h"
#include "win.h"
#include "x11drv.h"
#include "debugtools.h"
DEFAULT_DEBUG_CHANNEL(keyboard);
DECLARE_DEBUG_CHANNEL(key);
......@@ -512,92 +510,102 @@ static unsigned kbd_layout=0; /* index into above table of layouts */
/* Yes, to distinguish based on scan codes, also
for PrtScn key ... GA */
static const WORD special_key_vkey[] =
static const WORD nonchar_key_vkey[256] =
{
/* unused */
0, 0, 0, 0, 0, 0, 0, 0, /* FF00 */
/* special keys */
VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
0, 0, 0, VK_ESCAPE /* FF18 */
};
static const WORD special_key_scan[] =
{
0x0E, 0x0F, 0, /*?*/ 0, 0, 0x1C, 0, 0, /* FF08 */
0, 0, 0, 0x45, 0x46, 0 , 0, 0, /* FF10 */
0, 0, 0, 0x01 /* FF18 */
};
static const WORD cursor_key_vkey[] =
{
VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
VK_NEXT, VK_END /* FF50 */
};
static const WORD cursor_key_scan[] =
{
0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F /* FF50 */
};
static const WORD misc_key_vkey[] =
{
0, 0, 0, VK_ESCAPE, 0, 0, 0, 0, /* FF18 */
/* unused */
0, 0, 0, 0, 0, 0, 0, 0, /* FF20 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF28 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF30 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF38 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF40 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF48 */
/* cursor keys */
VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, /* FF50 */
VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
0, 0, 0, 0, 0, 0, 0, 0, /* FF58 */
/* misc keys */
VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL /* FF68 */
};
static const WORD misc_key_scan[] =
{
/*?*/ 0, 0x137, /*?*/ 0, 0x152, 0, 0, 0, 0, /* FF60 */
/*?*/ 0, /*?*/ 0, 0x38, 0x146 /* FF68 */
};
static const WORD keypad_key_vkey[] =
{
0, VK_NUMLOCK, /* FF7E */
VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0, /* FF68 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF70 */
/* keypad keys */
0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK, /* FF78 */
0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
VK_INSERT, VK_DELETE, /* FF98 */
0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT,
VK_DECIMAL, VK_DIVIDE, /* FFA8 */
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
VK_NUMPAD8, VK_NUMPAD9 /* FFB8 */
};
static const WORD keypad_key_scan[] =
{
0x138, 0x145, /* FF7E */
0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
0, 0, 0, 0, 0, 0x11C, 0, 0, /* FF88 */
0, 0, 0, 0, 0, 0x47, 0x4B, 0x48, /* FF90 */
0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53, /* FF98 */
VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, /* FF98 */
VK_END, 0, VK_INSERT, VK_DELETE,
0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
0, 0, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135, /* FFA8 */
0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* FFB0 */
0x48, 0x49 /* FFB8 */
};
static const WORD function_key_vkey[] =
{
VK_F1, VK_F2, /* FFBE */
0, 0, VK_MULTIPLY, VK_ADD, /* FFA8 */
VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, /* FFB0 */
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0, /* FFB8 */
/* function keys */
VK_F1, VK_F2,
VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16 /* FFC8 */
};
static const WORD function_key_scan[] =
{
0x3B, 0x3C, /* FFBE */
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, /* FFC0 */
0x57, 0x58, 0, 0, 0, 0 /* FFC8 */
VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0, /* FFC8 */
0, 0, 0, 0, 0, 0, 0, 0, /* FFD0 */
0, 0, 0, 0, 0, 0, 0, 0, /* FFD8 */
/* modifier keys */
0, VK_SHIFT, VK_SHIFT, VK_CONTROL, /* FFE0 */
VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0, /* FFE8 */
0, 0, 0, 0, 0, 0, 0, 0, /* FFF0 */
0, 0, 0, 0, 0, 0, 0, VK_DELETE /* FFF8 */
};
static const WORD modifier_key_vkey[] =
{
VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */
};
static const WORD modifier_key_scan[] =
{
0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0, /* FFE1 */
0x38, 0x138, 0x38, 0x138 /* FFE7 */
static const WORD nonchar_key_scan[256] =
{
/* unused */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF00 */
/* special keys */
0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00, /* FF08 */
0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00, /* FF10 */
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, /* FF18 */
/* unused */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF20 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF28 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF30 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF38 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF40 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF48 */
/* cursor keys */
0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F, /* FF50 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF58 */
/* misc keys */
/*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00, /* FF60 */
/*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00, /* FF68 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF70 */
/* keypad keys */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145, /* FF78 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF80 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00, /* FF88 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48, /* FF90 */
0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53, /* FF98 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFA0 */
0x00, 0x00, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135, /* FFA8 */
0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* FFB0 */
0x48, 0x49, 0x00, 0x00, 0x00, 0x00, /* FFB8 */
/* function keys */
0x3B, 0x3C,
0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, /* FFC0 */
0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFC8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD8 */
/* modifier keys */
0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38, /* FFE0 */
0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFE8 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFF0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153 /* FFF8 */
};
/* Returns the Windows virtual key code associated with the X event <e> */
static WORD EVENT_event_to_vkey( XKeyEvent *e)
{
......@@ -609,7 +617,7 @@ static WORD EVENT_event_to_vkey( XKeyEvent *e)
&& (e->state & NumLockMask))
/* Only the Keypad keys 0-9 and . send different keysyms
* depending on the NumLock state */
return keypad_key_vkey[(keysym & 0xFF) - 0x7E];
return nonchar_key_vkey[keysym & 0xFF];
return keyc2vkey[e->keycode];
}
......@@ -620,11 +628,11 @@ static BOOL NumState=FALSE, CapsState=FALSE;
/***********************************************************************
* send_keyboard_input
*/
void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
static void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
{
INPUT input;
input.type = INPUT_KEYBOARD;
input.type = WINE_INTERNAL_INPUT_KEYBOARD;
input.u.ki.wVk = wVk;
input.u.ki.wScan = wScan;
input.u.ki.dwFlags = dwFlags;
......@@ -686,7 +694,7 @@ static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_
* Updates internal state for <vkey>, depending on key <state> under X
*
*/
static void KEYBOARD_UpdateOneState ( int vkey, int state )
inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
{
/* Do something if internal table state != X state for keycode */
if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
......@@ -695,41 +703,44 @@ static void KEYBOARD_UpdateOneState ( int vkey, int state )
vkey, pKeyStateTable[vkey]);
/* Fake key being pressed inside wine */
send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, GetTickCount() );
send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time );
TRACE("State after %#.2x \n",pKeyStateTable[vkey]);
}
}
/***********************************************************************
* X11DRV_KEYBOARD_UpdateState
* X11DRV_KeymapNotify
*
* Update modifiers state (Ctrl, Alt, Shift)
* when window is activated (called by EVENT_FocusIn in event.c)
* Update modifiers state (Ctrl, Alt, Shift) when window is activated.
*
* This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
* from wine to another application and back.
* Toggle keys are handled in HandleEvent. (because XQueryKeymap says nothing
* about them)
* Toggle keys are handled in HandleEvent.
*/
void X11DRV_KEYBOARD_UpdateState ( void )
void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
{
/* extract a bit from the char[32] bit suite */
#define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0)
char keys_return[32];
int i, j, alt, control, shift;
DWORD time = GetCurrentTime();
TRACE("called\n");
if (!TSXQueryKeymap(thread_display(), keys_return)) {
ERR("Error getting keymap !\n");
return;
alt = control = shift = 0;
for (i = 0; i < 32; i++)
{
if (!event->key_vector[i]) continue;
for (j = 0; j < 8; j++)
{
if (!(event->key_vector[i] & (1<<j))) continue;
switch(keyc2vkey[(i * 8) + j] & 0xff)
{
case VK_MENU: alt = 1; break;
case VK_CONTROL: control = 1; break;
case VK_SHIFT: shift = 1; break;
}
}
}
/* Adjust the ALT and CONTROL state if any has been changed outside wine */
KEYBOARD_UpdateOneState(VK_MENU, KeyState(kcAlt));
KEYBOARD_UpdateOneState(VK_CONTROL, KeyState(kcControl));
KEYBOARD_UpdateOneState(VK_SHIFT, KeyState(kcShift));
#undef KeyState
KEYBOARD_UpdateOneState( VK_MENU, alt, time );
KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
}
/***********************************************************************
......@@ -1022,30 +1033,8 @@ void X11DRV_InitKeyboard( BYTE *key_state_table )
{
if ((keysym >> 8) == 0xFF) /* non-character key */
{
int key = keysym & 0xff;
if (key >= 0x08 && key <= 0x1B) { /* special key */
vkey = special_key_vkey[key - 0x08];
scan = special_key_scan[key - 0x08];
} else if (key >= 0x50 && key <= 0x57) { /* cursor key */
vkey = cursor_key_vkey[key - 0x50];
scan = cursor_key_scan[key - 0x50];
} else if (key >= 0x60 && key <= 0x6B) { /* miscellaneous key */
vkey = misc_key_vkey[key - 0x60];
scan = misc_key_scan[key - 0x60];
} else if (key >= 0x7E && key <= 0xB9) { /* keypad key */
vkey = keypad_key_vkey[key - 0x7E];
scan = keypad_key_scan[key - 0x7E];
} else if (key >= 0xBE && key <= 0xCD) { /* function key */
vkey = function_key_vkey[key - 0xBE] | 0x100; /* set extended bit */
scan = function_key_scan[key - 0xBE];
} else if (key >= 0xE1 && key <= 0xEA) { /* modifier key */
vkey = modifier_key_vkey[key - 0xE1];
scan = modifier_key_scan[key - 0xE1];
} else if (key == 0xFF) { /* DEL key */
vkey = VK_DELETE;
scan = 0x153;
}
vkey = nonchar_key_vkey[keysym & 0xff];
scan = nonchar_key_scan[keysym & 0xff];
/* set extended bit when necessary */
if (scan & 0x100) vkey |= 0x100;
} else if (keysym == 0x20) { /* Spacebar */
......@@ -1654,72 +1643,3 @@ void X11DRV_Beep(void)
{
TSXBell(thread_display(), 0);
}
/***********************************************************************
* GetDIState (X11DRV.@)
*/
BOOL X11DRV_GetDIState(DWORD len, LPVOID ptr)
{
if (len==256) {
int keyc,vkey;
memset(ptr,0,256);
for (keyc=min_keycode;keyc<max_keycode;keyc++)
{
/* X keycode to virtual key */
vkey = keyc2vkey[keyc] & 0xFF;
/* The windows scancode is keyc-min_keycode */
if (pKeyStateTable[vkey]&0x80) {
((LPBYTE)ptr)[keyc-min_keycode]=0x80;
((LPBYTE)ptr)[(keyc-min_keycode)|0x80]=0x80;
}
}
return TRUE;
}
WARN("whoops, got len %ld?\n", len);
return TRUE;
}
/***********************************************************************
* GetDIData (X11DRV.@)
*/
BOOL X11DRV_GetDIData(
BYTE *keystate,
DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
LPDWORD entries, DWORD flags)
{
int keyc,n,vkey,xentries;
/* FIXME !!! */
if (entries)
xentries = *entries;
else
xentries = 1;
n = 0;
for (keyc=min_keycode;(keyc<max_keycode) && (n<*entries);keyc++)
{
/* X keycode to virtual key */
vkey = keyc2vkey[keyc] & 0xFF;
if (keystate[vkey] == (pKeyStateTable[vkey]&0x80))
continue;
if (dod) {
/* add an entry */
dod[n].dwOfs = keyc-min_keycode; /* scancode */
dod[n].dwData = pKeyStateTable[vkey]&0x80;
dod[n].dwTimeStamp = 0; /* umm */
dod[n].dwSequence = 0; /* umm */
n++;
}
if (!(flags & DIGDD_PEEK))
keystate[vkey] = pKeyStateTable[vkey]&0x80;
}
if (n) TRACE_(dinput)("%d entries\n",n);
*entries = n;
return TRUE;
}
/*
* X11 mouse driver
*
* Copyright 1998 Ulrich Weigand
*/
#include "config.h"
#include "ts_xlib.h"
#include "windef.h"
#include "wine/winuser16.h"
#include "debugtools.h"
#include "mouse.h"
#include "win.h"
#include "x11drv.h"
DEFAULT_DEBUG_CHANNEL(cursor);
/**********************************************************************/
static LONG X11DRV_MOUSE_WarpPointer = 0; /* hack; see DISPLAY_MoveCursor */
static LPMOUSE_EVENT_PROC DefMouseEventProc = NULL;
/***********************************************************************
* X11DRV_GetCursor
*/
Cursor X11DRV_GetCursor( Display *display, CURSORICONINFO *ptr )
{
Pixmap pixmapBits, pixmapMask, pixmapMaskInv, pixmapAll;
XColor fg, bg;
Cursor cursor = None;
if (!ptr) /* Create an empty cursor */
{
static const char data[] = { 0 };
bg.red = bg.green = bg.blue = 0x0000;
pixmapBits = XCreateBitmapFromData( display, root_window, data, 1, 1 );
if (pixmapBits)
{
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapBits,
&bg, &bg, 0, 0 );
XFreePixmap( display, pixmapBits );
}
}
else /* Create the X cursor from the bits */
{
XImage *image;
GC gc;
if (ptr->bPlanes * ptr->bBitsPerPixel != 1)
{
WARN("Cursor has more than 1 bpp!\n" );
return 0;
}
/* Create a pixmap and transfer all the bits to it */
/* NOTE: Following hack works, but only because XFree depth
* 1 images really use 1 bit/pixel (and so the same layout
* as the Windows cursor data). Perhaps use a more generic
* algorithm here.
*/
if (!(pixmapAll = XCreatePixmap( display, root_window,
ptr->nWidth, ptr->nHeight * 2, 1 ))) return 0;
if (!(image = XCreateImage( display, visual,
1, ZPixmap, 0, (char *)(ptr + 1), ptr->nWidth,
ptr->nHeight * 2, 16, ptr->nWidthBytes))) return 0;
gc = XCreateGC( display, pixmapAll, 0, NULL );
XSetGraphicsExposures( display, gc, False );
image->byte_order = MSBFirst;
image->bitmap_bit_order = MSBFirst;
image->bitmap_unit = 16;
_XInitImageFuncPtrs(image);
XPutImage( display, pixmapAll, gc, image,
0, 0, 0, 0, ptr->nWidth, ptr->nHeight * 2 );
image->data = NULL;
XDestroyImage( image );
/* Now create the 2 pixmaps for bits and mask */
pixmapBits = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
pixmapMask = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
pixmapMaskInv = XCreatePixmap( display, root_window, ptr->nWidth, ptr->nHeight, 1 );
/* Make sure everything went OK so far */
if (pixmapBits && pixmapMask && pixmapMaskInv)
{
/* We have to do some magic here, as cursors are not fully
* compatible between Windows and X11. Under X11, there
* are only 3 possible color cursor: black, white and
* masked. So we map the 4th Windows color (invert the
* bits on the screen) to black and an additional white bit on
* an other place (+1,+1). This require some boolean arithmetic:
*
* Windows | X11
* And Xor Result | Bits Mask Result
* 0 0 black | 0 1 background
* 0 1 white | 1 1 foreground
* 1 0 no change | X 0 no change
* 1 1 inverted | 0 1 background
*
* which gives:
* Bits = not 'And' and 'Xor' or 'And2' and 'Xor2'
* Mask = not 'And' or 'Xor' or 'And2' and 'Xor2'
*
* FIXME: apparently some servers do support 'inverted' color.
* I don't know if it's correct per the X spec, but maybe
* we ought to take advantage of it. -- AJ
*/
XSetFunction( display, gc, GXcopy );
XCopyArea( display, pixmapAll, pixmapBits, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XCopyArea( display, pixmapAll, pixmapMask, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
0, 0, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXand );
XCopyArea( display, pixmapAll, pixmapMaskInv, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXandReverse );
XCopyArea( display, pixmapAll, pixmapBits, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
XSetFunction( display, gc, GXorReverse );
XCopyArea( display, pixmapAll, pixmapMask, gc,
0, ptr->nHeight, ptr->nWidth, ptr->nHeight, 0, 0 );
/* Additional white */
XSetFunction( display, gc, GXor );
XCopyArea( display, pixmapMaskInv, pixmapMask, gc,
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
XCopyArea( display, pixmapMaskInv, pixmapBits, gc,
0, 0, ptr->nWidth, ptr->nHeight, 1, 1 );
XSetFunction( display, gc, GXcopy );
fg.red = fg.green = fg.blue = 0xffff;
bg.red = bg.green = bg.blue = 0x0000;
cursor = XCreatePixmapCursor( display, pixmapBits, pixmapMask,
&fg, &bg, ptr->ptHotSpot.x, ptr->ptHotSpot.y );
}
/* Now free everything */
if (pixmapAll) XFreePixmap( display, pixmapAll );
if (pixmapBits) XFreePixmap( display, pixmapBits );
if (pixmapMask) XFreePixmap( display, pixmapMask );
if (pixmapMaskInv) XFreePixmap( display, pixmapMaskInv );
XFreeGC( display, gc );
}
return cursor;
}
/* set the cursor of a window; helper for X11DRV_SetCursor */
static BOOL CALLBACK set_win_cursor( HWND hwnd, LPARAM cursor )
{
Window win = X11DRV_get_whole_window( hwnd );
if (win) TSXDefineCursor( thread_display(), win, (Cursor)cursor );
return TRUE;
}
/***********************************************************************
* SetCursor (X11DRV.@)
*/
void X11DRV_SetCursor( CURSORICONINFO *lpCursor )
{
Cursor cursor;
if (root_window != DefaultRootWindow(gdi_display))
{
/* If in desktop mode, set the cursor on the desktop window */
wine_tsx11_lock();
cursor = X11DRV_GetCursor( gdi_display, lpCursor );
if (cursor)
{
XDefineCursor( gdi_display, root_window, cursor );
XFreeCursor( gdi_display, cursor );
}
wine_tsx11_unlock();
}
else /* set the same cursor for all top-level windows of the current thread */
{
Display *display = thread_display();
wine_tsx11_lock();
cursor = X11DRV_GetCursor( display, lpCursor );
wine_tsx11_unlock();
if (cursor)
{
/* EnumThreadWindows( GetCurrentThreadId(), set_win_cursor, (LPARAM)cursor );*/
EnumWindows( set_win_cursor, (LPARAM)cursor );
TSXFreeCursor( display, cursor );
}
}
}
/***********************************************************************
* SetCursorPos (X11DRV.@)
*/
void X11DRV_SetCursorPos(INT wAbsX, INT wAbsY)
{
/*
* We do not want to create MotionNotify events here,
* otherwise we will get an endless recursion:
* XMotionEvent -> MOUSEEVENTF_MOVE -> mouse_event -> DisplayMoveCursor
* -> XWarpPointer -> XMotionEvent -> ...
*
* Unfortunately, the XWarpPointer call does create a MotionNotify
* event. So, we use a hack: before MOUSE_SendEvent calls the mouse event
* procedure, it sets a global flag. If this flag is set, we skip the
* XWarpPointer call. If we are *not* called from within MOUSE_SendEvent,
* we will call XWarpPointer, which will create a MotionNotify event.
* Strictly speaking, this is also wrong, but that should normally not
* have any negative effects ...
*
* But first of all, we check whether we already are at the position
* are supposed to move to; if so, we don't need to do anything.
*/
Display *display = thread_display();
Window root, child;
int rootX, rootY, winX, winY;
unsigned int xstate;
if (X11DRV_MOUSE_WarpPointer < 0) return;
if (!TSXQueryPointer( display, root_window, &root, &child,
&rootX, &rootY, &winX, &winY, &xstate ))
return;
if ( winX == wAbsX && winY == wAbsY )
return;
TRACE("(%d,%d): moving from (%d,%d)\n", wAbsX, wAbsY, winX, winY );
wine_tsx11_lock();
XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, wAbsX, wAbsY );
XFlush( display ); /* just in case */
wine_tsx11_unlock();
}
/***********************************************************************
* GetCursorPos (X11DRV.@)
*/
void X11DRV_GetCursorPos(LPPOINT pos)
{
Display *display = thread_display();
Window root, child;
int rootX, rootY, winX, winY;
unsigned int xstate;
if (!TSXQueryPointer( display, root_window, &root, &child,
&rootX, &rootY, &winX, &winY, &xstate ))
return;
TRACE("pointer at (%d,%d)\n", winX, winY );
pos->x = winX;
pos->y = winY;
}
/***********************************************************************
* InitMouse (X11DRV.@)
*/
void X11DRV_InitMouse( LPMOUSE_EVENT_PROC proc )
{
static int init_done;
DefMouseEventProc = proc;
if (!init_done)
{
Window root, child;
int root_x, root_y, child_x, child_y;
unsigned int KeyState;
init_done = 1;
/* Get the current mouse position and simulate an absolute mouse
movement to initialize the mouse global variables */
TSXQueryPointer( thread_display(), root_window, &root, &child,
&root_x, &root_y, &child_x, &child_y, &KeyState);
X11DRV_SendEvent(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE,
root_x, root_y, X11DRV_EVENT_XStateToKeyState(KeyState),
0, GetTickCount(), 0 );
}
}
/***********************************************************************
* X11DRV_SendEvent (internal)
*/
void X11DRV_SendEvent( DWORD mouseStatus, DWORD posX, DWORD posY,
WORD keyState, DWORD data, DWORD time, HWND hWnd )
{
int iWndsLocks;
WINE_MOUSEEVENT wme;
if ( !DefMouseEventProc ) return;
TRACE("(%04lX,%ld,%ld)\n", mouseStatus, posX, posY );
if (mouseStatus & MOUSEEVENTF_ABSOLUTE)
{
int width = GetSystemMetrics( SM_CXSCREEN );
int height = GetSystemMetrics( SM_CYSCREEN );
/* Relative mouse movements seems not to be scaled as absolute ones */
posX = (((long)posX << 16) + width-1) / width;
posY = (((long)posY << 16) + height-1) / height;
}
wme.magic = WINE_MOUSEEVENT_MAGIC;
wme.time = time;
wme.hWnd = hWnd;
wme.keyState = keyState;
InterlockedDecrement( &X11DRV_MOUSE_WarpPointer );
/* To avoid deadlocks, we have to suspend all locks on windows structures
before the program control is passed to the mouse driver */
iWndsLocks = WIN_SuspendWndsLock();
DefMouseEventProc( mouseStatus, posX, posY, data, (DWORD)&wme );
WIN_RestoreWndsLock(iWndsLocks);
InterlockedIncrement( &X11DRV_MOUSE_WarpPointer );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment