From e35d6366ef36741ea93726f662b62d763edc5853 Mon Sep 17 00:00:00 2001 From: Patrik Stridvall Date: Mon, 7 Dec 1998 09:13:40 +0000 Subject: [PATCH] Moved more code to the X11 driver. --- include/clipboard.h | 33 +- include/keyboard.h | 15 +- include/message.h | 25 +- include/win.h | 20 +- include/x11drv.h | 66 +- windows/clipboard.c | 307 +------- windows/defwnd.c | 8 +- windows/dinput.c | 26 +- windows/display.c | 8 +- windows/event.c | 1383 ++--------------------------------- windows/focus.c | 40 +- windows/keyboard.c | 858 ++-------------------- windows/message.c | 4 +- windows/nonclient.c | 6 +- windows/win.c | 33 +- windows/winpos.c | 156 +--- windows/x11drv/Makefile.in | 7 +- windows/x11drv/clipboard.c | 299 ++++++++ windows/x11drv/event.c | 1388 ++++++++++++++++++++++++++++++++++++ windows/x11drv/init.c | 169 ++--- windows/x11drv/keyboard.c | 815 +++++++++++++++++++++ windows/x11drv/mouse.c | 13 + windows/x11drv/wnd.c | 431 +++++++++++ 23 files changed, 3319 insertions(+), 2791 deletions(-) create mode 100644 windows/x11drv/clipboard.c create mode 100644 windows/x11drv/event.c create mode 100644 windows/x11drv/keyboard.c create mode 100644 windows/x11drv/mouse.c create mode 100644 windows/x11drv/wnd.c diff --git a/include/clipboard.h b/include/clipboard.h index 69ef1d73550..4bda6641b6c 100644 --- a/include/clipboard.h +++ b/include/clipboard.h @@ -1,10 +1,33 @@ #ifndef __WINE_CLIPBOARD_H #define __WINE_CLIPBOARD_H -void CLIPBOARD_ResetLock(HQUEUE16 hqRef, HQUEUE16 hqNew); -void CLIPBOARD_ResetOwner(WND* pWnd); -void CLIPBOARD_ReadSelection(Window w, Atom prop); -void CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd); -BOOL32 CLIPBOARD_IsPresent(WORD wFormat); +#include "win.h" +#include "wintypes.h" + +typedef struct tagCLIPFORMAT { + WORD wFormatID; + WORD wRefCount; + WORD wDataPresent; + LPSTR Name; + HANDLE32 hData32; + DWORD BufSize; + struct tagCLIPFORMAT *PrevFormat; + struct tagCLIPFORMAT *NextFormat; + HANDLE16 hData16; +} CLIPFORMAT, *LPCLIPFORMAT; + +typedef struct _CLIPBOARD_DRIVER +{ + void (*pEmptyClipboard)(); + void (*pSetClipboardData)(UINT32); + BOOL32 (*pRequestSelection)(); + void (*pResetOwner)(WND *); +} CLIPBOARD_DRIVER; + +CLIPBOARD_DRIVER *CLIPBOARD_GetDriver(); + +extern void CLIPBOARD_ResetLock(HQUEUE16 hqRef, HQUEUE16 hqNew); +extern void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange); +extern BOOL32 CLIPBOARD_IsPresent(WORD wFormat); #endif /* __WINE_CLIPBOARD_H */ diff --git a/include/keyboard.h b/include/keyboard.h index 26049b14620..45ed3bbb21c 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -7,6 +7,8 @@ #ifndef __WINE_KEYBOARD_H #define __WINE_KEYBOARD_H +#include "wintypes.h" + #pragma pack(1) typedef struct _KBINFO { @@ -27,8 +29,17 @@ VOID WINAPI KEYBOARD_Disable(VOID); /* Wine internals */ -extern void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event ); -extern void KEYBOARD_UpdateState( void ); +typedef struct _KEYBOARD_DRIVER { + void (*pInit)(); + WORD (*pVkKeyScan)(CHAR); + UINT16 (*pMapVirtualKey)(UINT16, UINT16); + INT16 (*pGetKeyNameText)(LONG, LPSTR, INT16); + INT16 (*pToAscii)(UINT16, UINT16, LPBYTE, LPVOID, UINT16); +} KEYBOARD_DRIVER; + +extern KEYBOARD_DRIVER *KEYBOARD_GetDriver(); + +extern void KEYBOARD_SendEvent(BYTE bVk, BYTE bScan, DWORD dwFlags, DWORD posX, DWORD posY, DWORD time); #define WINE_KEYBDEVENT_MAGIC ( ('K'<<24)|('E'<<16)|('Y'<<8)|'B' ) typedef struct _WINE_KEYBDEVENT diff --git a/include/message.h b/include/message.h index 909235c7565..02519973b90 100644 --- a/include/message.h +++ b/include/message.h @@ -9,6 +9,7 @@ #include "win.h" #include "queue.h" +#include "wintypes.h" extern DWORD MSG_WineStartTicks; /* Ticks at Wine startup */ @@ -31,16 +32,32 @@ extern BOOL32 TIMER_GetTimerMsg( MSG16 *msg, HWND32 hwnd, #define EVENT_IO_EXCEPT 2 /* event.c */ + +typedef struct _EVENT_DRIVER { + BOOL32 (*pInit)(void); + void (*pAddIO)(int, unsigned); + void (*pDeleteIO)(int, unsigned); + BOOL32 (*pWaitNetEvent)(BOOL32, BOOL32); + void (*pSynchronize)(void); + BOOL32 (*pCheckFocus)(void); + BOOL32 (*pQueryPointer)(DWORD *, DWORD *, DWORD *); + void (*pDummyMotionNotify)(void); + BOOL32 (*pPending)(void); + BOOL16 (*pIsUserIdle)(void); +} EVENT_DRIVER; + extern void EVENT_AddIO( int fd, unsigned flag ); -extern BOOL32 EVENT_CheckFocus( void ); extern void EVENT_DeleteIO( int fd, unsigned flag ); extern BOOL32 EVENT_Init( void ); extern BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ); extern void EVENT_Synchronize(void); -extern void EVENT_ProcessEvent( XEvent *event ); -extern void EVENT_RegisterWindow( WND *pWnd ); -extern void EVENT_DestroyWindow( WND *pWnd ); +extern BOOL32 EVENT_CheckFocus( void ); +extern BOOL32 EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state); extern void EVENT_DummyMotionNotify(void); +extern BOOL32 EVENT_Pending(void); + +/* input.c */ + extern HWND32 EVENT_Capture( HWND32, INT16 ); extern INT16 EVENT_GetCaptureInfo(void); extern BOOL32 EVENT_QueryPointer( DWORD *posX, DWORD *posY, DWORD *state ); diff --git a/include/win.h b/include/win.h index 586e693312d..a7c4821742e 100644 --- a/include/win.h +++ b/include/win.h @@ -7,7 +7,11 @@ #ifndef __WINE_WIN_H #define __WINE_WIN_H -#include "ts_xlib.h" +#include "config.h" + +#ifndef X_DISPLAY_MISSING +#include +#endif /* !defined(X_DISPLAY_MISSING) */ #include "ldt.h" #include "class.h" @@ -89,14 +93,18 @@ typedef struct tagWND typedef struct _WND_DRIVER { + BOOL32 (*pCreateDesktopWindow)(WND *, CLASS *, BOOL32); BOOL32 (*pCreateWindow)(WND *, CLASS *, CREATESTRUCT32A *, BOOL32); + BOOL32 (*pDestroyWindow)(WND *); WND* (*pSetParent)(WND *, WND *); + void (*pForceWindowRaise)(WND *); + void (*pSetWindowPos)(WND *, const WINDOWPOS32 *, BOOL32); + void (*pSetText)(WND *, LPCSTR); + void (*pSetFocus)(WND *); + void (*pPreSizeMove)(WND *); + void (*pPostSizeMove)(WND *); } WND_DRIVER; -/* X11 windows driver */ -/* FIXME: does not belong here */ -extern WND_DRIVER X11DRV_WND_Driver; - typedef struct { RECT16 rectNormal; @@ -130,7 +138,6 @@ extern WND* WIN_FindWndPtr( HWND32 hwnd ); extern WND* WIN_GetDesktop(void); extern void WIN_DumpWindow( HWND32 hwnd ); extern void WIN_WalkWindows( HWND32 hwnd, int indent ); -extern Window WIN_GetXWindow( HWND32 hwnd ); extern BOOL32 WIN_UnlinkWindow( HWND32 hwnd ); extern BOOL32 WIN_LinkWindow( HWND32 hwnd, HWND32 hwndInsertAfter ); extern HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue ); @@ -164,7 +171,6 @@ extern HWND32 ICONTITLE_Create( WND* ); extern BOOL32 ICONTITLE_Init( void ); /* windows/focus.c */ -extern void FOCUS_SetXFocus( HWND32 ); extern void FOCUS_SwitchFocus( HWND32 , HWND32 ); extern Display * display; diff --git a/include/x11drv.h b/include/x11drv.h index dc9fb224666..61f43b28260 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -5,12 +5,18 @@ #ifndef __WINE_X11DRV_H #define __WINE_X11DRV_H +#include "config.h" #include "ts_xlib.h" #include "ts_xutil.h" + #include "winbase.h" #include "windows.h" #include "gdi.h" #include "xmalloc.h" /* for XCREATEIMAGE macro */ +#include "clipboard.h" +#include "keyboard.h" +#include "message.h" +#include "win.h" /* X physical pen */ typedef struct @@ -181,7 +187,6 @@ extern void _XInitImageFuncPtrs(XImage *); (width), (height), 32, width_bytes ); \ } - /* exported dib functions for now */ /* This structure holds the arguments for DIB_SetImageBits() */ @@ -213,6 +218,63 @@ extern int *X11DRV_DIB_BuildColorMap( struct tagDC *dc, WORD coloruse, WORD depth, const BITMAPINFO *info, int *nColors ); +/* X11 windows driver */ +extern WND_DRIVER X11DRV_WND_Driver; + +extern Window X11DRV_WND_GetXWindow(HWND32 hwnd); + +extern BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode); +extern BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode); +extern BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd); +extern WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent); +extern void X11DRV_WND_ForceWindowRaise(WND *pWnd); +extern void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS); +extern void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text); +extern void X11DRV_WND_SetFocus(WND *wndPtr); +extern void X11DRV_WND_PreSizeMove(WND *wndPtr); +extern void X11DRV_WND_PostSizeMove(WND *wndPtr); + +/* X11 clipboard driver */ + +extern CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver; + +extern void X11DRV_CLIPBOARD_EmptyClipboard(); +extern void X11DRV_CLIPBOARD_SetClipboardData(UINT32 wFormat); +extern BOOL32 X11DRV_CLIPBOARD_RequestSelection(); +extern void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd); + +void X11DRV_CLIPBOARD_ReadSelection(Window w, Atom prop); +void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd); + +/* X11 keyboard driver */ + +extern KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver; + +extern void X11DRV_KEYBOARD_Init(void); +extern WORD X11DRV_KEYBOARD_VkKeyScan(CHAR cChar); +extern UINT16 X11DRV_KEYBOARD_MapVirtualKey(UINT16 wCode, UINT16 wMapType); +extern INT16 X11DRV_KEYBOARD_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT16 nSize); +extern INT16 X11DRV_KEYBOARD_ToAscii(UINT16 virtKey, UINT16 scanCode, LPBYTE lpKeyState, LPVOID lpChar, UINT16 flags); + +/* X11 mouse driver */ + +#if 0 +extern MOUSE_DRIVER X11DRV_MOUSE_Driver; +#endif + +/* X11 event driver */ + +extern EVENT_DRIVER X11DRV_EVENT_Driver; + +extern BOOL32 X11DRV_EVENT_Init(void); +extern void X11DRV_EVENT_AddIO(int fd, unsigned flag); +extern void X11DRV_EVENT_DeleteIO(int fd, unsigned flag); +extern BOOL32 X11DRV_EVENT_WaitNetEvent(BOOL32 sleep, BOOL32 peek); +extern void X11DRV_EVENT_Synchronize(void); +extern BOOL32 X11DRV_EVENT_CheckFocus( void ); +extern BOOL32 X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state); +extern void X11DRV_EVENT_DummyMotionNotify(void); +extern BOOL32 X11DRV_EVENT_Pending(void); +extern BOOL16 X11DRV_EVENT_IsUserIdle(void); #endif /* __WINE_X11DRV_H */ - diff --git a/windows/clipboard.c b/windows/clipboard.c index e8fa56a1276..99382f9adcf 100644 --- a/windows/clipboard.c +++ b/windows/clipboard.c @@ -12,8 +12,6 @@ #include #include #include -#include "ts_xlib.h" -#include #include "windows.h" #include "win.h" #include "heap.h" @@ -22,39 +20,24 @@ #include "xmalloc.h" #include "debug.h" +extern CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver; + #define CF_REGFORMATBASE 0xC000 -typedef struct tagCLIPFORMAT { - WORD wFormatID; - WORD wRefCount; - WORD wDataPresent; - LPSTR Name; - HANDLE32 hData32; - DWORD BufSize; - struct tagCLIPFORMAT *PrevFormat; - struct tagCLIPFORMAT *NextFormat; - HANDLE16 hData16; -} CLIPFORMAT, *LPCLIPFORMAT; - -/* ************************************************************************* +/************************************************************************** * internal variables */ static HQUEUE16 hqClipLock = 0; static BOOL32 bCBHasChanged = FALSE; -static HWND32 hWndClipOwner = 0; /* current clipboard owner */ -static HWND32 hWndClipWindow = 0; /* window that opened clipboard */ +HWND32 hWndClipOwner = 0; /* current clipboard owner */ +HWND32 hWndClipWindow = 0; /* window that opened clipboard */ static HWND32 hWndViewer = 0; /* start of viewers chain */ static WORD LastRegFormat = CF_REGFORMATBASE; -static Bool selectionWait = False; -static Bool selectionAcquired = False; -static Window selectionWindow = None; -static Window selectionPrevWindow = None; - -static CLIPFORMAT ClipFormats[16] = { +CLIPFORMAT ClipFormats[16] = { { CF_TEXT, 1, 0, "Text", (HANDLE32)NULL, 0, NULL, &ClipFormats[1] , (HANDLE16)NULL}, { CF_BITMAP, 1, 0, "Bitmap", (HANDLE32)NULL, 0, &ClipFormats[0], &ClipFormats[2] , (HANDLE16)NULL}, { CF_METAFILEPICT, 1, 0, "MetaFile Picture", (HANDLE32)NULL, 0, &ClipFormats[1], &ClipFormats[3] , (HANDLE16)NULL}, @@ -84,39 +67,14 @@ static LPCLIPFORMAT __lookup_format( LPCLIPFORMAT lpFormat, WORD wID ) return lpFormat; } + /************************************************************************** - * CLIPBOARD_CheckSelection - * - * Prevent X selection from being lost when a top level window is - * destroyed. + * CLIPBOARD_GetDriver */ -static void CLIPBOARD_CheckSelection(WND* pWnd) +CLIPBOARD_DRIVER *CLIPBOARD_GetDriver() { - TRACE(clipboard,"\tchecking %08x\n", (unsigned)pWnd->window); - - if( selectionAcquired && selectionWindow != None && - pWnd->window == selectionWindow ) - { - selectionPrevWindow = selectionWindow; - selectionWindow = None; - - if( pWnd->next ) - selectionWindow = pWnd->next->window; - else if( pWnd->parent ) - if( pWnd->parent->child != pWnd ) - selectionWindow = pWnd->parent->child->window; - - TRACE(clipboard,"\tswitching selection from %08x to %08x\n", - (unsigned)selectionPrevWindow, (unsigned)selectionWindow); - - if( selectionWindow != None ) - { - TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime); - if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow ) - selectionWindow = None; - } - } -} + return &X11DRV_CLIPBOARD_Driver; +}; /************************************************************************** * CLIPBOARD_ResetLock @@ -137,46 +95,11 @@ void CLIPBOARD_ResetLock( HQUEUE16 hqCurrent, HQUEUE16 hqNew ) } } -/************************************************************************** - * CLIPBOARD_ResetOwner - * - * Called from DestroyWindow(). - */ -void CLIPBOARD_ResetOwner(WND* pWnd) -{ - LPCLIPFORMAT lpFormat = ClipFormats; - - TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n", - hWndClipOwner, (unsigned)selectionWindow); - - if( pWnd->hwndSelf == hWndClipOwner) - { - SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L); - - /* check if all formats were rendered */ - - while(lpFormat) - { - if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 ) - { - TRACE(clipboard,"\tdata missing for clipboard format %i\n", - lpFormat->wFormatID); - lpFormat->wDataPresent = 0; - } - lpFormat = lpFormat->NextFormat; - } - hWndClipOwner = 0; - } - - /* now try to salvage current selection from being destroyed by X */ - - if( pWnd->window ) CLIPBOARD_CheckSelection(pWnd); -} /************************************************************************** * CLIPBOARD_DeleteRecord */ -static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange) +void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange) { if( (lpFormat->wFormatID >= CF_GDIOBJFIRST && lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP ) @@ -220,41 +143,6 @@ static void CLIPBOARD_DeleteRecord(LPCLIPFORMAT lpFormat, BOOL32 bChange) if( bChange ) bCBHasChanged = TRUE; } -/************************************************************************** - * CLIPBOARD_RequestXSelection - */ -static BOOL32 CLIPBOARD_RequestXSelection() -{ - HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32(); - - if( !hWnd ) return FALSE; - - TRACE(clipboard,"Requesting selection...\n"); - - /* request data type XA_STRING, later - * CLIPBOARD_ReadSelection() will be invoked - * from the SelectionNotify event handler */ - - TSXConvertSelection(display,XA_PRIMARY,XA_STRING, - TSXInternAtom(display,"PRIMARY_TEXT",False), - WIN_GetXWindow(hWnd),CurrentTime); - - /* wait until SelectionNotify is processed - * - * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the - * CLIPBOARD_CheckSelection() ). - */ - - selectionWait=True; - while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE ); - - /* we treat Unix text as CF_OEMTEXT */ - TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n", - ClipFormats[CF_OEMTEXT-1].wDataPresent); - - return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent; -} - /************************************************************************** * CLIPBOARD_IsPresent */ @@ -370,17 +258,8 @@ BOOL32 WINAPI EmptyClipboard32(void) hWndClipOwner = hWndClipWindow; - if(selectionAcquired) - { - selectionAcquired = False; - selectionPrevWindow = selectionWindow; - selectionWindow = None; + CLIPBOARD_GetDriver()->pEmptyClipboard(); - TRACE(clipboard, "\tgiving up selection (spw = %08x)\n", - (unsigned)selectionPrevWindow); - - TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime); - } return TRUE; } @@ -409,7 +288,6 @@ HWND32 WINAPI GetClipboardOwner32(void) HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData ) { LPCLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat ); - Window owner; TRACE(clipboard, "(%04X, %04x) !\n", wFormat, hData); @@ -423,22 +301,7 @@ HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData ) if( (hqClipLock != GetTaskQueue(0)) || !lpFormat || (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; - /* Acquire X selection if text format */ - - if( !selectionAcquired && - (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) - { - owner = WIN_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() ); - TSXSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime); - if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner ) - { - selectionAcquired = True; - selectionWindow = owner; - - TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", - (unsigned) owner); - } - } + CLIPBOARD_GetDriver()->pSetClipboardData(wFormat); if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) { @@ -473,7 +336,6 @@ HANDLE16 WINAPI SetClipboardData16( UINT16 wFormat, HANDLE16 hData ) HANDLE32 WINAPI SetClipboardData32( UINT32 wFormat, HANDLE32 hData ) { LPCLIPFORMAT lpFormat = __lookup_format( ClipFormats, wFormat ); - Window owner; TRACE(clipboard, "(%08X, %08x) !\n", wFormat, hData); @@ -487,22 +349,7 @@ HANDLE32 WINAPI SetClipboardData32( UINT32 wFormat, HANDLE32 hData ) if( (hqClipLock != GetTaskQueue(0)) || !lpFormat || (!hData && (!hWndClipOwner || (hWndClipOwner != hWndClipWindow))) ) return 0; - /* Acquire X selection if text format */ - - if( !selectionAcquired && - (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) - { - owner = WIN_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() ); - TSXSetSelectionOwner(display,XA_PRIMARY,owner,CurrentTime); - if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner ) - { - selectionAcquired = True; - selectionWindow = owner; - - TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", - (unsigned) owner); - } - } + CLIPBOARD_GetDriver()->pSetClipboardData(wFormat); if ( lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32 ) { @@ -769,7 +616,8 @@ INT32 WINAPI CountClipboardFormats32(void) TRACE(clipboard,"(void)\n"); - if( !selectionAcquired ) CLIPBOARD_RequestXSelection(); + /* FIXME: Returns BOOL32 */ + CLIPBOARD_GetDriver()->pRequestSelection(); FormatCount += abs(lpFormat[CF_TEXT-1].wDataPresent - lpFormat[CF_OEMTEXT-1].wDataPresent); @@ -810,8 +658,8 @@ UINT32 WINAPI EnumClipboardFormats32( UINT32 wFormat ) if( hqClipLock != GetTaskQueue(0) ) return 0; - if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) - && !selectionAcquired) CLIPBOARD_RequestXSelection(); + if( (!wFormat || wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) + CLIPBOARD_GetDriver()->pRequestSelection(); if (wFormat == 0) { @@ -1037,8 +885,8 @@ BOOL32 WINAPI IsClipboardFormatAvailable32( UINT32 wFormat ) { TRACE(clipboard,"(%04X) !\n", wFormat); - if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) && - !selectionAcquired ) CLIPBOARD_RequestXSelection(); + if( (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) + CLIPBOARD_GetDriver()->pRequestSelection(); return CLIPBOARD_IsPresent(wFormat); } @@ -1094,117 +942,4 @@ INT32 WINAPI GetPriorityClipboardFormat32( UINT32 *lpPriorityList, INT32 nCount } -/************************************************************************** - * CLIPBOARD_ReadSelection - * - * Called from the SelectionNotify event handler. - */ -void CLIPBOARD_ReadSelection(Window w,Atom prop) -{ - HANDLE32 hText = 0; - LPCLIPFORMAT lpFormat = ClipFormats; - - TRACE(clipboard,"ReadSelection callback\n"); - - if(prop != None) - { - Atom atype=AnyPropertyType; - int aformat; - unsigned long nitems,remain; - unsigned char* val=NULL; - - TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop)); - - /* TODO: Properties longer than 64K */ - - if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING, - &atype, &aformat, &nitems, &remain, &val) != Success) - WARN(clipboard, "\tcouldn't read property\n"); - else - { - TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n", - TSXGetAtomName(display,atype),aformat,nitems,val); - - if(atype == XA_STRING && aformat == 8) - { - int i,inlcount = 0; - char* lpstr; - - TRACE(clipboard,"\tselection is '%s'\n",val); - - for(i=0; i <= nitems; i++) - if( val[i] == '\n' ) inlcount++; - - if( nitems ) - { - hText=GlobalAlloc32(GMEM_MOVEABLE, nitems + inlcount + 1); - if( (lpstr = (char*)GlobalLock32(hText)) ) - for(i=0,inlcount=0; i <= nitems; i++) - { - if( val[i] == '\n' ) lpstr[inlcount++]='\r'; - lpstr[inlcount++]=val[i]; - } - else hText = 0; - } - } - TSXFree(val); - } - } - - /* delete previous CF_TEXT and CF_OEMTEXT data */ - - if( hText ) - { - lpFormat = &ClipFormats[CF_TEXT-1]; - if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) - CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow)); - lpFormat = &ClipFormats[CF_OEMTEXT-1]; - if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) - CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow)); - - lpFormat->wDataPresent = 1; - lpFormat->hData32 = hText; - lpFormat->hData16 = 0; - } - - selectionWait=False; -} - -/************************************************************************** - * CLIPBOARD_ReleaseSelection - * - * Wine might have lost XA_PRIMARY selection because of - * EmptyClipboard() or other client. - */ -void CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd) -{ - /* w is the window that lost selection, - * - * selectionPrevWindow is nonzero if CheckSelection() was called. - */ - - TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", - (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow ); - - if( selectionAcquired ) - { - if( w == selectionWindow || selectionPrevWindow == None) - { - /* alright, we really lost it */ - - selectionAcquired = False; - selectionWindow = None; - - /* but we'll keep existing data for internal use */ - } - else if( w == selectionPrevWindow ) - { - w = TSXGetSelectionOwner(display, XA_PRIMARY); - if( w == None ) - TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime); - } - } - - selectionPrevWindow = None; -} diff --git a/windows/defwnd.c b/windows/defwnd.c index 5fdba8cf481..879ff50a6c1 100644 --- a/windows/defwnd.c +++ b/windows/defwnd.c @@ -60,12 +60,8 @@ void DEFWND_SetText( WND *wndPtr, LPCSTR text ) { if (!text) text = ""; if (wndPtr->text) HeapFree( SystemHeap, 0, wndPtr->text ); - wndPtr->text = HEAP_strdupA( SystemHeap, 0, text ); - if (wndPtr->window) - { - TSXStoreName( display, wndPtr->window, wndPtr->text ); - TSXSetIconName( display, wndPtr->window, wndPtr->text ); - } + wndPtr->text = HEAP_strdupA( SystemHeap, 0, text ); + wndPtr->pDriver->pSetText(wndPtr, wndPtr->text); } /*********************************************************************** diff --git a/windows/dinput.c b/windows/dinput.c index fbc2fc0f4b1..d2db6d0938b 100644 --- a/windows/dinput.c +++ b/windows/dinput.c @@ -18,11 +18,12 @@ * an utter mess.) */ +#include "ts_xlib.h" + #include "config.h" #include #include #include -#include #include #include "windows.h" @@ -470,17 +471,15 @@ static HRESULT WINAPI SysMouseA_SetDataFormat( if (df->dwFlags == DIDF_ABSAXIS) mthis->absolute = 1; else { - Window rw, cr; - int rx, ry, cx, cy; - unsigned int mask; + DWORD rx, ry; /* We need to get the initial "previous" position to be able to return deltas */ mthis->absolute = 0; /* Get the mouse position */ - TSXQueryPointer(display, rootWindow, &rw, &cr, - &rx, &ry, &cx, &cy, &mask); + EVENT_QueryPointer(&rx, &ry, NULL); + /* Fill the initial mouse state structure */ mthis->prevX = rx; mthis->prevY = ry; @@ -498,9 +497,7 @@ static HRESULT WINAPI SysMouseA_SetDataFormat( static HRESULT WINAPI SysMouseA_GetDeviceState( LPDIRECTINPUTDEVICE32A this,DWORD len,LPVOID ptr ) { - Window rw, cr; - int rx, ry, cx, cy; - unsigned int mask; + DWORD rx, ry, state; struct DIMOUSESTATE *mstate = (struct DIMOUSESTATE *) ptr; LPSYSMOUSE32A mthis = (LPSYSMOUSE32A) this; @@ -513,8 +510,7 @@ static HRESULT WINAPI SysMouseA_GetDeviceState( } /* Get the mouse position */ - TSXQueryPointer(display, rootWindow, &rw, &cr, - &rx, &ry, &cx, &cy, &mask); + EVENT_QueryPointer(&rx, &ry, &state); TRACE(dinput,"(X:%d - Y:%d)\n", rx, ry); /* Fill the mouse state structure */ @@ -529,10 +525,10 @@ static HRESULT WINAPI SysMouseA_GetDeviceState( mthis->prevY = ry; } mstate->lZ = 0; - mstate->rgbButtons[0] = (mask & Button1Mask ? 0xFF : 0x00); - mstate->rgbButtons[1] = (mask & Button3Mask ? 0xFF : 0x00); /* Windows button two is X button 3 */ - mstate->rgbButtons[2] = (mask & Button2Mask ? 0xFF : 0x00); - mstate->rgbButtons[3] = (mask & Button4Mask ? 0xFF : 0x00); + mstate->rgbButtons[0] = (state & MK_LBUTTON ? 0xFF : 0x00); + mstate->rgbButtons[1] = (state & MK_RBUTTON ? 0xFF : 0x00); + mstate->rgbButtons[2] = (state & MK_MBUTTON ? 0xFF : 0x00); + mstate->rgbButtons[3] = 0x00; return 0; } diff --git a/windows/display.c b/windows/display.c index c34a1454251..8282cccb418 100644 --- a/windows/display.c +++ b/windows/display.c @@ -5,13 +5,13 @@ * */ -#include -#include -#include #include "ts_xlib.h" #include "ts_xresource.h" #include "ts_xutil.h" +#include +#include +#include #include "windows.h" #include "win.h" #include "gdi.h" @@ -169,7 +169,7 @@ static BOOL32 DISPLAY_DoSetCursor( CURSORICONINFO *ptr ) HWND32 hwnd = GetWindow32( GetDesktopWindow32(), GW_CHILD ); while(hwnd) { - Window win = WIN_GetXWindow( hwnd ); + Window win = X11DRV_WND_GetXWindow( hwnd ); if (win && win!=DefaultRootWindow(display)) XDefineCursor( display, win, cursor ); hwnd = GetWindow32( hwnd, GW_HWNDNEXT ); diff --git a/windows/event.c b/windows/event.c index 3c96220399d..0a54bb0d05c 100644 --- a/windows/event.c +++ b/windows/event.c @@ -5,1404 +5,107 @@ * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "ts_xlib.h" -#include "ts_xresource.h" -#include "ts_xutil.h" -#include - -#include "windows.h" -#include "winnt.h" -#include "gdi.h" -#include "heap.h" -#include "queue.h" -#include "win.h" -#include "class.h" -#include "clipboard.h" -#include "dce.h" #include "message.h" -#include "module.h" -#include "options.h" -#include "queue.h" -#include "winpos.h" -#include "drive.h" -#include "shell.h" -#include "keyboard.h" -#include "mouse.h" -#include "debug.h" -#include "dde_proc.h" -#include "winsock.h" -#include "mouse.h" -#include "x11drv.h" -#define NB_BUTTONS 3 /* Windows can handle 3 buttons */ - -#define DndNotDnd -1 /* OffiX drag&drop */ -#define DndUnknown 0 -#define DndRawData 1 -#define DndFile 2 -#define DndFiles 3 -#define DndText 4 -#define DndDir 5 -#define DndLink 6 -#define DndExe 7 - -#define DndEND 8 - -#define DndURL 128 /* KDE drag&drop */ - - - /* X context to associate a hwnd to an X window */ -static XContext winContext = 0; - -static Atom wmProtocols = None; -static Atom wmDeleteWindow = None; -static Atom dndProtocol = None; -static Atom dndSelection = None; - -/* EVENT_WaitNetEvent() master fd sets */ - -static fd_set __event_io_set[3]; -static int __event_max_fd = 0; -static int __event_x_connection = 0; - -static const char * const event_names[] = -{ - "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", - "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", - "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", - "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", - "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", - "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", - "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", - "ClientMessage", "MappingNotify" -}; - - /* Event handlers */ -static void EVENT_Key( WND *pWnd, XKeyEvent *event ); -static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event ); -static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event ); -static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event ); -static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event ); -static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event ); -static int EVENT_Expose( WND *pWnd, XExposeEvent *event ); -static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event ); -static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event ); -static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event); -static void EVENT_SelectionNotify( XSelectionEvent *event); -static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event); -static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event ); -static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event ); - -/* Usable only with OLVWM - compile option perhaps? -static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event ); -*/ - -static void EVENT_GetGeometry( Window win, int *px, int *py, - unsigned int *pwidth, unsigned int *pheight ); +extern EVENT_DRIVER X11DRV_EVENT_Driver; /*********************************************************************** - * EVENT_Init + * EVENT_GetDriver + */ +EVENT_DRIVER *EVENT_GetDriver(void) +{ + return &X11DRV_EVENT_Driver; +} + +/*********************************************************************** + * EVENT_Init * * Initialize network IO. */ BOOL32 EVENT_Init(void) { - int i; - for( i = 0; i < 3; i++ ) - FD_ZERO( __event_io_set + i ); - - __event_max_fd = __event_x_connection = ConnectionNumber(display); - FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] ); - __event_max_fd++; - return TRUE; + return EVENT_GetDriver()->pInit(); } /*********************************************************************** - * EVENT_AddIO + * EVENT_AddIO */ -void EVENT_AddIO( int fd, unsigned io_type ) +void EVENT_AddIO(int fd, unsigned io_type) { - FD_SET( fd, &__event_io_set[io_type] ); - if( __event_max_fd <= fd ) __event_max_fd = fd + 1; -} - -void EVENT_DeleteIO( int fd, unsigned io_type ) -{ - FD_CLR( fd, &__event_io_set[io_type] ); + EVENT_GetDriver()->pAddIO(fd, io_type); } /*********************************************************************** - * EVENT_ProcessEvent - * - * Process an X event. + * EVENT_DeleteIO */ -void EVENT_ProcessEvent( XEvent *event ) +void EVENT_DeleteIO(int fd, unsigned io_type) { - WND *pWnd; - - if ( TSXFindContext( display, event->xany.window, winContext, - (char **)&pWnd ) != 0) { - if ( event->type == ClientMessage) { - /* query window (drag&drop event contains only drag window) */ - Window root, child; - int root_x, root_y, child_x, child_y; - unsigned u; - TSXQueryPointer( display, rootWindow, &root, &child, - &root_x, &root_y, &child_x, &child_y, &u); - if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0) - return; - } else { - pWnd = NULL; /* Not for a registered window */ - } - } - - TRACE(event, "Got event %s for hwnd %04x\n", - event_names[event->type], pWnd? pWnd->hwndSelf : 0 ); - - switch(event->type) - { - case KeyPress: - case KeyRelease: - EVENT_Key( pWnd, (XKeyEvent*)event ); - break; - - case ButtonPress: - EVENT_ButtonPress( pWnd, (XButtonEvent*)event ); - break; - - case ButtonRelease: - EVENT_ButtonRelease( pWnd, (XButtonEvent*)event ); - break; - - case MotionNotify: - /* Wine between two fast machines across the overloaded campus - ethernet gets very boged down in MotionEvents. The following - simply finds the last motion event in the queue and drops - the rest. On a good link events are servered before they build - up so this doesn't take place. On a slow link this may cause - problems if the event order is important. I'm not yet seen - of any problems. Jon 7/6/96. - */ - while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window, - MotionNotify, event)); - EVENT_MotionNotify( pWnd, (XMotionEvent*)event ); - break; - - case FocusIn: - if (!pWnd) return; - EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event ); - break; - - case FocusOut: - if (!pWnd) return; - EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event ); - break; - - case Expose: - if (!pWnd) return; - if (EVENT_Expose( pWnd, (XExposeEvent *)event )) { - /* need to process ConfigureNotify first */ - XEvent new_event; - - /* attempt to find and process the ConfigureNotify event now */ - if (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window, - ConfigureNotify, &new_event)) { - EVENT_ProcessEvent( &new_event ); - if (!EVENT_Expose( pWnd, (XExposeEvent *)event )) - break; - } - - /* no luck at this time, defer Expose event for later */ - /* use "type" for an event counter, it is never rechecked */ - if (!pWnd->expose_event) { - pWnd->expose_event = malloc( sizeof(XExposeEvent) ); - pWnd->expose_event[0] = *(XExposeEvent *)event; - pWnd->expose_event[0].type = 1; - } else { - int i; - - i = ++pWnd->expose_event[0].type; - pWnd->expose_event = realloc( pWnd->expose_event, - i * sizeof(XExposeEvent) ); - pWnd->expose_event[i-1] = *(XExposeEvent *)event; - FIXME(x11, "Try and combine Expose events? %d queued.\n", i); - } - } - break; - - case GraphicsExpose: - if (!pWnd) return; - EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event ); - break; - - case ConfigureNotify: - if (!pWnd) return; - EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event ); - if (pWnd->expose_event) { - /* process deferred Expose event(s) */ - int i; - - for (i=0; iexpose_event[0].type; i++) { - if(EVENT_Expose( pWnd, &pWnd->expose_event[i] )) - ERR(x11, "Unprocessed expose event discarded\n"); - } - free( pWnd->expose_event ); - pWnd->expose_event = NULL; - } - break; - - case SelectionRequest: - if (!pWnd) return; - EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event ); - break; - - case SelectionNotify: - if (!pWnd) return; - EVENT_SelectionNotify( (XSelectionEvent *)event ); - break; - - case SelectionClear: - if (!pWnd) return; - EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event ); - break; - - case ClientMessage: - if (!pWnd) return; - EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event ); - break; - -/* case EnterNotify: - * EVENT_EnterNotify( pWnd, (XCrossingEvent *) event ); - * break; - */ - case NoExpose: - break; - - /* We get all these because of StructureNotifyMask. */ - case UnmapNotify: - case CirculateNotify: - case CreateNotify: - case DestroyNotify: - case GravityNotify: - case ReparentNotify: - break; - - case MapNotify: - if (!pWnd) return; - EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event ); - break; - - default: - WARN(event, "Unprocessed event %s for hwnd %04x\n", - event_names[event->type], pWnd? pWnd->hwndSelf : 0 ); - break; - } -} - - -/*********************************************************************** - * EVENT_RegisterWindow - * - * Associate an X window to a HWND. - */ -void EVENT_RegisterWindow( WND *pWnd ) -{ - if (wmProtocols == None) - wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True ); - if (wmDeleteWindow == None) - wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True ); - if( dndProtocol == None ) - dndProtocol = TSXInternAtom( display, "DndProtocol" , False ); - if( dndSelection == None ) - dndSelection = TSXInternAtom( display, "DndSelection" , False ); - - TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 ); - - if (!winContext) winContext = TSXUniqueContext(); - TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd ); + EVENT_GetDriver()->pDeleteIO(fd, io_type); } /*********************************************************************** - * EVENT_DestroyWindow - */ -void EVENT_DestroyWindow( WND *pWnd ) -{ - XEvent xe; - - if (pWnd->expose_event) { - free( pWnd->expose_event ); - pWnd->expose_event = NULL; - } - TSXDeleteContext( display, pWnd->window, winContext ); - TSXDestroyWindow( display, pWnd->window ); - while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) ); -} - - -/*********************************************************************** - * IsUserIdle (USER.333) - * - * Check if we have pending X events. - */ -BOOL16 WINAPI IsUserIdle(void) -{ - struct timeval timeout = {0, 0}; - fd_set check_set; - - FD_ZERO(&check_set); - FD_SET(__event_x_connection, &check_set); - if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 ) - return TRUE; - return FALSE; -} - - -/*********************************************************************** - * EVENT_WaitNetEvent + * EVENT_WaitNetEvent * * Wait for a network event, optionally sleeping until one arrives. * Return TRUE if an event is pending, FALSE on timeout or error * (for instance lost connection with the server). */ -BOOL32 EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ) +BOOL32 EVENT_WaitNetEvent(BOOL32 sleep, BOOL32 peek) { - XEvent event; - LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0; - int pending = TSXPending(display); - - /* Wait for an event or a timeout. If maxWait is -1, we have no timeout; - * in this case, we fall through directly to the XNextEvent loop. - */ - - if ((maxWait != -1) && !pending) - { - int num_pending; - struct timeval timeout; - fd_set io_set[3]; - - memcpy( io_set, __event_io_set, sizeof(io_set) ); - - timeout.tv_usec = (maxWait % 1000) * 1000; - timeout.tv_sec = maxWait / 1000; - -#ifdef CONFIG_IPC - sigsetjmp(env_wait_x, 1); - stop_wait_op= CONT; - - if (DDE_GetRemoteMessage()) { - while(DDE_GetRemoteMessage()) - ; - return TRUE; - } - stop_wait_op = STOP_WAIT_X; - /* The code up to the next "stop_wait_op = CONT" must be reentrant */ - num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], - &io_set[EVENT_IO_WRITE], - &io_set[EVENT_IO_EXCEPT], &timeout ); - if ( num_pending == 0 ) - { - stop_wait_op = CONT; - TIMER_ExpireTimers(); - return FALSE; - } - else stop_wait_op = CONT; -#else /* CONFIG_IPC */ - num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], - &io_set[EVENT_IO_WRITE], - &io_set[EVENT_IO_EXCEPT], &timeout ); - if ( num_pending == 0) - { - /* Timeout or error */ - TIMER_ExpireTimers(); - return FALSE; - } -#endif /* CONFIG_IPC */ - - /* Winsock asynchronous services */ - - if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) - { - num_pending--; - if( num_pending ) - WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set ); - } - else /* no X events */ - return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set ); - } - else if(!pending) - { /* Wait for X11 input. */ - fd_set set; - - FD_ZERO(&set); - FD_SET(__event_x_connection, &set); - select(__event_x_connection + 1, &set, 0, 0, 0 ); - } - - /* Process current X event (and possibly others that occurred in the meantime) */ - - EnterCriticalSection(&X11DRV_CritSection); - while (XPending( display )) - { - -#ifdef CONFIG_IPC - if (DDE_GetRemoteMessage()) - { - LeaveCriticalSection(&X11DRV_CritSection); - while(DDE_GetRemoteMessage()) ; - return TRUE; - } -#endif /* CONFIG_IPC */ - - XNextEvent( display, &event ); - - LeaveCriticalSection(&X11DRV_CritSection); - if( peek ) - { - WND* pWnd; - MESSAGEQUEUE* pQ; - - - /* Check only for those events which can be processed - * internally. */ - - if( event.type == MotionNotify || - event.type == ButtonPress || event.type == ButtonRelease || - event.type == KeyPress || event.type == KeyRelease || - event.type == SelectionRequest || event.type == SelectionClear || - event.type == ClientMessage ) - { - EVENT_ProcessEvent( &event ); - continue; - } - - if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext, - (char **)&pWnd ) || (event.type == NoExpose)) - pWnd = NULL; - - if( pWnd ) - { - if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) ) - { - pQ->flags |= QUEUE_FLAG_XEVENT; - PostEvent(pQ->hTask); - TSXPutBackEvent(display, &event); - break; - } - } - } - else EVENT_ProcessEvent( &event ); - EnterCriticalSection(&X11DRV_CritSection); - } - LeaveCriticalSection(&X11DRV_CritSection); - return TRUE; + return EVENT_GetDriver()->pWaitNetEvent(sleep, peek); } - /*********************************************************************** - * EVENT_Synchronize + * EVENT_Synchronize * * Synchronize with the X server. Should not be used too often. */ -void EVENT_Synchronize() +void EVENT_Synchronize(void) { - XEvent event; - - /* Use of the X critical section is needed or we have a small - * race between XPending() and XNextEvent(). - */ - EnterCriticalSection( &X11DRV_CritSection ); - XSync( display, False ); - while (XPending( display )) - { - XNextEvent( display, &event ); - /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */ - LeaveCriticalSection( &X11DRV_CritSection ); - EVENT_ProcessEvent( &event ); - EnterCriticalSection( &X11DRV_CritSection ); - } - LeaveCriticalSection( &X11DRV_CritSection ); + EVENT_GetDriver()->pSynchronize(); } -/*********************************************************************** - * EVENT_QueryZOrder - * - * Try to synchronize internal z-order with the window manager's. - * Probably a futile endeavor. +/********************************************************************** + * EVENT_CheckFocus */ -static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB ) +BOOL32 EVENT_CheckFocus(void) { - /* return TRUE if we have at least two managed windows */ - - for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next ) - if( (*pWndA)->flags & WIN_MANAGED && - (*pWndA)->dwStyle & WS_VISIBLE ) break; - if( *pWndA ) - for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next ) - if( (*pWndB)->flags & WIN_MANAGED && - (*pWndB)->dwStyle & WS_VISIBLE ) break; - return ((*pWndB) != NULL); + return EVENT_GetDriver()->pCheckFocus(); } -static Window __get_common_ancestor( Window A, Window B, - Window** children, unsigned* total ) -{ - /* find the real root window */ - - Window root, *childrenB; - unsigned totalB; - - do - { - if( *children ) TSXFree( *children ); - TSXQueryTree( display, A, &root, &A, children, total ); - TSXQueryTree( display, B, &root, &B, &childrenB, &totalB ); - if( childrenB ) TSXFree( childrenB ); - } while( A != B && A && B ); - return ( A && B ) ? A : 0 ; -} - -static Window __get_top_decoration( Window w, Window ancestor ) -{ - Window* children, root, prev = w, parent = w; - unsigned total; - - do - { - w = parent; - TSXQueryTree( display, w, &root, &parent, &children, &total ); - if( children ) TSXFree( children ); - } while( parent && parent != ancestor ); - TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w ); - return ( parent ) ? w : 0 ; -} - -static unsigned __td_lookup( Window w, Window* list, unsigned max ) -{ - unsigned i; - for( i = 0; i < max; i++ ) if( list[i] == w ) break; - return i; -} - -static BOOL32 EVENT_QueryZOrder( WND* pWndCheck ) -{ - BOOL32 bRet = FALSE; - HWND32 hwndInsertAfter = HWND_TOP; - WND* pWnd, *pWndZ = WIN_GetDesktop()->child; - Window w, parent, *children = NULL; - unsigned total, check, pos, best; - - if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE; - - parent = __get_common_ancestor( pWndZ->window, pWnd->window, - &children, &total ); - if( parent && children ) - { - w = __get_top_decoration( pWndCheck->window, parent ); - if( w != children[total - 1] ) - { - check = __td_lookup( w, children, total ); - best = total; - for( pWnd = pWndZ; pWnd; pWnd = pWnd->next ) - { - if( pWnd != pWndCheck ) - { - if( !(pWnd->flags & WIN_MANAGED) || - !(w = __get_top_decoration( pWnd->window, parent )) ) - continue; - pos = __td_lookup( w, children, total ); - if( pos < best && pos > check ) - { - best = pos; - hwndInsertAfter = pWnd->hwndSelf; - } - if( check - best == 1 ) break; - } - } - WIN_UnlinkWindow( pWndCheck->hwndSelf ); - WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter); - } - } - if( children ) TSXFree( children ); - return bRet; -} - - /*********************************************************************** - * EVENT_XStateToKeyState - * - * Translate a X event state (Button1Mask, ShiftMask, etc...) to - * a Windows key state (MK_SHIFT, MK_CONTROL, etc...) + * EVENT_QueryPointer */ -static WORD EVENT_XStateToKeyState( int state ) +BOOL32 EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *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; -} - -/*********************************************************************** - * EVENT_QueryPointer - */ -BOOL32 EVENT_QueryPointer( DWORD *posX, DWORD *posY, DWORD *state ) -{ - Window root, child; - int rootX, rootY, winX, winY; - unsigned int xstate; - - if (!TSXQueryPointer( display, rootWindow, &root, &child, - &rootX, &rootY, &winX, &winY, &xstate )) - return FALSE; - - *posX = (DWORD)winX; - *posY = (DWORD)winY; - *state = EVENT_XStateToKeyState( xstate ); - - return TRUE; -} - -/*********************************************************************** - * EVENT_Expose - */ -static int EVENT_Expose( WND *pWnd, XExposeEvent *event ) -{ - RECT32 rect; - int x, y; - unsigned int width, height; - - /* When scrolling, many (fvwm2-based) window managers send the Expose - * event before sending the ConfigureNotify event, and we don't like - * that, so before processing the Expose event, we check whether the - * geometry has changed, and if so, we defer the Expose event until - * we get the ConfigureNotify event. -Ove Kåven */ - EVENT_GetGeometry( event->window, &x, &y, &width, &height ); - - if ( x != pWnd->rectWindow.left || y != pWnd->rectWindow.top || - (width != pWnd->rectWindow.right - pWnd->rectWindow.left) || - (height != pWnd->rectWindow.bottom - pWnd->rectWindow.top)) - return 1; /* tell EVENT_ProcessEvent() to defer it */ - - /* Make position relative to client area instead of window */ - rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left); - rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top); - rect.right = rect.left + event->width; - rect.bottom = rect.top + event->height; - - PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0, - RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE | - (event->count ? 0 : RDW_ERASENOW), 0 ); - return 0; + return EVENT_GetDriver()->pQueryPointer(posX, posY, state); } /*********************************************************************** - * EVENT_GraphicsExpose - * - * This is needed when scrolling area is partially obscured - * by non-Wine X window. - */ -static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event ) -{ - RECT32 rect; - - /* Make position relative to client area instead of window */ - rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left); - rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top); - rect.right = rect.left + event->width; - rect.bottom = rect.top + event->height; - - PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0, - RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | - (event->count ? 0 : RDW_ERASENOW), 0 ); -} - - -/*********************************************************************** - * EVENT_Key - * - * Handle a X key event - */ -static void EVENT_Key( WND *pWnd, XKeyEvent *event ) -{ - KEYBOARD_HandleEvent( pWnd, event ); -} - - -/*********************************************************************** - * EVENT_MotionNotify - */ -static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event ) -{ - int xOffset = pWnd? pWnd->rectWindow.left : 0; - int yOffset = pWnd? pWnd->rectWindow.top : 0; - - MOUSE_SendEvent( MOUSEEVENTF_MOVE, - xOffset + event->x, yOffset + event->y, - EVENT_XStateToKeyState( event->state ), - event->time - MSG_WineStartTicks, - pWnd? pWnd->hwndSelf : 0 ); -} - - -/*********************************************************************** - * EVENT_DummyMotionNotify + * EVENT_DummyMotionNotify * * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message. */ void EVENT_DummyMotionNotify(void) { - DWORD winX, winY, state; - - if ( EVENT_QueryPointer( &winX, &winY, &state ) ) - { - MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state, - GetTickCount(), 0 ); - } + EVENT_GetDriver()->pDummyMotionNotify(); } +/********************************************************************** + * X11DRV_EVENT_Pending + */ +BOOL32 EVENT_Pending() +{ + return EVENT_GetDriver()->pPending(); +} /*********************************************************************** - * EVENT_ButtonPress - */ -static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event ) -{ - static WORD statusCodes[NB_BUTTONS] = - { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN }; - int buttonNum = event->button - 1; - - int xOffset = pWnd? pWnd->rectWindow.left : 0; - int yOffset = pWnd? pWnd->rectWindow.top : 0; - - if (buttonNum >= NB_BUTTONS) return; - - MOUSE_SendEvent( statusCodes[buttonNum], - xOffset + event->x, yOffset + event->y, - EVENT_XStateToKeyState( event->state ), - event->time - MSG_WineStartTicks, - pWnd? pWnd->hwndSelf : 0 ); -} - - -/*********************************************************************** - * EVENT_ButtonRelease - */ -static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event ) -{ - static WORD statusCodes[NB_BUTTONS] = - { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP }; - int buttonNum = event->button - 1; - - int xOffset = pWnd? pWnd->rectWindow.left : 0; - int yOffset = pWnd? pWnd->rectWindow.top : 0; - - if (buttonNum >= NB_BUTTONS) return; - - MOUSE_SendEvent( statusCodes[buttonNum], - xOffset + event->x, yOffset + event->y, - EVENT_XStateToKeyState( event->state ), - event->time - MSG_WineStartTicks, - pWnd? pWnd->hwndSelf : 0 ); -} - - -/********************************************************************** - * EVENT_FocusIn - */ -static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event ) -{ - if (Options.managed) EVENT_QueryZOrder( pWnd ); - - if (event->detail != NotifyPointer) - { - HWND32 hwnd = pWnd->hwndSelf; - - if (hwnd != GetActiveWindow32()) - { - WINPOS_ChangeActiveWindow( hwnd, FALSE ); - KEYBOARD_UpdateState(); - } - if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32())) - SetFocus32( hwnd ); - } -} - - -/********************************************************************** - * EVENT_FocusOut + * IsUserIdle (USER.333) * - * Note: only top-level override-redirect windows get FocusOut events. + * Check if we have pending X events. */ -static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event ) +BOOL16 WINAPI IsUserIdle(void) { - if (event->detail != NotifyPointer) - { - HWND32 hwnd = pWnd->hwndSelf; - - if (hwnd == GetActiveWindow32()) - WINPOS_ChangeActiveWindow( 0, FALSE ); - if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32())) - SetFocus32( 0 ); - } + return EVENT_GetDriver()->pIsUserIdle(); } - -/********************************************************************** - * EVENT_CheckFocus - */ -BOOL32 EVENT_CheckFocus(void) -{ - WND* pWnd; - Window xW; - int state; - - TSXGetInputFocus(display, &xW, &state); - if( xW == None || - TSXFindContext(display, xW, winContext, (char **)&pWnd) ) - return FALSE; - return TRUE; -} - - -/********************************************************************** - * EVENT_GetGeometry - * - * Helper function for ConfigureNotify handling. - * Get the new geometry of a window relative to the root window. - */ -static void EVENT_GetGeometry( Window win, int *px, int *py, - unsigned int *pwidth, unsigned int *pheight ) -{ - Window root, parent, *children; - int xpos, ypos; - unsigned int width, height, border, depth, nb_children; - - if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight, - &border, &depth )) return; - if (win == rootWindow) - { - *px = *py = 0; - return; - } - - for (;;) - { - if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children)) - return; - TSXFree( children ); - if (parent == rootWindow) break; - win = parent; - if (!TSXGetGeometry( display, win, &root, &xpos, &ypos, - &width, &height, &border, &depth )) return; - *px += xpos; - *py += ypos; - } -} - - -/********************************************************************** - * EVENT_ConfigureNotify - * - * The ConfigureNotify event is only selected on top-level windows - * when the -managed flag is used. - */ -static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event ) -{ - WINDOWPOS32 winpos; - RECT32 newWindowRect, newClientRect; - HRGN32 hrgnOldPos, hrgnNewPos; - Window above = event->above; - int x, y; - unsigned int width, height; - - assert (pWnd->flags & WIN_MANAGED); - - /* We don't rely on the event geometry info, because it is relative - * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0 - * if the window hasn't moved). - */ - EVENT_GetGeometry( event->window, &x, &y, &width, &height ); - - /* Fill WINDOWPOS struct */ - winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER; - winpos.hwnd = pWnd->hwndSelf; - winpos.x = x; - winpos.y = y; - winpos.cx = width; - winpos.cy = height; - - /* Check for unchanged attributes */ - if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top) - winpos.flags |= SWP_NOMOVE; - if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) && - (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top)) - winpos.flags |= SWP_NOSIZE; - else - { - RECT32 rect = { 0, 0, pWnd->rectWindow.right - pWnd->rectWindow.left, - pWnd->rectWindow.bottom - pWnd->rectWindow.top }; - DCE_InvalidateDCE( pWnd, &rect ); - } - - /* Send WM_WINDOWPOSCHANGING */ - SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos ); - - /* Calculate new position and size */ - newWindowRect.left = x; - newWindowRect.right = x + width; - newWindowRect.top = y; - newWindowRect.bottom = y + height; - - WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect, - &pWnd->rectWindow, &pWnd->rectClient, - &winpos, &newClientRect ); - - hrgnOldPos = CreateRectRgnIndirect32( &pWnd->rectWindow ); - hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect ); - CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF ); - DeleteObject32(hrgnOldPos); - DeleteObject32(hrgnNewPos); - - /* Set new size and position */ - pWnd->rectWindow = newWindowRect; - pWnd->rectClient = newClientRect; - SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos ); - - if (!IsWindow32( winpos.hwnd )) return; - if( above == None ) /* absolute bottom */ - { - WIN_UnlinkWindow( winpos.hwnd ); - WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM); - } - else EVENT_QueryZOrder( pWnd ); /* try to outsmart window manager */ -} - - -/*********************************************************************** - * EVENT_SelectionRequest - */ -static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event ) -{ - XSelectionEvent result; - Atom rprop = None; - Window request = event->requestor; - - if(event->target == XA_STRING) - { - HANDLE16 hText; - LPSTR text; - int size,i,j; - - rprop = event->property; - - if(rprop == None) rprop = event->target; - - if(event->selection!=XA_PRIMARY) rprop = None; - else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None; - else - { - /* open to make sure that clipboard is available */ - - BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf ); - char* lpstr = 0; - - hText = GetClipboardData16(CF_TEXT); - text = GlobalLock16(hText); - size = GlobalSize16(hText); - - /* remove carriage returns */ - - lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- ); - for(i=0,j=0; i < size && text[i]; i++ ) - { - if( text[i] == '\r' && - (text[i+1] == '\n' || text[i+1] == '\0') ) continue; - lpstr[j++] = text[i]; - } - lpstr[j]='\0'; - - TSXChangeProperty(display, request, rprop, - XA_STRING, 8, PropModeReplace, - lpstr, j); - HeapFree( GetProcessHeap(), 0, lpstr ); - - /* close only if we opened before */ - - if(couldOpen) CloseClipboard32(); - } - } - - if(rprop == None) - TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target)); - - result.type = SelectionNotify; - result.display = display; - result.requestor = request; - result.selection = event->selection; - result.property = rprop; - result.target = event->target; - result.time = event->time; - TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result); -} - - -/*********************************************************************** - * EVENT_SelectionNotify - */ -static void EVENT_SelectionNotify( XSelectionEvent *event ) -{ - if (event->selection != XA_PRIMARY) return; - - if (event->target != XA_STRING) CLIPBOARD_ReadSelection( 0, None ); - else CLIPBOARD_ReadSelection( event->requestor, event->property ); - - TRACE(clipboard,"\tSelectionNotify done!\n"); -} - - -/*********************************************************************** - * EVENT_SelectionClear - */ -static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event ) -{ - if (event->selection != XA_PRIMARY) return; - CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); -} - - -/********************************************************************** - * EVENT_DropFromOffix - * - * don't know if it still works (last Changlog is from 96/11/04) - */ -static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event ) -{ - unsigned long data_length; - unsigned long aux_long; - unsigned char* p_data = NULL; - union { - Atom atom_aux; - POINT32 pt_aux; - int i; - } u; - int x, y; - BOOL16 bAccept; - HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO)); - LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo); - SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo); - Window w_aux_root, w_aux_child; - WND* pDropWnd; - - if( !lpDragInfo || !spDragInfo ) return; - - TSXQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child, - &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long); - - lpDragInfo->hScope = pWnd->hwndSelf; - lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y; - - /* find out drop point and drop window */ - if( x < 0 || y < 0 || - x > (pWnd->rectWindow.right - pWnd->rectWindow.left) || - y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) ) - { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; } - else - { - bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE ); - x = lpDragInfo->pt.x; y = lpDragInfo->pt.y; - } - pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope ); - GlobalFree16( hDragInfo ); - - if( bAccept ) - { - TSXGetWindowProperty( display, DefaultRootWindow(display), - dndSelection, 0, 65535, FALSE, - AnyPropertyType, &u.atom_aux, &u.pt_aux.y, - &data_length, &aux_long, &p_data); - - if( !aux_long && p_data) /* don't bother if > 64K */ - { - char *p = (char*) p_data; - char *p_drop; - - aux_long = 0; - while( *p ) /* calculate buffer size */ - { - p_drop = p; - if((u.i = *p) != -1 ) - u.i = DRIVE_FindDriveRoot( (const char **)&p_drop ); - if( u.i == -1 ) *p = -1; /* mark as "bad" */ - else - { - INT32 len = GetShortPathName32A( p, NULL, 0 ); - if (len) aux_long += len + 1; - else *p = -1; - } - p += strlen(p) + 1; - } - if( aux_long && aux_long < 65535 ) - { - HDROP16 hDrop; - LPDROPFILESTRUCT16 lpDrop; - - aux_long += sizeof(DROPFILESTRUCT16) + 1; - hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long ); - lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop ); - - if( lpDrop ) - { - lpDrop->wSize = sizeof(DROPFILESTRUCT16); - lpDrop->ptMousePos.x = (INT16)x; - lpDrop->ptMousePos.y = (INT16)y; - lpDrop->fInNonClientArea = (BOOL16) - ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || - y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || - x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || - y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); - p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16); - p = p_data; - while(*p) - { - if( *p != -1 ) /* use only "good" entries */ - { - GetShortPathName32A( p, p_drop, 65535 ); - p_drop += strlen( p_drop ) + 1; - } - p += strlen(p) + 1; - } - *p_drop = '\0'; - PostMessage16( pWnd->hwndSelf, WM_DROPFILES, - (WPARAM16)hDrop, 0L ); - } - } - } - if( p_data ) TSXFree(p_data); - - } /* WS_EX_ACCEPTFILES */ -} - -/********************************************************************** - * EVENT_DropURLs - * - * drop items are separated by \n - * each item is prefixed by its mime type - * - * event->data.l[3], event->data.l[4] contains drop x,y position - */ -static void EVENT_DropURLs( WND *pWnd, XClientMessageEvent *event ) -{ - WND *pDropWnd; - unsigned long data_length; - unsigned long aux_long, drop_len = 0; - unsigned char *p_data = NULL; /* property data */ - char *p_drop = NULL; - char *p, *next; - int x, y, drop32 = FALSE ; - union { - Atom atom_aux; - POINT32 pt_aux; - int i; - Window w_aux; - } u; /* unused */ - union { - HDROP16 h16; - HDROP32 h32; - } hDrop; - - drop32 = pWnd->flags & WIN_ISWIN32; - - if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES)) - return; - - TSXGetWindowProperty( display, DefaultRootWindow(display), - dndSelection, 0, 65535, FALSE, - AnyPropertyType, &u.atom_aux, &u.i, - &data_length, &aux_long, &p_data); - if (aux_long) - WARN(event,"property too large, truncated!\n"); - TRACE(event,"urls=%s\n", p_data); - - if( !aux_long && p_data) { /* don't bother if > 64K */ - /* calculate length */ - p = p_data; - next = strchr(p, '\n'); - while (p) { - if (next) *next=0; - if (strncmp(p,"file:",5) == 0 ) { - INT32 len = GetShortPathName32A( p+5, NULL, 0 ); - if (len) drop_len += len + 1; - } - if (next) { - *next = '\n'; - p = next + 1; - next = strchr(p, '\n'); - } else { - p = NULL; - } - } - - if( drop_len && drop_len < 65535 ) { - TSXQueryPointer( display, rootWindow, &u.w_aux, &u.w_aux, - &x, &y, &u.i, &u.i, &u.i); - pDropWnd = WIN_FindWndPtr( pWnd->hwndSelf ); - - if (drop32) { - LPDROPFILESTRUCT32 lpDrop; - drop_len += sizeof(DROPFILESTRUCT32) + 1; - hDrop.h32 = (HDROP32)GlobalAlloc32( GMEM_SHARE, drop_len ); - lpDrop = (LPDROPFILESTRUCT32) GlobalLock32( hDrop.h32 ); - - if( lpDrop ) { - lpDrop->lSize = sizeof(DROPFILESTRUCT32); - lpDrop->ptMousePos.x = (INT32)x; - lpDrop->ptMousePos.y = (INT32)y; - lpDrop->fInNonClientArea = (BOOL32) - ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || - y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || - x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || - y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); - lpDrop->fWideChar = FALSE; - p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT32); - } - } else { - LPDROPFILESTRUCT16 lpDrop; - drop_len += sizeof(DROPFILESTRUCT16) + 1; - hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len ); - lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 ); - - if( lpDrop ) { - lpDrop->wSize = sizeof(DROPFILESTRUCT16); - lpDrop->ptMousePos.x = (INT16)x; - lpDrop->ptMousePos.y = (INT16)y; - lpDrop->fInNonClientArea = (BOOL16) - ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || - y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || - x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || - y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); - p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16); - } - } - - /* create message content */ - if (p_drop) { - p = p_data; - next = strchr(p, '\n'); - while (p) { - if (next) *next=0; - if (strncmp(p,"file:",5) == 0 ) { - INT32 len = GetShortPathName32A( p+5, p_drop, 65535 ); - if (len) { - TRACE(event, "drop file %s as %s\n", p+5, p_drop); - p_drop += len+1; - } else { - WARN(event, "can't convert file %s to dos name \n", p+5); - } - } else { - WARN(event, "unknown mime type %s\n", p); - } - if (next) { - *next = '\n'; - p = next + 1; - next = strchr(p, '\n'); - } else { - p = NULL; - } - *p_drop = '\0'; - } - - if (drop32) { - /* can not use PostMessage32A because it is currently based on - * PostMessage16 and WPARAM32 would be truncated to WPARAM16 - */ - GlobalUnlock32(hDrop.h32); - SendMessage32A( pWnd->hwndSelf, WM_DROPFILES, - (WPARAM32)hDrop.h32, 0L ); - } else { - GlobalUnlock16(hDrop.h16); - PostMessage16( pWnd->hwndSelf, WM_DROPFILES, - (WPARAM16)hDrop.h16, 0L ); - } - } - } - if( p_data ) TSXFree(p_data); - } -} - -/********************************************************************** - * EVENT_ClientMessage - */ -static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event ) -{ - if (event->message_type != None && event->format == 32) { - if ((event->message_type == wmProtocols) && - (((Atom) event->data.l[0]) == wmDeleteWindow)) - SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 ); - else if ( event->message_type == dndProtocol && - (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) ) - EVENT_DropFromOffiX(pWnd, event); - else if ( event->message_type == dndProtocol && - event->data.l[0] == DndURL ) - EVENT_DropURLs(pWnd, event); - else { -#if 0 - /* enable this if you want to see the message */ - unsigned char* p_data = NULL; - union { - unsigned long l; - int i; - Atom atom; - } u; /* unused */ - TSXGetWindowProperty( display, DefaultRootWindow(display), - dndSelection, 0, 65535, FALSE, - AnyPropertyType, &u.atom, &u.i, - &u.l, &u.l, &p_data); - TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n", - event->message_type, event->data.l[0], event->data.l[1], - event->data.l[2], event->data.l[3], event->data.l[4], - p_data); -#endif - TRACE(event, "unrecognized ClientMessage\n" ); - } - } -} - -/********************************************************************** - * EVENT_EnterNotify - * - * Install colormap when Wine window is focused in - * self-managed mode with private colormap - */ -/* - void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event ) - { - if( !Options.managed && rootWindow == DefaultRootWindow(display) && - (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() ) - TSXInstallColormap( display, COLOR_GetColormap() ); - } - */ - -/********************************************************************** - * EVENT_MapNotify - */ -void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event ) -{ - HWND32 hwndFocus = GetFocus32(); - - if (hwndFocus && IsChild32( hWnd, hwndFocus )) - FOCUS_SetXFocus( (HWND32)hwndFocus ); - - return; -} - diff --git a/windows/focus.c b/windows/focus.c index 92c757afedb..5e64fe2c12b 100644 --- a/windows/focus.c +++ b/windows/focus.c @@ -16,47 +16,12 @@ static HWND32 hwndFocus = 0; -/***************************************************************** - * FOCUS_SetXFocus - * - * Set the X focus. - * Explicit colormap management seems to work only with OLVWM. - */ -void FOCUS_SetXFocus( HWND32 hwnd ) -{ - XWindowAttributes win_attr; - Window win; - - /* Only mess with the X focus if there's */ - /* no desktop window and no window manager. */ - if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return; - - if (!hwnd) /* If setting the focus to 0, uninstall the colormap */ - { - if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) - TSXUninstallColormap( display, COLOR_GetColormap() ); - return; - } - - /* Set X focus and install colormap */ - - if (!(win = WIN_GetXWindow( hwnd ))) return; - if (!TSXGetWindowAttributes( display, win, &win_attr ) || - (win_attr.map_state != IsViewable)) - return; /* If window is not viewable, don't change anything */ - - TSXSetInputFocus( display, win, RevertToParent, CurrentTime ); - if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) - TSXInstallColormap( display, COLOR_GetColormap() ); - - EVENT_Synchronize(); -} - /***************************************************************** * FOCUS_SwitchFocus */ void FOCUS_SwitchFocus( HWND32 hFocusFrom, HWND32 hFocusTo ) { + WND *pFocusTo = WIN_FindWndPtr( hFocusTo ); hwndFocus = hFocusTo; #if 0 @@ -71,7 +36,8 @@ void FOCUS_SwitchFocus( HWND32 hFocusFrom, HWND32 hFocusTo ) /* According to API docs, the WM_SETFOCUS message is sent AFTER the window has received the keyboard focus. */ - FOCUS_SetXFocus( hFocusTo ); + + pFocusTo->pDriver->pSetFocus(pFocusTo); #if 0 SendMessage32A( hFocusTo, WM_SETFOCUS, hFocusFrom, 0 ); diff --git a/windows/keyboard.c b/windows/keyboard.c index a4eed119a21..85ea3b88123 100644 --- a/windows/keyboard.c +++ b/windows/keyboard.c @@ -12,12 +12,6 @@ #include #include #include -#include -#include "ts_xlib.h" -#include "ts_xresource.h" -#include "ts_xutil.h" -#include - #include "windows.h" #include "win.h" #include "gdi.h" @@ -30,254 +24,16 @@ #include "winerror.h" static LPKEYBD_EVENT_PROC DefKeybEventProc = NULL; -static LPBYTE pKeyStateTable = NULL; +LPBYTE pKeyStateTable = NULL; -int min_keycode, max_keycode, keysyms_per_keycode; -WORD keyc2vkey[256]; +extern KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver; -static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */ -static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */ - -/* Keyboard translation tables */ -static const int special_key[] = -{ - 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 int cursor_key[] = -{ - VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, - VK_NEXT, VK_END /* FF50 */ -}; - -static const int misc_key[] = -{ - VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */ - VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */ -}; - -static const int keypad_key[] = -{ - 0, VK_NUMLOCK, /* FF7E */ - 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 int function_key[] = -{ - VK_F1, VK_F2, /* FFBE */ - 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 int modifier_key[] = -{ - VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */ - VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */ -}; - -/* Returns the Windows virtual key code associated with the X event */ -static WORD EVENT_event_to_vkey( XKeyEvent *e) -{ - KeySym keysym; - - TSXLookupString(e, NULL, 0, &keysym, NULL); - - if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask)) - /* Only the Keypad keys 0-9 and . send different keysyms - * depending on the NumLock state */ - return keypad_key[(keysym & 0xFF) - 0x7E]; - - return keyc2vkey[e->keycode]; -} - -/********************************************************************** - * KEYBOARD_Init +/*********************************************************************** + * KEYBOARD_GetDriver */ -static void KEYBOARD_Init(void) +KEYBOARD_DRIVER *KEYBOARD_GetDriver() { - int i; - KeySym *ksp; - XModifierKeymap *mmp; - KeySym keysym; - KeyCode *kcp; - XKeyEvent e2; - WORD vkey, OEMvkey; - int keyc; - - TSXDisplayKeycodes(display, &min_keycode, &max_keycode); - ksp = TSXGetKeyboardMapping(display, min_keycode, - max_keycode + 1 - min_keycode, &keysyms_per_keycode); - /* We are only interested in keysyms_per_keycode. - There is no need to hold a local copy of the keysyms table */ - TSXFree(ksp); - mmp = TSXGetModifierMapping(display); - kcp = mmp->modifiermap; - for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */ - { - int j; - - for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1) - if (*kcp) - { - int k; - - for (k = 0; k < keysyms_per_keycode; k += 1) - if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch) - { - AltGrMask = 1 << i; - TRACE(key, "AltGrMask is %x\n", AltGrMask); - } - else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock) - { - NumLockMask = 1 << i; - TRACE(key, "NumLockMask is %x\n", NumLockMask); - } - } - } - TSXFreeModifiermap(mmp); - - /* Now build two conversion arrays : - * keycode -> vkey + extended - * vkey + extended -> keycode */ - - e2.display = display; - e2.state = 0; - - OEMvkey = VK_OEM_7; /* next is available. */ - for (keyc = min_keycode; keyc <= max_keycode; keyc++) - { - e2.keycode = (KeyCode)keyc; - TSXLookupString(&e2, NULL, 0, &keysym, NULL); - vkey = 0; - if (keysym) /* otherwise, keycode not used */ - { - if ((keysym >> 8) == 0xFF) /* non-character key */ - { - int key = keysym & 0xff; - - if (key >= 0x08 && key <= 0x1B) /* special key */ - vkey = special_key[key - 0x08]; - else if (key >= 0x50 && key <= 0x57) /* cursor key */ - vkey = cursor_key[key - 0x50]; - else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */ - vkey = misc_key[key - 0x60]; - else if (key >= 0x7E && key <= 0xB9) /* keypad key */ - vkey = keypad_key[key - 0x7E]; - else if (key >= 0xBE && key <= 0xCD) /* function key */ - { - vkey = function_key[key - 0xBE]; - vkey |= 0x100; /* set extended bit */ - } - else if (key >= 0xE1 && key <= 0xEA) /* modifier key */ - vkey = modifier_key[key - 0xE1]; - else if (key == 0xFF) /* DEL key */ - vkey = VK_DELETE; - /* extended must also be set for ALT_R, CTRL_R, - INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys, - keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */ - /* FIXME should we set extended bit for NumLock ? My - * Windows does ... DF */ - switch (keysym) - { - case XK_Control_R : - case XK_Alt_R : - case XK_Insert : - case XK_Delete : - case XK_Home : - case XK_End : - case XK_Prior : - case XK_Next : - case XK_Left : - case XK_Up : - case XK_Right : - case XK_Down : - case XK_KP_Divide : - case XK_KP_Enter : - vkey |= 0x100; - } - } - for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++) - { - keysym = TSXLookupKeysym(&e2, i); - if ((keysym >= VK_0 && keysym <= VK_9) - || (keysym >= VK_A && keysym <= VK_Z) - || keysym == VK_SPACE) - vkey = keysym; - } - - for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++) - { - keysym = TSXLookupKeysym(&e2, i); - switch (keysym) - { - case ';': vkey = VK_OEM_1; break; - case '/': vkey = VK_OEM_2; break; - case '`': vkey = VK_OEM_3; break; - case '[': vkey = VK_OEM_4; break; - case '\\': vkey = VK_OEM_5; break; - case ']': vkey = VK_OEM_6; break; - case '\'': vkey = VK_OEM_7; break; - case ',': vkey = VK_OEM_COMMA; break; - case '.': vkey = VK_OEM_PERIOD; break; - case '-': vkey = VK_OEM_MINUS; break; - case '+': vkey = VK_OEM_PLUS; break; - } - } - - if (!vkey) - { - /* Others keys: let's assign OEM virtual key codes in the allowed range, - * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */ - switch (++OEMvkey) - { - case 0xc1 : OEMvkey=0xdb; break; - case 0xe5 : OEMvkey=0xe9; break; - case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n"); - } - - vkey = OEMvkey; - - if (TRACE_ON(keyboard)) - { - dbg_decl_str(keyboard, 1024); - - TRACE(keyboard, "OEM specific virtual key %X assigned " - "to keycode %X:\n", OEMvkey, e2.keycode); - for (i = 0; i < keysyms_per_keycode; i += 1) - { - char *ksname; - - keysym = TSXLookupKeysym(&e2, i); - ksname = TSXKeysymToString(keysym); - if (!ksname) - ksname = "NoSymbol"; - dsprintf(keyboard, "%lX (%s) ", keysym, ksname); - } - TRACE(keyboard, "(%s)\n", dbg_str(keyboard)); - } - } - } - keyc2vkey[e2.keycode] = vkey; - } /* for */ - /* Now store one keycode for each modifier. Used to simulate keypresses. */ - kcControl = TSXKeysymToKeycode(display, XK_Control_L); - kcAlt = TSXKeysymToKeycode(display, XK_Alt_L); - if (!kcAlt) kcAlt = TSXKeysymToKeycode(display, XK_Meta_L); - kcShift = TSXKeysymToKeycode(display, XK_Shift_L); - kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock); - kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock); + return &X11DRV_KEYBOARD_Driver; } /*********************************************************************** @@ -285,13 +41,13 @@ static void KEYBOARD_Init(void) */ WORD WINAPI KEYBOARD_Inquire(LPKBINFO kbInfo) { - kbInfo->Begin_First_Range = 0; - kbInfo->End_First_Range = 0; - kbInfo->Begin_Second_Range = 0; - kbInfo->End_Second_Range = 0; - kbInfo->StateSize = 16; - - return sizeof(KBINFO); + kbInfo->Begin_First_Range = 0; + kbInfo->End_First_Range = 0; + kbInfo->Begin_Second_Range = 0; + kbInfo->End_Second_Range = 0; + kbInfo->StateSize = 16; + + return sizeof(KBINFO); } /*********************************************************************** @@ -300,16 +56,16 @@ WORD WINAPI KEYBOARD_Inquire(LPKBINFO kbInfo) VOID WINAPI KEYBOARD_Enable( LPKEYBD_EVENT_PROC lpKeybEventProc, LPBYTE lpKeyState ) { - static BOOL32 initDone = FALSE; - - DefKeybEventProc = lpKeybEventProc; - pKeyStateTable = lpKeyState; - - /* all states to false */ - memset( lpKeyState, 0, sizeof(lpKeyState) ); - - if (!initDone) KEYBOARD_Init(); - initDone = TRUE; + static BOOL32 initDone = FALSE; + + DefKeybEventProc = lpKeybEventProc; + pKeyStateTable = lpKeyState; + + /* all states to false */ + memset( lpKeyState, 0, sizeof(lpKeyState) ); + + if (!initDone) KEYBOARD_GetDriver()->pInit(); + initDone = TRUE; } /*********************************************************************** @@ -317,8 +73,8 @@ VOID WINAPI KEYBOARD_Enable( LPKEYBD_EVENT_PROC lpKeybEventProc, */ VOID WINAPI KEYBOARD_Disable(VOID) { - DefKeybEventProc = NULL; - pKeyStateTable = NULL; + DefKeybEventProc = NULL; + pKeyStateTable = NULL; } /*********************************************************************** @@ -327,239 +83,26 @@ VOID WINAPI KEYBOARD_Disable(VOID) void KEYBOARD_SendEvent( BYTE bVk, BYTE bScan, DWORD dwFlags, DWORD posX, DWORD posY, DWORD time ) { - WINE_KEYBDEVENT wke; - - if ( !DefKeybEventProc ) return; - - TRACE( event, "(%d,%d,%04lX)\n", bVk, bScan, dwFlags ); - - wke.magic = WINE_KEYBDEVENT_MAGIC; - wke.posX = posX; - wke.posY = posY; - wke.time = time; - - DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke ); + WINE_KEYBDEVENT wke; + + if ( !DefKeybEventProc ) return; + + TRACE( event, "(%d,%d,%04lX)\n", bVk, bScan, dwFlags ); + + wke.magic = WINE_KEYBDEVENT_MAGIC; + wke.posX = posX; + wke.posY = posY; + wke.time = time; + + DefKeybEventProc( bVk, bScan, dwFlags, (DWORD)&wke ); } - -static BOOL32 NumState=FALSE, CapsState=FALSE; - -/********************************************************************** - * KEYBOARD_GenerateMsg - * - * Generate Down+Up messages when NumLock or CapsLock is pressed. - * - * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL - * - */ -void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y, - DWORD event_time ) -{ - BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState); - - if (*State) { - /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes, - don't treat it. It's from the same key press. Then the state goes to ON. - And from there, a 'release' event will switch off the toggle key. */ - *State=FALSE; - TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]); - } else - { - if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */ - { - if (Evtype!=KeyPress) - { - TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n"); - KEYBOARD_SendEvent( vkey, 0, 0, - event_x, event_y, event_time ); - KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, - event_x, event_y, event_time ); - *State=FALSE; - pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ - } - } - else /* it was OFF */ - if (Evtype==KeyPress) - { - TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n"); - KEYBOARD_SendEvent( vkey, 0, 0, - event_x, event_y, event_time ); - KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, - event_x, event_y, event_time ); - *State=TRUE; /* Goes to intermediary state before going to ON */ - pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */ - } - } -} - -/*********************************************************************** - * KEYBOARD_UpdateOneState - * - * Updates internal state for , depending on key under X - * - */ -void KEYBOARD_UpdateOneState ( int vkey, int state ) -{ - /* Do something if internal table state != X state for keycode */ - if (((pKeyStateTable[vkey] & 0x80)!=0) != state) - { - TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n", - vkey, pKeyStateTable[vkey]); - - /* Fake key being pressed inside wine */ - KEYBOARD_SendEvent( vkey, 0, state? 0 : KEYEVENTF_KEYUP, - 0, 0, GetTickCount() ); - - TRACE(keyboard,"State after %#.2x \n",pKeyStateTable[vkey]); - } -} - -/*********************************************************************** - * KEYBOARD_UpdateState - * - * Update modifiers state (Ctrl, Alt, Shift) - * when window is activated (called by EVENT_FocusIn in event.c) - * - * 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) - */ -void KEYBOARD_UpdateState ( void ) -{ -/* extract a bit from the char[32] bit suite */ -#define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0) - - char keys_return[32]; - - TRACE(keyboard,"called\n"); - if (!TSXQueryKeymap(display, keys_return)) { - ERR(keyboard,"Error getting keymap !"); - return; - } - - /* 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_HandleEvent - * - * Handle a X key event - */ -void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event ) -{ - char Str[24]; - XComposeStatus cs; - KeySym keysym; - WORD vkey = 0, bScan; - DWORD dwFlags; - static BOOL32 force_extended = FALSE; /* hack for AltGr translation */ - - int ascii_chars; - - INT32 event_x = (pWnd? pWnd->rectWindow.left : 0) + event->x; - INT32 event_y = (pWnd? pWnd->rectWindow.top : 0) + event->y; - DWORD event_time = event->time - MSG_WineStartTicks; - - /* this allows support for dead keys */ - if ((event->keycode >> 8) == 0x10) - event->keycode=(event->keycode & 0xff); - - ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs); - - TRACE(key, "EVENT_key : state = %X\n", event->state); - if (keysym == XK_Mode_switch) - { - TRACE(key, "Alt Gr key event received\n"); - event->keycode = kcControl; /* Simulate Control */ - KEYBOARD_HandleEvent( pWnd, event ); - - event->keycode = kcAlt; /* Simulate Alt */ - force_extended = TRUE; - KEYBOARD_HandleEvent( pWnd, event ); - force_extended = FALSE; - return; - } - - Str[ascii_chars] = '\0'; - if (TRACE_ON(key)){ - char *ksname; - - ksname = TSXKeysymToString(keysym); - if (!ksname) - ksname = "No Name"; - TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", - (event->type == KeyPress) ? "KeyPress" : "KeyRelease", - keysym, ksname, ascii_chars, Str[0] & 0xff, Str); - } - - vkey = EVENT_event_to_vkey(event); - if (force_extended) vkey |= 0x100; - - TRACE(key, "keycode 0x%x converted to vkey 0x%x\n", - event->keycode, vkey); - - if (vkey) - { - switch (vkey & 0xff) - { - case VK_NUMLOCK: - KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y, - event_time ); - break; - case VK_CAPITAL: - TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]); - KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y, - event_time ); - TRACE(keyboard,"State after : %#.2x\n",pKeyStateTable[vkey]); - break; - default: - /* Adjust the NUMLOCK state if it has been changed outside wine */ - if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask)) - { - TRACE(keyboard,"Adjusting NumLock state. \n"); - KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y, - event_time ); - KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y, - event_time ); - } - /* Adjust the CAPSLOCK state if it has been changed outside wine */ - if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask)) - { - TRACE(keyboard,"Adjusting Caps Lock state.\n"); - KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y, - event_time ); - KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y, - event_time ); - } - /* Not Num nor Caps : end of intermediary states for both. */ - NumState = FALSE; - CapsState = FALSE; - - bScan = event->keycode - min_keycode; /* Windows starts from 0, X from - min_keycode (8 usually) */ - dwFlags = 0; - if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP; - if ( vkey & 0x100 ) dwFlags |= KEYEVENTF_EXTENDEDKEY; - if ( force_extended ) dwFlags |= KEYEVENTF_WINE_FORCEEXTENDED; - - KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags, - event_x, event_y, event_time ); - } - } -} - - /********************************************************************** * ScreenSwitchEnable (KEYBOARD.100) */ VOID WINAPI ScreenSwitchEnable(WORD unused) { - FIXME(keyboard,"(%04x): stub\n",unused); + FIXME(keyboard,"(%04x): stub\n",unused); } /********************************************************************** @@ -567,9 +110,9 @@ VOID WINAPI ScreenSwitchEnable(WORD unused) */ DWORD WINAPI OemKeyScan(WORD wOemChar) { - TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar); + TRACE(keyboard,"*OemKeyScan (%d)\n",wOemChar); - return wOemChar; + return wOemChar; } /********************************************************************** @@ -592,46 +135,7 @@ DWORD WINAPI OemKeyScan(WORD wOemChar) WORD WINAPI VkKeyScan16(CHAR cChar) { - KeyCode keycode; - KeySym keysym; - int i,index; - int highbyte=0; - - /* char->keysym (same for ANSI chars) */ - keysym=(unsigned char) cChar;/* (!) cChar is signed */ - if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/ - - keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */ - if (!keycode) - { /* It didn't work ... let's try with deadchar code. */ - keycode = TSXKeysymToKeycode(display, keysym | 0xFE00); - } - - TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n", - cChar,keysym,keysym,keycode); - - if (keycode) - { - for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */ - if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i; - switch (index) { - case -1 : - WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break; - case 0 : break; - case 1 : highbyte = 0x0100; break; - case 2 : highbyte = 0X0600; break; - default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index); - } - /* - index : 0 adds 0x0000 - index : 1 adds 0x0100 (shift) - index : ? adds 0x0200 (ctrl) - index : 2 adds 0x0600 (ctrl+alt) - index : ? adds 0x0700 (ctrl+alt+shift (used?)) - */ - } - TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte); - return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */ + return KEYBOARD_GetDriver()->pVkKeyScan(cChar); } /****************************************************************************** @@ -664,55 +168,16 @@ INT16 WINAPI GetKeyboardType16(INT16 nTypeFlag) */ UINT16 WINAPI MapVirtualKey16(UINT16 wCode, UINT16 wMapType) { -#define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; } - - TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n", - wCode,wMapType); - switch(wMapType) { - case 0: { /* vkey-code to scan-code */ - /* let's do vkey -> keycode -> scan */ - int keyc; - for (keyc=min_keycode; keyc<=max_keycode; keyc++) - if ((keyc2vkey[keyc] & 0xFF) == wCode) - returnMVK (keyc - min_keycode); - return 0; } - - case 1: /* scan-code to vkey-code */ - /* let's do scan -> keycode -> vkey */ - - returnMVK (keyc2vkey[(wCode & 0xFF) + min_keycode]); - - case 2: { /* vkey-code to unshifted ANSI code */ - /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */ - /* My Windows returns 'A'. */ - /* let's do vkey -> keycode -> (XLookupString) ansi char */ - XKeyEvent e; - KeySym keysym; - char s[2]; - e.display = display; - e.state = 0; /* unshifted */ - e.keycode = MapVirtualKey16( wCode, 0); - if (!TSXLookupString(&e, s , 2 , &keysym, NULL)) - returnMVK (*s); - - return 0; - } - default: /* reserved */ - WARN(keyboard, "Unknown wMapType %d !\n", - wMapType); - return 0; - } - return 0; + return KEYBOARD_GetDriver()->pMapVirtualKey(wCode,wMapType); } - /**************************************************************************** * GetKBCodePage16 (KEYBOARD.132) */ INT16 WINAPI GetKBCodePage16(void) { - TRACE(keyboard,"(void)\n"); - return 850; + TRACE(keyboard,"(void)\n"); + return 850; } /**************************************************************************** @@ -720,227 +185,32 @@ INT16 WINAPI GetKBCodePage16(void) */ INT16 WINAPI GetKeyNameText16(LONG lParam, LPSTR lpBuffer, INT16 nSize) { - /* int i; */ - - FIXME(keyboard,"(%ld,,%d): stub\n",lParam,nSize); - - /* - lParam >>= 16; - lParam &= 0xff; - - for (i = 0 ; i != KeyTableSize ; i++) - if (KeyTable[i].scancode == lParam) { - lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize ); - return strlen(lpBuffer); - } - */ - - *lpBuffer = 0; - return 0; + return KEYBOARD_GetDriver()->pGetKeyNameText(lParam, lpBuffer, nSize); } /**************************************************************************** * ToAscii (KEYBOARD.4) - -The ToAscii function translates the specified virtual-key code and keyboard -state to the corresponding Windows character or characters. - -If the specified key is a dead key, the return value is negative. Otherwise, -it is one of the following values: -Value Meaning -0 The specified virtual key has no translation for the current state of the keyboard. -1 One Windows character was copied to the buffer. -2 Two characters were copied to the buffer. This usually happens when a - dead-key character (accent or diacritic) stored in the keyboard layout cannot - be composed with the specified virtual key to form a single character. - -FIXME : should do the above (return 2 for non matching deadchar+char combinations) - + * + * The ToAscii function translates the specified virtual-key code and keyboard + * state to the corresponding Windows character or characters. + * + * If the specified key is a dead key, the return value is negative. Otherwise, + * it is one of the following values: + * Value Meaning + * 0 The specified virtual key has no translation for the current state of the keyboard. + * 1 One Windows character was copied to the buffer. + * 2 Two characters were copied to the buffer. This usually happens when a + * dead-key character (accent or diacritic) stored in the keyboard layout cannot + * be composed with the specified virtual key to form a single character. + * + * FIXME : should do the above (return 2 for non matching deadchar+char combinations) + * */ INT16 WINAPI ToAscii16(UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, LPVOID lpChar, UINT16 flags) { - XKeyEvent e; - KeySym keysym; - static XComposeStatus cs; - INT32 ret; - int keyc; - - if (scanCode==0) { - /* This happens when doing Alt+letter : a fake 'down arrow' key press - event is generated by windows. Just ignore it. */ - TRACE(keyboard,"scanCode=0, doing nothing\n"); - return 0; - } - e.display = display; - e.keycode = 0; - e.state = 0; - if (lpKeyState[VK_SHIFT] & 0x80) - e.state |= ShiftMask; - if (lpKeyState[VK_CAPITAL] & 0x01) - e.state |= LockMask; - if (lpKeyState[VK_CONTROL] & 0x80) - { - if (lpKeyState[VK_MENU] & 0x80) - e.state |= AltGrMask; - else - e.state |= ControlMask; - } - if (lpKeyState[VK_NUMLOCK] & 0x01) - e.state |= NumLockMask; - TRACE(key, "(%04X, %04X) : faked state = %X\n", - virtKey, scanCode, e.state); - /* We exit on the first keycode found, to speed up the thing. */ - for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++) - { /* Find a keycode that could have generated this virtual key */ - if ((keyc2vkey[keyc] & 0xFF) == virtKey) - { /* We filter the extended bit, we don't know it */ - e.keycode = keyc; /* Store it temporarily */ - if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) { - e.keycode = 0; /* Wrong one (ex: because of the NumLock - state), so set it to 0, we'll find another one */ - } - } - } - - if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9)) - e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0); - - if (virtKey==VK_DECIMAL) - e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal); - - if (!e.keycode) - { - WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey); - return virtKey; /* whatever */ - } - else TRACE(keyboard,"Found keycode %d (0x%2X)\n",e.keycode,e.keycode); - - ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs); - if (ret == 0) - { - BYTE dead_char = 0; - - ((char*)lpChar)[1] = '\0'; - switch (keysym) - { - /* symbolic ASCII is the same as defined in rfc1345 */ -#ifdef XK_dead_tilde - case XK_dead_tilde : -#endif - case 0x1000FE7E : /* Xfree's XK_Dtilde */ - dead_char = '~'; /* '? */ - break; -#ifdef XK_dead_acute - case XK_dead_acute : -#endif - case 0x1000FE27 : /* Xfree's XK_Dacute_accent */ - dead_char = 0xb4; /* '' */ - break; -#ifdef XK_dead_circumflex - case XK_dead_circumflex : -#endif - case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */ - dead_char = '^'; /* '> */ - break; -#ifdef XK_dead_grave - case XK_dead_grave : -#endif - case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */ - dead_char = '`'; /* '! */ - break; -#ifdef XK_dead_diaeresis - case XK_dead_diaeresis : -#endif - case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */ - dead_char = 0xa8; /* ': */ - break; -#ifdef XK_dead_cedilla - case XK_dead_cedilla : - dead_char = 0xb8; /* ', */ - break; -#endif -#ifdef XK_dead_macron - case XK_dead_macron : - dead_char = '-'; /* 'm isn't defined on iso-8859-x */ - break; -#endif -#ifdef XK_dead_breve - case XK_dead_breve : - dead_char = 0xa2; /* '( */ - break; -#endif -#ifdef XK_dead_abovedot - case XK_dead_abovedot : - dead_char = 0xff; /* '. */ - break; -#endif -#ifdef XK_dead_abovering - case XK_dead_abovering : - dead_char = '0'; /* '0 isn't defined on iso-8859-x */ - break; -#endif -#ifdef XK_dead_doubleacute - case XK_dead_doubleacute : - dead_char = 0xbd; /* '" */ - break; -#endif -#ifdef XK_dead_caron - case XK_dead_caron : - dead_char = 0xb7; /* '< */ - break; -#endif -#ifdef XK_dead_ogonek - case XK_dead_ogonek : - dead_char = 0xb2; /* '; */ - break; -#endif -/* FIXME: I don't know this three. - case XK_dead_iota : - dead_char = 'i'; - break; - case XK_dead_voiced_sound : - dead_char = 'v'; - break; - case XK_dead_semivoiced_sound : - dead_char = 's'; - break; -*/ - } - if (dead_char) - { - *(char*)lpChar = dead_char; - ret = -1; - } - else - { - char *ksname; - - ksname = TSXKeysymToString(keysym); - if (!ksname) - ksname = "No Name"; - if ((keysym >> 8) != 0xff) - { - ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n", - keysym, ksname); - ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n", - virtKey, scanCode, e.keycode, e.state); - } - } - } - else { /* ret = 1 */ - /* We have a special case to handle : Shift + arrow, shift + home, ... - X returns a char for it, but Windows doesn't. Let's eat it. */ - if (!(lpKeyState[VK_NUMLOCK] & 0x01) /* NumLock is off */ - && (lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */ - && (keysym>=XK_KP_0) && (keysym<=XK_KP_9)) - { - *(char*)lpChar = 0; - ret = 0; - } - } - - TRACE(key, "ToAscii about to return %d with char %x\n", - ret, *(char*)lpChar); - return ret; + return KEYBOARD_GetDriver()->pToAscii( + virtKey, scanCode, lpKeyState, lpChar, flags + ); } + diff --git a/windows/message.c b/windows/message.c index f3b0c96f64b..c7ad72d35bd 100644 --- a/windows/message.c +++ b/windows/message.c @@ -4,6 +4,8 @@ * Copyright 1993, 1994 Alexandre Julliard */ +#include "ts_xlib.h" + #include #include #include @@ -449,7 +451,7 @@ static BOOL32 MSG_PeekHardwareMsg( MSG16 *msg, HWND16 hwnd, DWORD filter, /* If the queue is empty, attempt to fill it */ if (!sysMsgQueue->msgCount && THREAD_IsWin16( THREAD_Current() ) - && TSXPending(display)) + && EVENT_Pending()) EVENT_WaitNetEvent( FALSE, FALSE ); for (i = kbd_msg = 0; i < sysMsgQueue->msgCount; i++, pos++) diff --git a/windows/nonclient.c b/windows/nonclient.c index 41efc2fdd07..5d65d6303e0 100644 --- a/windows/nonclient.c +++ b/windows/nonclient.c @@ -2048,9 +2048,10 @@ static void NC_DoSizeMove( HWND32 hwnd, WORD wParam ) else { /* Grab the server only when moving top-level windows without desktop */ hdc = GetDC32( 0 ); - if (rootWindow == DefaultRootWindow(display)) TSXGrabServer( display ); } + wndPtr->pDriver->pPreSizeMove(wndPtr); + if( iconic ) /* create a cursor for dragging */ { HICON16 hIcon = (wndPtr->class->hIcon) ? wndPtr->class->hIcon @@ -2146,9 +2147,10 @@ static void NC_DoSizeMove( HWND32 hwnd, WORD wParam ) else { ReleaseDC32( 0, hdc ); - if (rootWindow == DefaultRootWindow(display)) TSXUngrabServer( display ); } + wndPtr->pDriver->pPostSizeMove(wndPtr); + if (HOOK_IsHooked( WH_CBT )) { RECT16* pr = SEGPTR_NEW(RECT16); diff --git a/windows/win.c b/windows/win.c index c73ef1d8295..983aca58737 100644 --- a/windows/win.c +++ b/windows/win.c @@ -31,6 +31,8 @@ #include "winerror.h" #include "mdi.h" +extern WND_DRIVER X11DRV_WND_Driver; + /* Desktop window */ static WND *pWndDesktop = NULL; @@ -146,20 +148,6 @@ void WIN_WalkWindows( HWND32 hwnd, int indent ) } } - -/*********************************************************************** - * WIN_GetXWindow - * - * Return the X window associated to a window. - */ -Window WIN_GetXWindow( HWND32 hwnd ) -{ - WND *wndPtr = WIN_FindWndPtr( hwnd ); - while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent; - return wndPtr ? wndPtr->window : 0; -} - - /*********************************************************************** * WIN_UnlinkWindow * @@ -325,7 +313,7 @@ static WND* WIN_DestroyWindow( WND* wndPtr ) if (!(wndPtr->dwStyle & WS_CHILD)) if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu ); if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu ); - if (wndPtr->window) EVENT_DestroyWindow( wndPtr ); + wndPtr->pDriver->pDestroyWindow( wndPtr ); DCE_FreeWindowDCE( wndPtr ); /* Always do this to catch orphaned DCs */ WINPROC_FreeProc( wndPtr->winproc, WIN_PROC_WINDOW ); wndPtr->hwndSelf = 0; @@ -433,15 +421,15 @@ BOOL32 WIN_CreateDesktopWindow(void) pWndDesktop->wIDmenu = 0; pWndDesktop->helpContext = 0; pWndDesktop->flags = 0; - pWndDesktop->window = rootWindow; pWndDesktop->hSysMenu = 0; pWndDesktop->userdata = 0; pWndDesktop->pDriver = &X11DRV_WND_Driver; - pWndDesktop->expose_event = NULL; - pWndDesktop->winproc = (WNDPROC16)class->winproc; - EVENT_RegisterWindow( pWndDesktop ); + /* FIXME: How do we know if it should be Unicode or not */ + if(!pWndDesktop->pDriver->pCreateDesktopWindow(pWndDesktop, class, FALSE)) + return FALSE; + SendMessage32A( hwndDesktop, WM_NCCREATE, 0, 0 ); pWndDesktop->flags |= WIN_NEEDS_ERASEBKGND; return TRUE; @@ -648,7 +636,8 @@ static HWND32 WIN_CreateWindowEx( CREATESTRUCT32A *cs, ATOM classAtom, wndPtr->rectWindow.bottom = cs->y + cs->cy; wndPtr->rectClient = wndPtr->rectWindow; - (*wndPtr->pDriver->pCreateWindow)(wndPtr, classPtr, cs, unicode); + if(!wndPtr->pDriver->pCreateWindow(wndPtr, classPtr, cs, unicode)) + return FALSE; /* Set the window menu */ @@ -924,7 +913,7 @@ static void WIN_SendDestroyMsg( WND* pWnd ) WIN_CheckFocus(pWnd); if( CARET_GetHwnd() == pWnd->hwndSelf ) DestroyCaret32(); - if( !pWnd->window ) CLIPBOARD_ResetOwner( pWnd ); + if( !pWnd->window ) CLIPBOARD_GetDriver()->pResetOwner( pWnd ); SendMessage32A( pWnd->hwndSelf, WM_DESTROY, 0, 0); @@ -986,7 +975,7 @@ BOOL32 WINAPI DestroyWindow32( HWND32 hwnd ) if( !IsWindow32(hwnd) ) return TRUE; } - if( wndPtr->window ) CLIPBOARD_ResetOwner( wndPtr ); /* before the window is unmapped */ + if( wndPtr->window ) CLIPBOARD_GetDriver()->pResetOwner( wndPtr ); /* before the window is unmapped */ /* Hide the window */ diff --git a/windows/winpos.c b/windows/winpos.c index de2e46ee7a6..fcb9a39f915 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -6,9 +6,6 @@ */ #include -#include "ts_xlib.h" -#include "ts_xutil.h" -#include #include "sysmetrics.h" #include "heap.h" #include "module.h" @@ -1435,35 +1432,6 @@ void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd, } } - -/*********************************************************************** - * WINPOS_ForceXWindowRaise - * - * Raise a window on top of the X stacking order, while preserving - * the correct Windows Z order. - */ -static void WINPOS_ForceXWindowRaise( WND* pWnd ) -{ - XWindowChanges winChanges; - WND *wndPrev; - - /* Raise all windows up to pWnd according to their Z order. - * (it would be easier with sibling-related Below but it doesn't - * work very well with SGI mwm for instance) - */ - winChanges.stack_mode = Above; - while (pWnd) - { - if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0, - CWStackMode, &winChanges ); - wndPrev = WIN_GetDesktop()->child; - if (wndPrev == pWnd) break; - while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next; - pWnd = wndPrev; - } -} - - /******************************************************************* * WINPOS_SetActiveWindow * @@ -1620,9 +1588,8 @@ BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus) hwndActive ); - if( !hwndPrevActive && wndPtr && - wndPtr->window && !(wndPtr->flags & WIN_MANAGED) ) - WINPOS_ForceXWindowRaise(wndPtr); + if( !hwndPrevActive && wndPtr ) + (*wndPtr->pDriver->pForceWindowRaise)(wndPtr); /* if active wnd is minimized redraw icon title */ if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive); @@ -2057,104 +2024,6 @@ static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn, return uFlags; } - -/*********************************************************************** - * WINPOS_FindDeskTopXWindow - * - * Find the actual X window which needs be restacked. - * Used by WINPOS_SetXWindowPos(). - */ -static Window WINPOS_FindDeskTopXWindow( WND *wndPtr ) -{ - if (!(wndPtr->flags & WIN_MANAGED)) - return wndPtr->window; - else - { - Window window, root, parent, *children; - int nchildren; - window = wndPtr->window; - for (;;) - { - TSXQueryTree( display, window, &root, &parent, - &children, &nchildren ); - TSXFree( children ); - if (parent == root) - return window; - window = parent; - } - } -} - -/*********************************************************************** - * WINPOS_SetXWindowPos - * - * SetWindowPos() for an X window. Used by the real SetWindowPos(). - */ -static void WINPOS_SetXWindowPos( const WINDOWPOS32 *winpos ) -{ - XWindowChanges winChanges; - int changeMask = 0; - WND *wndPtr = WIN_FindWndPtr( winpos->hwnd ); - - if (!(winpos->flags & SWP_NOSIZE)) - { - winChanges.width = winpos->cx; - winChanges.height = winpos->cy; - changeMask |= CWWidth | CWHeight; - - /* Tweak dialog window size hints */ - - if ((wndPtr->flags & WIN_MANAGED) && - (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)) - { - XSizeHints *size_hints = TSXAllocSizeHints(); - - if (size_hints) - { - long supplied_return; - - TSXGetWMSizeHints( display, wndPtr->window, size_hints, - &supplied_return, XA_WM_NORMAL_HINTS); - size_hints->min_width = size_hints->max_width = winpos->cx; - size_hints->min_height = size_hints->max_height = winpos->cy; - TSXSetWMSizeHints( display, wndPtr->window, size_hints, - XA_WM_NORMAL_HINTS ); - TSXFree(size_hints); - } - } - } - if (!(winpos->flags & SWP_NOMOVE)) - { - winChanges.x = winpos->x; - winChanges.y = winpos->y; - changeMask |= CWX | CWY; - } - if (!(winpos->flags & SWP_NOZORDER)) - { - winChanges.stack_mode = Below; - changeMask |= CWStackMode; - - if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above; - else if (winpos->hwndInsertAfter != HWND_BOTTOM) - { - WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter ); - Window stack[2]; - - stack[0] = WINPOS_FindDeskTopXWindow( insertPtr ); - stack[1] = WINPOS_FindDeskTopXWindow( wndPtr ); - - /* for stupid window managers (i.e. all of them) */ - - TSXRestackWindows(display, stack, 2); - changeMask &= ~CWStackMode; - } - } - if (!changeMask) return; - - TSXReconfigureWMWindow( display, wndPtr->window, 0, changeMask, &winChanges ); -} - - /*********************************************************************** * SetWindowPos (USER.232) */ @@ -2364,7 +2233,7 @@ BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter, if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) ) { - WINPOS_SetXWindowPos( &winpos ); + wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE); winpos.hwndInsertAfter = tempInsertAfter; } else uFlags |= SMC_SETXPOS; @@ -2459,12 +2328,12 @@ BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter, { HWND32 focus, curr; + wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS ); if( uFlags & SMC_SETXPOS ) { - WINPOS_SetXWindowPos( &winpos ); winpos.hwndInsertAfter = tempInsertAfter; } - TSXMapWindow( display, wndPtr->window ); + if (wndPtr->flags & WIN_MANAGED) resync = TRUE; /* If focus was set to an unmapped window, reset X focus now */ @@ -2488,19 +2357,18 @@ BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter, } else if (flags & SWP_HIDEWINDOW) { + wndPtr->dwStyle &= ~WS_VISIBLE; + if (wndPtr->window) { - if (wndPtr->dwStyle & WS_VISIBLE) TSXUnmapWindow( display, wndPtr->window ); - wndPtr->dwStyle &= ~WS_VISIBLE; - if( uFlags & SMC_SETXPOS ) - { - WINPOS_SetXWindowPos( &winpos ); - winpos.hwndInsertAfter = tempInsertAfter; - } + wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS ); + if( uFlags & SMC_SETXPOS ) + { + winpos.hwndInsertAfter = tempInsertAfter; + } } else { - wndPtr->dwStyle &= ~WS_VISIBLE; if (!(flags & SWP_NOREDRAW)) PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN | diff --git a/windows/x11drv/Makefile.in b/windows/x11drv/Makefile.in index 89eb67b3aea..ebf0d612a1a 100644 --- a/windows/x11drv/Makefile.in +++ b/windows/x11drv/Makefile.in @@ -6,7 +6,12 @@ VPATH = @srcdir@ MODULE = x11drv C_SRCS = \ - init.c + clipboard.c \ + event.c \ + init.c \ + keyboard.c \ + mouse.c \ + wnd.c all: $(MODULE).o diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c new file mode 100644 index 00000000000..39c1f47cd24 --- /dev/null +++ b/windows/x11drv/clipboard.c @@ -0,0 +1,299 @@ +/* + * X11 windows driver + * + * Copyright 1994 Martin Ayotte + * 1996 Alex Korobka + */ + +#include "config.h" + +#ifndef X_DISPLAY_MISSING + +#include +#include "ts_xlib.h" + +#include "windows.h" +#include "wintypes.h" + +#include "clipboard.h" +#include "debug.h" +#include "message.h" +#include "win.h" +#include "x11drv.h" + +extern HWND32 hWndClipOwner; +extern HWND32 hWndClipWindow; +extern CLIPFORMAT ClipFormats[]; + +static Bool selectionWait = False; +static Bool selectionAcquired = False; +static Window selectionWindow = None; +static Window selectionPrevWindow = None; + +/************************************************************************** + * X11DRV_CLIPBOARD_CheckSelection [Internal] + * + * Prevent X selection from being lost when a top level window is + * destroyed. + */ +static void X11DRV_CLIPBOARD_CheckSelection(WND* pWnd) +{ + TRACE(clipboard,"\tchecking %08x\n", (unsigned)pWnd->window); + + if( selectionAcquired && selectionWindow != None && + pWnd->window == selectionWindow ) + { + selectionPrevWindow = selectionWindow; + selectionWindow = None; + + if( pWnd->next ) + selectionWindow = pWnd->next->window; + else if( pWnd->parent ) + if( pWnd->parent->child != pWnd ) + selectionWindow = pWnd->parent->child->window; + + TRACE(clipboard,"\tswitching selection from %08x to %08x\n", + (unsigned)selectionPrevWindow, (unsigned)selectionWindow); + + if( selectionWindow != None ) + { + TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime); + if( TSXGetSelectionOwner(display, XA_PRIMARY) != selectionWindow ) + selectionWindow = None; + } + } +} + +/************************************************************************** + * X11DRV_CLIPBOARD_ReadSelection + * + * Called from the SelectionNotify event handler. + */ +void X11DRV_CLIPBOARD_ReadSelection(Window w,Atom prop) +{ + HANDLE32 hText = 0; + LPCLIPFORMAT lpFormat = ClipFormats; + + TRACE(clipboard,"ReadSelection callback\n"); + + if(prop != None) + { + Atom atype=AnyPropertyType; + int aformat; + unsigned long nitems,remain; + unsigned char* val=NULL; + + TRACE(clipboard,"\tgot property %s\n",TSXGetAtomName(display,prop)); + + /* TODO: Properties longer than 64K */ + + if(TSXGetWindowProperty(display,w,prop,0,0x3FFF,True,XA_STRING, + &atype, &aformat, &nitems, &remain, &val) != Success) + WARN(clipboard, "\tcouldn't read property\n"); + else + { + TRACE(clipboard,"\tType %s,Format %d,nitems %ld,value %s\n", + TSXGetAtomName(display,atype),aformat,nitems,val); + + if(atype == XA_STRING && aformat == 8) + { + int i,inlcount = 0; + char* lpstr; + + TRACE(clipboard,"\tselection is '%s'\n",val); + + for(i=0; i <= nitems; i++) + if( val[i] == '\n' ) inlcount++; + + if( nitems ) + { + hText=GlobalAlloc32(GMEM_MOVEABLE, nitems + inlcount + 1); + if( (lpstr = (char*)GlobalLock32(hText)) ) + for(i=0,inlcount=0; i <= nitems; i++) + { + if( val[i] == '\n' ) lpstr[inlcount++]='\r'; + lpstr[inlcount++]=val[i]; + } + else hText = 0; + } + } + TSXFree(val); + } + } + + /* delete previous CF_TEXT and CF_OEMTEXT data */ + + if( hText ) + { + lpFormat = &ClipFormats[CF_TEXT-1]; + if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) + CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow)); + lpFormat = &ClipFormats[CF_OEMTEXT-1]; + if (lpFormat->wDataPresent || lpFormat->hData16 || lpFormat->hData32) + CLIPBOARD_DeleteRecord(lpFormat, !(hWndClipWindow)); + + lpFormat->wDataPresent = 1; + lpFormat->hData32 = hText; + lpFormat->hData16 = 0; + } + + selectionWait=False; +} + +/************************************************************************** + * X11DRV_CLIPBOARD_ReleaseSelection + * + * Wine might have lost XA_PRIMARY selection because of + * EmptyClipboard() or other client. + */ +void X11DRV_CLIPBOARD_ReleaseSelection(Window w, HWND32 hwnd) +{ + /* w is the window that lost selection, + * + * selectionPrevWindow is nonzero if CheckSelection() was called. + */ + + TRACE(clipboard,"\tevent->window = %08x (sw = %08x, spw=%08x)\n", + (unsigned)w, (unsigned)selectionWindow, (unsigned)selectionPrevWindow ); + + if( selectionAcquired ) + { + if( w == selectionWindow || selectionPrevWindow == None) + { + /* alright, we really lost it */ + + selectionAcquired = False; + selectionWindow = None; + + /* but we'll keep existing data for internal use */ + } + else if( w == selectionPrevWindow ) + { + w = TSXGetSelectionOwner(display, XA_PRIMARY); + if( w == None ) + TSXSetSelectionOwner(display, XA_PRIMARY, selectionWindow, CurrentTime); + } + } + + selectionPrevWindow = None; +} + +/************************************************************************** + * X11DRV_CLIPBOARD_EmptyClipboard + */ +void X11DRV_CLIPBOARD_EmptyClipboard() +{ + if(selectionAcquired) + { + selectionAcquired = False; + selectionPrevWindow = selectionWindow; + selectionWindow = None; + + TRACE(clipboard, "\tgiving up selection (spw = %08x)\n", + (unsigned)selectionPrevWindow); + + TSXSetSelectionOwner(display, XA_PRIMARY, None, CurrentTime); + } +} + +/************************************************************************** + * X11DRV_CLIPBOARD_SetClipboardData + */ +void X11DRV_CLIPBOARD_SetClipboardData(UINT32 wFormat) +{ + Window owner; + + /* Acquire X selection if text format */ + + if( !selectionAcquired && + (wFormat == CF_TEXT || wFormat == CF_OEMTEXT) ) + { + owner = X11DRV_WND_GetXWindow( hWndClipWindow ? hWndClipWindow : AnyPopup32() ); + + TSXSetSelectionOwner(display,XA_PRIMARY, owner, CurrentTime); + if( TSXGetSelectionOwner(display,XA_PRIMARY) == owner ) + { + selectionAcquired = True; + selectionWindow = owner; + + TRACE(clipboard,"Grabbed X selection, owner=(%08x)\n", + (unsigned) owner); + } + } +} + +/************************************************************************** + * X11DRV_CLIPBOARD_RequestSelection + */ +BOOL32 X11DRV_CLIPBOARD_RequestSelection() +{ + HWND32 hWnd = (hWndClipWindow) ? hWndClipWindow : GetActiveWindow32(); + + if( selectionAcquired ) + return TRUE; + + if( !hWnd ) return FALSE; + + TRACE(clipboard,"Requesting selection...\n"); + + /* request data type XA_STRING, later + * CLIPBOARD_ReadSelection() will be invoked + * from the SelectionNotify event handler */ + + TSXConvertSelection(display,XA_PRIMARY,XA_STRING, + TSXInternAtom(display,"PRIMARY_TEXT",False), + X11DRV_WND_GetXWindow(hWnd),CurrentTime); + + /* wait until SelectionNotify is processed + * + * FIXME: Use TSXCheckTypedWindowEvent() instead ( same in the + * CLIPBOARD_CheckSelection() ). + */ + + selectionWait=True; + while(selectionWait) EVENT_WaitNetEvent( TRUE, FALSE ); + + /* we treat Unix text as CF_OEMTEXT */ + TRACE(clipboard,"\tgot CF_OEMTEXT = %i\n", + ClipFormats[CF_OEMTEXT-1].wDataPresent); + + return (BOOL32)ClipFormats[CF_OEMTEXT-1].wDataPresent; +} + +/************************************************************************** + * X11DRV_CLIPBOARD_ResetOwner + * + * Called from DestroyWindow(). + */ +void X11DRV_CLIPBOARD_ResetOwner(WND *pWnd) +{ + LPCLIPFORMAT lpFormat = ClipFormats; + + TRACE(clipboard,"clipboard owner = %04x, selection = %08x\n", + hWndClipOwner, (unsigned)selectionWindow); + + if( pWnd->hwndSelf == hWndClipOwner) + { + SendMessage16(hWndClipOwner,WM_RENDERALLFORMATS,0,0L); + + /* check if all formats were rendered */ + + while(lpFormat) + { + if( lpFormat->wDataPresent && !lpFormat->hData16 && !lpFormat->hData32 ) + { + TRACE(clipboard,"\tdata missing for clipboard format %i\n", + lpFormat->wFormatID); + lpFormat->wDataPresent = 0; + } + lpFormat = lpFormat->NextFormat; + } + hWndClipOwner = 0; + } + + /* now try to salvage current selection from being destroyed by X */ + + if( pWnd->window ) X11DRV_CLIPBOARD_CheckSelection(pWnd); +} + +#endif /* !defined(X_DISPLAY_MISSING) */ diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c new file mode 100644 index 00000000000..e3016479180 --- /dev/null +++ b/windows/x11drv/event.c @@ -0,0 +1,1388 @@ +/* + * X11 windows driver + * + * Copyright 1993 Alexandre Julliard + */ + +#include "config.h" + +#ifndef X_DISPLAY_MISSING + +#include +#include +#include "ts_xlib.h" +#include "ts_xresource.h" +#include "ts_xutil.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "windows.h" +#include "winnt.h" +#include "gdi.h" +#include "heap.h" +#include "queue.h" +#include "win.h" +#include "class.h" +#include "dce.h" +#include "message.h" +#include "module.h" +#include "options.h" +#include "queue.h" +#include "winpos.h" +#include "drive.h" +#include "shell.h" +#include "keyboard.h" +#include "mouse.h" +#include "debug.h" +#include "dde_proc.h" +#include "winsock.h" +#include "mouse.h" +#include "x11drv.h" + +/* X context to associate a hwnd to an X window */ +extern XContext winContext; + +extern Atom wmProtocols; +extern Atom wmDeleteWindow; +extern Atom dndProtocol; +extern Atom dndSelection; + +#define NB_BUTTONS 3 /* Windows can handle 3 buttons */ + +#define DndNotDnd -1 /* OffiX drag&drop */ +#define DndUnknown 0 +#define DndRawData 1 +#define DndFile 2 +#define DndFiles 3 +#define DndText 4 +#define DndDir 5 +#define DndLink 6 +#define DndExe 7 + +#define DndEND 8 + +#define DndURL 128 /* KDE drag&drop */ + +/* EVENT_WaitNetEvent() master fd sets */ + +static fd_set __event_io_set[3]; +static int __event_max_fd = 0; +static int __event_x_connection = 0; + +static const char * const event_names[] = +{ + "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease", + "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut", + "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify", + "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest", + "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify", + "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify", + "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify", + "ClientMessage", "MappingNotify" +}; + +static void EVENT_ProcessEvent( XEvent *event ); + + /* Event handlers */ +static void EVENT_Key( WND *pWnd, XKeyEvent *event ); +static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event ); +static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event ); +static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event ); +static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event ); +static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event ); +static int EVENT_Expose( WND *pWnd, XExposeEvent *event ); +static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event ); +static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event ); +static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event); +static void EVENT_SelectionNotify( XSelectionEvent *event); +static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event); +static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event ); +static void EVENT_MapNotify( HWND32 hwnd, XMapEvent *event ); + +/* Usable only with OLVWM - compile option perhaps? +static void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event ); +*/ + +static void EVENT_GetGeometry( Window win, int *px, int *py, + unsigned int *pwidth, unsigned int *pheight ); + + +/*********************************************************************** + * EVENT_Init + * + * Initialize network IO. + */ +BOOL32 X11DRV_EVENT_Init(void) +{ + int i; + for( i = 0; i < 3; i++ ) + FD_ZERO( __event_io_set + i ); + + __event_max_fd = __event_x_connection = ConnectionNumber(display); + FD_SET( __event_x_connection, &__event_io_set[EVENT_IO_READ] ); + __event_max_fd++; + return TRUE; +} + +/*********************************************************************** + * X11DRV_EVENT_AddIO + */ +void X11DRV_EVENT_AddIO( int fd, unsigned io_type ) +{ + FD_SET( fd, &__event_io_set[io_type] ); + if( __event_max_fd <= fd ) __event_max_fd = fd + 1; +} + +/*********************************************************************** + * X11DRV_EVENT_DeleteIO + */ +void X11DRV_EVENT_DeleteIO( int fd, unsigned io_type ) +{ + FD_CLR( fd, &__event_io_set[io_type] ); +} + +/*********************************************************************** + * X11DRV_EVENT_IsUserIdle + */ +BOOL16 WINAPI X11DRV_EVENT_IsUserIdle(void) +{ + struct timeval timeout = {0, 0}; + fd_set check_set; + + FD_ZERO(&check_set); + FD_SET(__event_x_connection, &check_set); + if( select(__event_x_connection + 1, &check_set, NULL, NULL, &timeout) > 0 ) + return TRUE; + return FALSE; +} + +/*********************************************************************** + * X11DRV_EVENT_WaitNetEvent + * + * Wait for a network event, optionally sleeping until one arrives. + * Return TRUE if an event is pending, FALSE on timeout or error + * (for instance lost connection with the server). + */ + +BOOL32 X11DRV_EVENT_WaitNetEvent( BOOL32 sleep, BOOL32 peek ) +{ + XEvent event; + LONG maxWait = sleep ? TIMER_GetNextExpiration() : 0; + int pending = TSXPending(display); + + /* Wait for an event or a timeout. If maxWait is -1, we have no timeout; + * in this case, we fall through directly to the XNextEvent loop. + */ + + if ((maxWait != -1) && !pending) + { + int num_pending; + struct timeval timeout; + fd_set io_set[3]; + + memcpy( io_set, __event_io_set, sizeof(io_set) ); + + timeout.tv_usec = (maxWait % 1000) * 1000; + timeout.tv_sec = maxWait / 1000; + +#ifdef CONFIG_IPC + sigsetjmp(env_wait_x, 1); + stop_wait_op= CONT; + + if (DDE_GetRemoteMessage()) { + while(DDE_GetRemoteMessage()) + ; + return TRUE; + } + stop_wait_op = STOP_WAIT_X; + /* The code up to the next "stop_wait_op = CONT" must be reentrant */ + num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], + &io_set[EVENT_IO_WRITE], + &io_set[EVENT_IO_EXCEPT], &timeout ); + if ( num_pending == 0 ) + { + stop_wait_op = CONT; + TIMER_ExpireTimers(); + return FALSE; + } + else stop_wait_op = CONT; +#else /* CONFIG_IPC */ + num_pending = select( __event_max_fd, &io_set[EVENT_IO_READ], + &io_set[EVENT_IO_WRITE], + &io_set[EVENT_IO_EXCEPT], &timeout ); + if ( num_pending == 0) + { + /* Timeout or error */ + TIMER_ExpireTimers(); + return FALSE; + } +#endif /* CONFIG_IPC */ + + /* Winsock asynchronous services */ + + if( FD_ISSET( __event_x_connection, &io_set[EVENT_IO_READ]) ) + { + num_pending--; + if( num_pending ) + WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set ); + } + else /* no X events */ + return WINSOCK_HandleIO( &__event_max_fd, num_pending, io_set, __event_io_set ); + } + else if(!pending) + { /* Wait for X11 input. */ + fd_set set; + + FD_ZERO(&set); + FD_SET(__event_x_connection, &set); + select(__event_x_connection + 1, &set, 0, 0, 0 ); + } + + /* Process current X event (and possibly others that occurred in the meantime) */ + + EnterCriticalSection(&X11DRV_CritSection); + while (XPending( display )) + { + +#ifdef CONFIG_IPC + if (DDE_GetRemoteMessage()) + { + LeaveCriticalSection(&X11DRV_CritSection); + while(DDE_GetRemoteMessage()) ; + return TRUE; + } +#endif /* CONFIG_IPC */ + + XNextEvent( display, &event ); + + LeaveCriticalSection(&X11DRV_CritSection); + if( peek ) + { + WND* pWnd; + MESSAGEQUEUE* pQ; + + + /* Check only for those events which can be processed + * internally. */ + + if( event.type == MotionNotify || + event.type == ButtonPress || event.type == ButtonRelease || + event.type == KeyPress || event.type == KeyRelease || + event.type == SelectionRequest || event.type == SelectionClear || + event.type == ClientMessage ) + { + EVENT_ProcessEvent( &event ); + continue; + } + + if (TSXFindContext( display, ((XAnyEvent *)&event)->window, winContext, + (char **)&pWnd ) || (event.type == NoExpose)) + pWnd = NULL; + + if( pWnd ) + { + if( (pQ = (MESSAGEQUEUE*)GlobalLock16(pWnd->hmemTaskQ)) ) + { + pQ->flags |= QUEUE_FLAG_XEVENT; + PostEvent(pQ->hTask); + TSXPutBackEvent(display, &event); + break; + } + } + } + else EVENT_ProcessEvent( &event ); + EnterCriticalSection(&X11DRV_CritSection); + } + LeaveCriticalSection(&X11DRV_CritSection); + return TRUE; +} + +/*********************************************************************** + * EVENT_Synchronize + * + * Synchronize with the X server. Should not be used too often. + */ +void X11DRV_EVENT_Synchronize() +{ + XEvent event; + + /* Use of the X critical section is needed or we have a small + * race between XPending() and XNextEvent(). + */ + EnterCriticalSection( &X11DRV_CritSection ); + XSync( display, False ); + while (XPending( display )) + { + XNextEvent( display, &event ); + /* unlock X critsection for EVENT_ProcessEvent() might switch tasks */ + LeaveCriticalSection( &X11DRV_CritSection ); + EVENT_ProcessEvent( &event ); + EnterCriticalSection( &X11DRV_CritSection ); + } + LeaveCriticalSection( &X11DRV_CritSection ); +} + +/*********************************************************************** + * EVENT_ProcessEvent + * + * Process an X event. + */ +static void EVENT_ProcessEvent( XEvent *event ) +{ + WND *pWnd; + + if ( TSXFindContext( display, event->xany.window, winContext, + (char **)&pWnd ) != 0) { + if ( event->type == ClientMessage) { + /* query window (drag&drop event contains only drag window) */ + Window root, child; + int root_x, root_y, child_x, child_y; + unsigned u; + TSXQueryPointer( display, rootWindow, &root, &child, + &root_x, &root_y, &child_x, &child_y, &u); + if (TSXFindContext( display, child, winContext, (char **)&pWnd ) != 0) + return; + } else { + pWnd = NULL; /* Not for a registered window */ + } + } + + TRACE(event, "Got event %s for hwnd %04x\n", + event_names[event->type], pWnd? pWnd->hwndSelf : 0 ); + + switch(event->type) + { + case KeyPress: + case KeyRelease: + EVENT_Key( pWnd, (XKeyEvent*)event ); + break; + + case ButtonPress: + EVENT_ButtonPress( pWnd, (XButtonEvent*)event ); + break; + + case ButtonRelease: + EVENT_ButtonRelease( pWnd, (XButtonEvent*)event ); + break; + + case MotionNotify: + /* Wine between two fast machines across the overloaded campus + ethernet gets very boged down in MotionEvents. The following + simply finds the last motion event in the queue and drops + the rest. On a good link events are servered before they build + up so this doesn't take place. On a slow link this may cause + problems if the event order is important. I'm not yet seen + of any problems. Jon 7/6/96. + */ + while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window, + MotionNotify, event)); + EVENT_MotionNotify( pWnd, (XMotionEvent*)event ); + break; + + case FocusIn: + if (!pWnd) return; + EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event ); + break; + + case FocusOut: + if (!pWnd) return; + EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event ); + break; + + case Expose: + if (!pWnd) return; + if (EVENT_Expose( pWnd, (XExposeEvent *)event )) { + /* need to process ConfigureNotify first */ + XEvent new_event; + + /* attempt to find and process the ConfigureNotify event now */ + if (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window, + ConfigureNotify, &new_event)) { + EVENT_ProcessEvent( &new_event ); + if (!EVENT_Expose( pWnd, (XExposeEvent *)event )) + break; + } + + /* no luck at this time, defer Expose event for later */ + /* use "type" for an event counter, it is never rechecked */ + if (!pWnd->expose_event) { + pWnd->expose_event = malloc( sizeof(XExposeEvent) ); + pWnd->expose_event[0] = *(XExposeEvent *)event; + pWnd->expose_event[0].type = 1; + } else { + int i; + + i = ++pWnd->expose_event[0].type; + pWnd->expose_event = realloc( pWnd->expose_event, + i * sizeof(XExposeEvent) ); + pWnd->expose_event[i-1] = *(XExposeEvent *)event; + FIXME(x11, "Try and combine Expose events? %d queued.\n", i); + } + } + break; + + case GraphicsExpose: + if (!pWnd) return; + EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event ); + break; + + case ConfigureNotify: + if (!pWnd) return; + EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event ); + if (pWnd->expose_event) { + /* process deferred Expose event(s) */ + int i; + + for (i=0; iexpose_event[0].type; i++) { + if(EVENT_Expose( pWnd, &pWnd->expose_event[i] )) + ERR(x11, "Unprocessed expose event discarded\n"); + } + free( pWnd->expose_event ); + pWnd->expose_event = NULL; + } + break; + + case SelectionRequest: + if (!pWnd) return; + EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event ); + break; + + case SelectionNotify: + if (!pWnd) return; + EVENT_SelectionNotify( (XSelectionEvent *)event ); + break; + + case SelectionClear: + if (!pWnd) return; + EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event ); + break; + + case ClientMessage: + if (!pWnd) return; + EVENT_ClientMessage( pWnd, (XClientMessageEvent *) event ); + break; + +#if 0 + case EnterNotify: + EVENT_EnterNotify( pWnd, (XCrossingEvent *) event ); + break; +#endif + + case NoExpose: + break; + + /* We get all these because of StructureNotifyMask. */ + case UnmapNotify: + case CirculateNotify: + case CreateNotify: + case DestroyNotify: + case GravityNotify: + case ReparentNotify: + break; + + case MapNotify: + if (!pWnd) return; + EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event ); + break; + + default: + WARN(event, "Unprocessed event %s for hwnd %04x\n", + event_names[event->type], pWnd? pWnd->hwndSelf : 0 ); + break; + } +} + +/*********************************************************************** + * EVENT_QueryZOrder + * + * Try to synchronize internal z-order with the window manager's. + * Probably a futile endeavor. + */ +static BOOL32 __check_query_condition( WND** pWndA, WND** pWndB ) +{ + /* return TRUE if we have at least two managed windows */ + + for( *pWndB = NULL; *pWndA; *pWndA = (*pWndA)->next ) + if( (*pWndA)->flags & WIN_MANAGED && + (*pWndA)->dwStyle & WS_VISIBLE ) break; + if( *pWndA ) + for( *pWndB = (*pWndA)->next; *pWndB; *pWndB = (*pWndB)->next ) + if( (*pWndB)->flags & WIN_MANAGED && + (*pWndB)->dwStyle & WS_VISIBLE ) break; + return ((*pWndB) != NULL); +} + +static Window __get_common_ancestor( Window A, Window B, + Window** children, unsigned* total ) +{ + /* find the real root window */ + + Window root, *childrenB; + unsigned totalB; + + do + { + if( *children ) TSXFree( *children ); + TSXQueryTree( display, A, &root, &A, children, total ); + TSXQueryTree( display, B, &root, &B, &childrenB, &totalB ); + if( childrenB ) TSXFree( childrenB ); + } while( A != B && A && B ); + return ( A && B ) ? A : 0 ; +} + +static Window __get_top_decoration( Window w, Window ancestor ) +{ + Window* children, root, prev = w, parent = w; + unsigned total; + + do + { + w = parent; + TSXQueryTree( display, w, &root, &parent, &children, &total ); + if( children ) TSXFree( children ); + } while( parent && parent != ancestor ); + TRACE(event, "\t%08x -> %08x\n", (unsigned)prev, (unsigned)w ); + return ( parent ) ? w : 0 ; +} + +static unsigned __td_lookup( Window w, Window* list, unsigned max ) +{ + unsigned i; + for( i = 0; i < max; i++ ) if( list[i] == w ) break; + return i; +} + +static BOOL32 EVENT_QueryZOrder( WND* pWndCheck ) +{ + BOOL32 bRet = FALSE; + HWND32 hwndInsertAfter = HWND_TOP; + WND* pWnd, *pWndZ = WIN_GetDesktop()->child; + Window w, parent, *children = NULL; + unsigned total, check, pos, best; + + if( !__check_query_condition(&pWndZ, &pWnd) ) return TRUE; + + parent = __get_common_ancestor( pWndZ->window, pWnd->window, + &children, &total ); + if( parent && children ) + { + w = __get_top_decoration( pWndCheck->window, parent ); + if( w != children[total - 1] ) + { + check = __td_lookup( w, children, total ); + best = total; + for( pWnd = pWndZ; pWnd; pWnd = pWnd->next ) + { + if( pWnd != pWndCheck ) + { + if( !(pWnd->flags & WIN_MANAGED) || + !(w = __get_top_decoration( pWnd->window, parent )) ) + continue; + pos = __td_lookup( w, children, total ); + if( pos < best && pos > check ) + { + best = pos; + hwndInsertAfter = pWnd->hwndSelf; + } + if( check - best == 1 ) break; + } + } + WIN_UnlinkWindow( pWndCheck->hwndSelf ); + WIN_LinkWindow( pWndCheck->hwndSelf, hwndInsertAfter); + } + } + if( children ) TSXFree( children ); + return bRet; +} + + +/*********************************************************************** + * EVENT_XStateToKeyState + * + * Translate a X event state (Button1Mask, ShiftMask, etc...) to + * a Windows key state (MK_SHIFT, MK_CONTROL, etc...) + */ +static WORD 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; +} + +/*********************************************************************** + * X11DRV_EVENT_QueryPointer + */ +BOOL32 X11DRV_EVENT_QueryPointer(DWORD *posX, DWORD *posY, DWORD *state) +{ + Window root, child; + int rootX, rootY, winX, winY; + unsigned int xstate; + + if (!TSXQueryPointer( display, rootWindow, &root, &child, + &rootX, &rootY, &winX, &winY, &xstate )) + return FALSE; + + if(posX) + *posX = (DWORD)winX; + if(posY) + *posY = (DWORD)winY; + if(state) + *state = EVENT_XStateToKeyState( xstate ); + + return TRUE; +} + +/*********************************************************************** + * EVENT_Expose + */ +static int EVENT_Expose( WND *pWnd, XExposeEvent *event ) +{ + RECT32 rect; + int x, y; + unsigned int width, height; + + /* When scrolling, many (fvwm2-based) window managers send the Expose + * event before sending the ConfigureNotify event, and we don't like + * that, so before processing the Expose event, we check whether the + * geometry has changed, and if so, we defer the Expose event until + * we get the ConfigureNotify event. -Ove Kåven */ + EVENT_GetGeometry( event->window, &x, &y, &width, &height ); + + if ( x != pWnd->rectWindow.left || y != pWnd->rectWindow.top || + (width != pWnd->rectWindow.right - pWnd->rectWindow.left) || + (height != pWnd->rectWindow.bottom - pWnd->rectWindow.top)) + return 1; /* tell EVENT_ProcessEvent() to defer it */ + + /* Make position relative to client area instead of window */ + rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left); + rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top); + rect.right = rect.left + event->width; + rect.bottom = rect.top + event->height; + + PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0, + RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE | + (event->count ? 0 : RDW_ERASENOW), 0 ); + return 0; +} + + +/*********************************************************************** + * EVENT_GraphicsExpose + * + * This is needed when scrolling area is partially obscured + * by non-Wine X window. + */ +static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event ) +{ + RECT32 rect; + + /* Make position relative to client area instead of window */ + rect.left = event->x - (pWnd->rectClient.left - pWnd->rectWindow.left); + rect.top = event->y - (pWnd->rectClient.top - pWnd->rectWindow.top); + rect.right = rect.left + event->width; + rect.bottom = rect.top + event->height; + + PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0, + RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE | + (event->count ? 0 : RDW_ERASENOW), 0 ); +} + + +/*********************************************************************** + * EVENT_Key + * + * Handle a X key event + */ +static void EVENT_Key( WND *pWnd, XKeyEvent *event ) +{ + KEYBOARD_HandleEvent( pWnd, event ); +} + + +/*********************************************************************** + * EVENT_MotionNotify + */ +static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event ) +{ + int xOffset = pWnd? pWnd->rectWindow.left : 0; + int yOffset = pWnd? pWnd->rectWindow.top : 0; + + MOUSE_SendEvent( MOUSEEVENTF_MOVE, + xOffset + event->x, yOffset + event->y, + EVENT_XStateToKeyState( event->state ), + event->time - MSG_WineStartTicks, + pWnd? pWnd->hwndSelf : 0 ); +} + + +/*********************************************************************** + * X11DRV_EVENT_DummyMotionNotify + * + * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message. + */ +void X11DRV_EVENT_DummyMotionNotify(void) +{ + DWORD winX, winY, state; + + if ( EVENT_QueryPointer( &winX, &winY, &state ) ) + { + MOUSE_SendEvent( MOUSEEVENTF_MOVE, winX, winY, state, + GetTickCount(), 0 ); + } +} + + +/*********************************************************************** + * EVENT_ButtonPress + */ +static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event ) +{ + static WORD statusCodes[NB_BUTTONS] = + { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN }; + int buttonNum = event->button - 1; + + int xOffset = pWnd? pWnd->rectWindow.left : 0; + int yOffset = pWnd? pWnd->rectWindow.top : 0; + + if (buttonNum >= NB_BUTTONS) return; + + MOUSE_SendEvent( statusCodes[buttonNum], + xOffset + event->x, yOffset + event->y, + EVENT_XStateToKeyState( event->state ), + event->time - MSG_WineStartTicks, + pWnd? pWnd->hwndSelf : 0 ); +} + + +/*********************************************************************** + * EVENT_ButtonRelease + */ +static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event ) +{ + static WORD statusCodes[NB_BUTTONS] = + { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP }; + int buttonNum = event->button - 1; + + int xOffset = pWnd? pWnd->rectWindow.left : 0; + int yOffset = pWnd? pWnd->rectWindow.top : 0; + + if (buttonNum >= NB_BUTTONS) return; + + MOUSE_SendEvent( statusCodes[buttonNum], + xOffset + event->x, yOffset + event->y, + EVENT_XStateToKeyState( event->state ), + event->time - MSG_WineStartTicks, + pWnd? pWnd->hwndSelf : 0 ); +} + + +/********************************************************************** + * EVENT_FocusIn + */ +static void EVENT_FocusIn( WND *pWnd, XFocusChangeEvent *event ) +{ + if (Options.managed) EVENT_QueryZOrder( pWnd ); + + if (event->detail != NotifyPointer) + { + HWND32 hwnd = pWnd->hwndSelf; + + if (hwnd != GetActiveWindow32()) + { + WINPOS_ChangeActiveWindow( hwnd, FALSE ); + KEYBOARD_UpdateState(); + } + if ((hwnd != GetFocus32()) && !IsChild32( hwnd, GetFocus32())) + SetFocus32( hwnd ); + } +} + + +/********************************************************************** + * EVENT_FocusOut + * + * Note: only top-level override-redirect windows get FocusOut events. + */ +static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event ) +{ + if (event->detail != NotifyPointer) + { + HWND32 hwnd = pWnd->hwndSelf; + + if (hwnd == GetActiveWindow32()) + WINPOS_ChangeActiveWindow( 0, FALSE ); + if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32())) + SetFocus32( 0 ); + } +} + +/********************************************************************** + * X11DRV_EVENT_CheckFocus + */ +BOOL32 X11DRV_EVENT_CheckFocus(void) +{ + WND* pWnd; + Window xW; + int state; + + TSXGetInputFocus(display, &xW, &state); + if( xW == None || + TSXFindContext(display, xW, winContext, (char **)&pWnd) ) + return FALSE; + return TRUE; +} + +/********************************************************************** + * EVENT_GetGeometry + * + * Helper function for ConfigureNotify handling. + * Get the new geometry of a window relative to the root window. + */ +static void EVENT_GetGeometry( Window win, int *px, int *py, + unsigned int *pwidth, unsigned int *pheight ) +{ + Window root, parent, *children; + int xpos, ypos; + unsigned int width, height, border, depth, nb_children; + + if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight, + &border, &depth )) return; + if (win == rootWindow) + { + *px = *py = 0; + return; + } + + for (;;) + { + if (!TSXQueryTree(display, win, &root, &parent, &children, &nb_children)) + return; + TSXFree( children ); + if (parent == rootWindow) break; + win = parent; + if (!TSXGetGeometry( display, win, &root, &xpos, &ypos, + &width, &height, &border, &depth )) return; + *px += xpos; + *py += ypos; + } +} + + +/********************************************************************** + * EVENT_ConfigureNotify + * + * The ConfigureNotify event is only selected on top-level windows + * when the -managed flag is used. + */ +static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event ) +{ + WINDOWPOS32 winpos; + RECT32 newWindowRect, newClientRect; + HRGN32 hrgnOldPos, hrgnNewPos; + Window above = event->above; + int x, y; + unsigned int width, height; + + assert (pWnd->flags & WIN_MANAGED); + + /* We don't rely on the event geometry info, because it is relative + * to parent and not to root, and it may be wrong (XFree sets x,y to 0,0 + * if the window hasn't moved). + */ + EVENT_GetGeometry( event->window, &x, &y, &width, &height ); + + /* Fill WINDOWPOS struct */ + winpos.flags = SWP_NOACTIVATE | SWP_NOZORDER; + winpos.hwnd = pWnd->hwndSelf; + winpos.x = x; + winpos.y = y; + winpos.cx = width; + winpos.cy = height; + + /* Check for unchanged attributes */ + if (winpos.x == pWnd->rectWindow.left && winpos.y == pWnd->rectWindow.top) + winpos.flags |= SWP_NOMOVE; + if ((winpos.cx == pWnd->rectWindow.right - pWnd->rectWindow.left) && + (winpos.cy == pWnd->rectWindow.bottom - pWnd->rectWindow.top)) + winpos.flags |= SWP_NOSIZE; + else + { + RECT32 rect = { 0, 0, pWnd->rectWindow.right - pWnd->rectWindow.left, + pWnd->rectWindow.bottom - pWnd->rectWindow.top }; + DCE_InvalidateDCE( pWnd, &rect ); + } + + /* Send WM_WINDOWPOSCHANGING */ + SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos ); + + /* Calculate new position and size */ + newWindowRect.left = x; + newWindowRect.right = x + width; + newWindowRect.top = y; + newWindowRect.bottom = y + height; + + WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect, + &pWnd->rectWindow, &pWnd->rectClient, + &winpos, &newClientRect ); + + hrgnOldPos = CreateRectRgnIndirect32( &pWnd->rectWindow ); + hrgnNewPos = CreateRectRgnIndirect32( &newWindowRect ); + CombineRgn32( hrgnOldPos, hrgnOldPos, hrgnNewPos, RGN_DIFF ); + DeleteObject32(hrgnOldPos); + DeleteObject32(hrgnNewPos); + + /* Set new size and position */ + pWnd->rectWindow = newWindowRect; + pWnd->rectClient = newClientRect; + SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos ); + + if (!IsWindow32( winpos.hwnd )) return; + if( above == None ) /* absolute bottom */ + { + WIN_UnlinkWindow( winpos.hwnd ); + WIN_LinkWindow( winpos.hwnd, HWND_BOTTOM); + } + else EVENT_QueryZOrder( pWnd ); /* try to outsmart window manager */ +} + + +/*********************************************************************** + * EVENT_SelectionRequest + */ +static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event ) +{ + XSelectionEvent result; + Atom rprop = None; + Window request = event->requestor; + + if(event->target == XA_STRING) + { + HANDLE16 hText; + LPSTR text; + int size,i,j; + + rprop = event->property; + + if(rprop == None) rprop = event->target; + + if(event->selection!=XA_PRIMARY) rprop = None; + else if(!CLIPBOARD_IsPresent(CF_OEMTEXT)) rprop = None; + else + { + /* open to make sure that clipboard is available */ + + BOOL32 couldOpen = OpenClipboard32( pWnd->hwndSelf ); + char* lpstr = 0; + + hText = GetClipboardData16(CF_TEXT); + text = GlobalLock16(hText); + size = GlobalSize16(hText); + + /* remove carriage returns */ + + lpstr = (char*)HEAP_xalloc( GetProcessHeap(), 0, size-- ); + for(i=0,j=0; i < size && text[i]; i++ ) + { + if( text[i] == '\r' && + (text[i+1] == '\n' || text[i+1] == '\0') ) continue; + lpstr[j++] = text[i]; + } + lpstr[j]='\0'; + + TSXChangeProperty(display, request, rprop, + XA_STRING, 8, PropModeReplace, + lpstr, j); + HeapFree( GetProcessHeap(), 0, lpstr ); + + /* close only if we opened before */ + + if(couldOpen) CloseClipboard32(); + } + } + + if(rprop == None) + TRACE(event,"Request for %s ignored\n", TSXGetAtomName(display,event->target)); + + result.type = SelectionNotify; + result.display = display; + result.requestor = request; + result.selection = event->selection; + result.property = rprop; + result.target = event->target; + result.time = event->time; + TSXSendEvent(display,event->requestor,False,NoEventMask,(XEvent*)&result); +} + + +/*********************************************************************** + * EVENT_SelectionNotify + */ +static void EVENT_SelectionNotify( XSelectionEvent *event ) +{ + if (event->selection != XA_PRIMARY) return; + + if (event->target != XA_STRING) X11DRV_CLIPBOARD_ReadSelection( 0, None ); + else X11DRV_CLIPBOARD_ReadSelection( event->requestor, event->property ); + + TRACE(clipboard,"\tSelectionNotify done!\n"); +} + + +/*********************************************************************** + * EVENT_SelectionClear + */ +static void EVENT_SelectionClear( WND *pWnd, XSelectionClearEvent *event ) +{ + if (event->selection != XA_PRIMARY) return; + X11DRV_CLIPBOARD_ReleaseSelection( event->window, pWnd->hwndSelf ); +} + + +/********************************************************************** + * EVENT_DropFromOffix + * + * don't know if it still works (last Changlog is from 96/11/04) + */ +static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event ) +{ + unsigned long data_length; + unsigned long aux_long; + unsigned char* p_data = NULL; + union { + Atom atom_aux; + POINT32 pt_aux; + int i; + } u; + int x, y; + BOOL16 bAccept; + HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO)); + LPDRAGINFO lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo); + SEGPTR spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo); + Window w_aux_root, w_aux_child; + WND* pDropWnd; + + if( !lpDragInfo || !spDragInfo ) return; + + TSXQueryPointer( display, pWnd->window, &w_aux_root, &w_aux_child, + &x, &y, &u.pt_aux.x, &u.pt_aux.y, (unsigned int*)&aux_long); + + lpDragInfo->hScope = pWnd->hwndSelf; + lpDragInfo->pt.x = (INT16)x; lpDragInfo->pt.y = (INT16)y; + + /* find out drop point and drop window */ + if( x < 0 || y < 0 || + x > (pWnd->rectWindow.right - pWnd->rectWindow.left) || + y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) ) + { bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; } + else + { + bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE ); + x = lpDragInfo->pt.x; y = lpDragInfo->pt.y; + } + pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope ); + GlobalFree16( hDragInfo ); + + if( bAccept ) + { + TSXGetWindowProperty( display, DefaultRootWindow(display), + dndSelection, 0, 65535, FALSE, + AnyPropertyType, &u.atom_aux, &u.pt_aux.y, + &data_length, &aux_long, &p_data); + + if( !aux_long && p_data) /* don't bother if > 64K */ + { + char *p = (char*) p_data; + char *p_drop; + + aux_long = 0; + while( *p ) /* calculate buffer size */ + { + p_drop = p; + if((u.i = *p) != -1 ) + u.i = DRIVE_FindDriveRoot( (const char **)&p_drop ); + if( u.i == -1 ) *p = -1; /* mark as "bad" */ + else + { + INT32 len = GetShortPathName32A( p, NULL, 0 ); + if (len) aux_long += len + 1; + else *p = -1; + } + p += strlen(p) + 1; + } + if( aux_long && aux_long < 65535 ) + { + HDROP16 hDrop; + LPDROPFILESTRUCT16 lpDrop; + + aux_long += sizeof(DROPFILESTRUCT16) + 1; + hDrop = (HDROP16)GlobalAlloc16( GMEM_SHARE, aux_long ); + lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop ); + + if( lpDrop ) + { + lpDrop->wSize = sizeof(DROPFILESTRUCT16); + lpDrop->ptMousePos.x = (INT16)x; + lpDrop->ptMousePos.y = (INT16)y; + lpDrop->fInNonClientArea = (BOOL16) + ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || + y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || + x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || + y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); + p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16); + p = p_data; + while(*p) + { + if( *p != -1 ) /* use only "good" entries */ + { + GetShortPathName32A( p, p_drop, 65535 ); + p_drop += strlen( p_drop ) + 1; + } + p += strlen(p) + 1; + } + *p_drop = '\0'; + PostMessage16( pWnd->hwndSelf, WM_DROPFILES, + (WPARAM16)hDrop, 0L ); + } + } + } + if( p_data ) TSXFree(p_data); + + } /* WS_EX_ACCEPTFILES */ +} + +/********************************************************************** + * EVENT_DropURLs + * + * drop items are separated by \n + * each item is prefixed by its mime type + * + * event->data.l[3], event->data.l[4] contains drop x,y position + */ +static void EVENT_DropURLs( WND *pWnd, XClientMessageEvent *event ) +{ + WND *pDropWnd; + unsigned long data_length; + unsigned long aux_long, drop_len = 0; + unsigned char *p_data = NULL; /* property data */ + char *p_drop = NULL; + char *p, *next; + int x, y, drop32 = FALSE ; + union { + Atom atom_aux; + POINT32 pt_aux; + int i; + Window w_aux; + } u; /* unused */ + union { + HDROP16 h16; + HDROP32 h32; + } hDrop; + + drop32 = pWnd->flags & WIN_ISWIN32; + + if (!(pWnd->dwExStyle & WS_EX_ACCEPTFILES)) + return; + + TSXGetWindowProperty( display, DefaultRootWindow(display), + dndSelection, 0, 65535, FALSE, + AnyPropertyType, &u.atom_aux, &u.i, + &data_length, &aux_long, &p_data); + if (aux_long) + WARN(event,"property too large, truncated!\n"); + TRACE(event,"urls=%s\n", p_data); + + if( !aux_long && p_data) { /* don't bother if > 64K */ + /* calculate length */ + p = p_data; + next = strchr(p, '\n'); + while (p) { + if (next) *next=0; + if (strncmp(p,"file:",5) == 0 ) { + INT32 len = GetShortPathName32A( p+5, NULL, 0 ); + if (len) drop_len += len + 1; + } + if (next) { + *next = '\n'; + p = next + 1; + next = strchr(p, '\n'); + } else { + p = NULL; + } + } + + if( drop_len && drop_len < 65535 ) { + TSXQueryPointer( display, rootWindow, &u.w_aux, &u.w_aux, + &x, &y, &u.i, &u.i, &u.i); + pDropWnd = WIN_FindWndPtr( pWnd->hwndSelf ); + + if (drop32) { + LPDROPFILESTRUCT32 lpDrop; + drop_len += sizeof(DROPFILESTRUCT32) + 1; + hDrop.h32 = (HDROP32)GlobalAlloc32( GMEM_SHARE, drop_len ); + lpDrop = (LPDROPFILESTRUCT32) GlobalLock32( hDrop.h32 ); + + if( lpDrop ) { + lpDrop->lSize = sizeof(DROPFILESTRUCT32); + lpDrop->ptMousePos.x = (INT32)x; + lpDrop->ptMousePos.y = (INT32)y; + lpDrop->fInNonClientArea = (BOOL32) + ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || + y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || + x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || + y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); + lpDrop->fWideChar = FALSE; + p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT32); + } + } else { + LPDROPFILESTRUCT16 lpDrop; + drop_len += sizeof(DROPFILESTRUCT16) + 1; + hDrop.h16 = (HDROP16)GlobalAlloc16( GMEM_SHARE, drop_len ); + lpDrop = (LPDROPFILESTRUCT16) GlobalLock16( hDrop.h16 ); + + if( lpDrop ) { + lpDrop->wSize = sizeof(DROPFILESTRUCT16); + lpDrop->ptMousePos.x = (INT16)x; + lpDrop->ptMousePos.y = (INT16)y; + lpDrop->fInNonClientArea = (BOOL16) + ( x < (pDropWnd->rectClient.left - pDropWnd->rectWindow.left) || + y < (pDropWnd->rectClient.top - pDropWnd->rectWindow.top) || + x > (pDropWnd->rectClient.right - pDropWnd->rectWindow.left) || + y > (pDropWnd->rectClient.bottom - pDropWnd->rectWindow.top) ); + p_drop = ((char*)lpDrop) + sizeof(DROPFILESTRUCT16); + } + } + + /* create message content */ + if (p_drop) { + p = p_data; + next = strchr(p, '\n'); + while (p) { + if (next) *next=0; + if (strncmp(p,"file:",5) == 0 ) { + INT32 len = GetShortPathName32A( p+5, p_drop, 65535 ); + if (len) { + TRACE(event, "drop file %s as %s\n", p+5, p_drop); + p_drop += len+1; + } else { + WARN(event, "can't convert file %s to dos name \n", p+5); + } + } else { + WARN(event, "unknown mime type %s\n", p); + } + if (next) { + *next = '\n'; + p = next + 1; + next = strchr(p, '\n'); + } else { + p = NULL; + } + *p_drop = '\0'; + } + + if (drop32) { + /* can not use PostMessage32A because it is currently based on + * PostMessage16 and WPARAM32 would be truncated to WPARAM16 + */ + GlobalUnlock32(hDrop.h32); + SendMessage32A( pWnd->hwndSelf, WM_DROPFILES, + (WPARAM32)hDrop.h32, 0L ); + } else { + GlobalUnlock16(hDrop.h16); + PostMessage16( pWnd->hwndSelf, WM_DROPFILES, + (WPARAM16)hDrop.h16, 0L ); + } + } + } + if( p_data ) TSXFree(p_data); + } +} + +/********************************************************************** + * EVENT_ClientMessage + */ +static void EVENT_ClientMessage( WND *pWnd, XClientMessageEvent *event ) +{ + if (event->message_type != None && event->format == 32) { + if ((event->message_type == wmProtocols) && + (((Atom) event->data.l[0]) == wmDeleteWindow)) + SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, 0 ); + else if ( event->message_type == dndProtocol && + (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) ) + EVENT_DropFromOffiX(pWnd, event); + else if ( event->message_type == dndProtocol && + event->data.l[0] == DndURL ) + EVENT_DropURLs(pWnd, event); + else { +#if 0 + /* enable this if you want to see the message */ + unsigned char* p_data = NULL; + union { + unsigned long l; + int i; + Atom atom; + } u; /* unused */ + TSXGetWindowProperty( display, DefaultRootWindow(display), + dndSelection, 0, 65535, FALSE, + AnyPropertyType, &u.atom, &u.i, + &u.l, &u.l, &p_data); + TRACE(event, "message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n", + event->message_type, event->data.l[0], event->data.l[1], + event->data.l[2], event->data.l[3], event->data.l[4], + p_data); +#endif + TRACE(event, "unrecognized ClientMessage\n" ); + } + } +} + +/********************************************************************** + * EVENT_EnterNotify + * + * Install colormap when Wine window is focused in + * self-managed mode with private colormap + */ +#if 0 +void EVENT_EnterNotify( WND *pWnd, XCrossingEvent *event ) +{ + if( !Options.managed && rootWindow == DefaultRootWindow(display) && + (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) && GetFocus32() ) + TSXInstallColormap( display, COLOR_GetColormap() ); +} +#endif + +/********************************************************************** + * EVENT_MapNotify + */ +void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event ) +{ + HWND32 hwndFocus = GetFocus32(); + + if (hwndFocus && IsChild32( hWnd, hwndFocus )) + X11DRV_WND_SetFocus( WIN_FindWndPtr( hwndFocus ) ); + + return; +} + +/********************************************************************** + * X11DRV_EVENT_Pending + */ +BOOL32 X11DRV_EVENT_Pending() +{ + return TSXPending(display); +} + +#endif /* !defined(X_DISPLAY_MISSING) */ + + + diff --git a/windows/x11drv/init.c b/windows/x11drv/init.c index 70a0822cd50..cdae2aad8b1 100644 --- a/windows/x11drv/init.c +++ b/windows/x11drv/init.c @@ -1,139 +1,70 @@ /* - * X11 windows driver + * X11 driver * - * Copyright 1993, 1994 Alexandre Julliard * Copyright 1998 Patrik Stridvall */ -#include -#include -#include "ts_xlib.h" -#include "color.h" -#include "display.h" -#include "dce.h" -#include "options.h" -#include "message.h" -#include "win.h" -#include "windows.h" -#include "x11drv.h" +#include "config.h" -static BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode); -static WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent); +#ifndef X_DISPLAY_MISSING + +#include "x11drv.h" WND_DRIVER X11DRV_WND_Driver = { - X11DRV_WND_CreateWindow, - X11DRV_WND_SetParent + X11DRV_WND_CreateDesktopWindow, + X11DRV_WND_CreateWindow, + X11DRV_WND_DestroyWindow, + X11DRV_WND_SetParent, + X11DRV_WND_ForceWindowRaise, + X11DRV_WND_SetWindowPos, + X11DRV_WND_SetText, + X11DRV_WND_SetFocus, + X11DRV_WND_PreSizeMove, + X11DRV_WND_PostSizeMove }; -extern Cursor DISPLAY_XCursor; /* Current X cursor */ - -/********************************************************************** - * X11DRV_WND_CreateWindow [Internal] - */ -static BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode) +CLIPBOARD_DRIVER X11DRV_CLIPBOARD_Driver = { - /* Create the X window (only for top-level windows, and then only */ - /* when there's no desktop window) */ - - if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display))) - { - XSetWindowAttributes win_attr; - - if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) || - (cs->dwExStyle & WS_EX_DLGMODALFRAME))) - { - win_attr.event_mask = ExposureMask | KeyPressMask | - KeyReleaseMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | - FocusChangeMask | StructureNotifyMask; - win_attr.override_redirect = FALSE; - wndPtr->flags |= WIN_MANAGED; - } - else - { - win_attr.event_mask = ExposureMask | KeyPressMask | - KeyReleaseMask | PointerMotionMask | - ButtonPressMask | ButtonReleaseMask | - FocusChangeMask; - win_attr.override_redirect = TRUE; - } - win_attr.colormap = COLOR_GetColormap(); - win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful; - win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0); - win_attr.cursor = DISPLAY_XCursor; - wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y, - cs->cx, cs->cy, 0, CopyFromParent, - InputOutput, CopyFromParent, - CWEventMask | CWOverrideRedirect | - CWColormap | CWCursor | CWSaveUnder | - CWBackingStore, &win_attr ); + X11DRV_CLIPBOARD_EmptyClipboard, + X11DRV_CLIPBOARD_SetClipboardData, + X11DRV_CLIPBOARD_RequestSelection, + X11DRV_CLIPBOARD_ResetOwner +}; - if ((wndPtr->flags & WIN_MANAGED) && - (cs->dwExStyle & WS_EX_DLGMODALFRAME)) - { - XSizeHints* size_hints = TSXAllocSizeHints(); - - if (size_hints) - { - size_hints->min_width = size_hints->max_width = cs->cx; - size_hints->min_height = size_hints->max_height = cs->cy; - size_hints->flags = (PSize | PMinSize | PMaxSize); - TSXSetWMSizeHints( display, wndPtr->window, size_hints, - XA_WM_NORMAL_HINTS ); - TSXFree(size_hints); - } - } - - if (cs->hwndParent) /* Get window owner */ - { - Window win = WIN_GetXWindow( cs->hwndParent ); - if (win) TSXSetTransientForHint( display, wndPtr->window, win ); - } - EVENT_RegisterWindow( wndPtr ); - } - return TRUE; -} - -/***************************************************************** - * X11DRV_WND_SetParent [Internal] - */ -static WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent) +KEYBOARD_DRIVER X11DRV_KEYBOARD_Driver = { - if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) ) - { - WND* pWndPrev = wndPtr->parent; + X11DRV_KEYBOARD_Init, + X11DRV_KEYBOARD_VkKeyScan, + X11DRV_KEYBOARD_MapVirtualKey, + X11DRV_KEYBOARD_GetKeyNameText, + X11DRV_KEYBOARD_ToAscii +}; + +EVENT_DRIVER X11DRV_EVENT_Driver = +{ + X11DRV_EVENT_Init, + X11DRV_EVENT_AddIO, + X11DRV_EVENT_DeleteIO, + X11DRV_EVENT_WaitNetEvent, + X11DRV_EVENT_Synchronize, + X11DRV_EVENT_CheckFocus, + X11DRV_EVENT_QueryPointer, + X11DRV_EVENT_DummyMotionNotify, + X11DRV_EVENT_Pending, + X11DRV_EVENT_IsUserIdle +}; + +#if 0 +MOUSE_DRIVER X11DRV_MOUSE_Driver = +{ +}; +#endif + +#endif /* !defined(X_DISPLAY_MISSING) */ - if( pWndParent != pWndPrev ) - { - BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf); - if ( wndPtr->window ) - { - /* Toplevel window needs to be reparented. Used by Tk 8.0 */ - TSXDestroyWindow( display, wndPtr->window ); - wndPtr->window = None; - } - else if( bFixupDCE ) - DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow ); - WIN_UnlinkWindow(wndPtr->hwndSelf); - wndPtr->parent = pWndParent; - /* FIXME: Create an X counterpart for reparented top-level windows - * when not in the desktop mode. */ - - if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD; - WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM); - if( bFixupDCE ) - { - DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow ); - UpdateWindow32(wndPtr->hwndSelf); - } - } - return pWndPrev; - } /* failure */ - return 0; -} diff --git a/windows/x11drv/keyboard.c b/windows/x11drv/keyboard.c new file mode 100644 index 00000000000..a28a1077560 --- /dev/null +++ b/windows/x11drv/keyboard.c @@ -0,0 +1,815 @@ +/* + * X11 windows driver + * + * Copyright 1993 Bob Amstadt + * Copyright 1996 Albrecht Kleine + * Copyright 1997 David Faure + * Copyright 1998 Morten Welinder + * Copyright 1998 Ulrich Weigand + */ + +#include "config.h" + +#ifndef X_DISPLAY_MISSING + +#include +#include +#include "ts_xlib.h" +#include "ts_xresource.h" +#include "ts_xutil.h" + +#include "debug.h" +#include "message.h" +#include "wintypes.h" +#include "x11drv.h" + +extern LPBYTE pKeyStateTable; + +int min_keycode, max_keycode, keysyms_per_keycode; +WORD keyc2vkey[256]; + +static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */ +static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */ + +/* Keyboard translation tables */ +static const int special_key[] = +{ + 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 int cursor_key[] = +{ + VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, + VK_NEXT, VK_END /* FF50 */ +}; + +static const int misc_key[] = +{ + VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */ + VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU /* FF68 */ +}; + +static const int keypad_key[] = +{ + 0, VK_NUMLOCK, /* FF7E */ + 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 int function_key[] = +{ + VK_F1, VK_F2, /* FFBE */ + 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 int modifier_key[] = +{ + VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */ + VK_MENU, VK_MENU, VK_MENU, VK_MENU /* FFE7 */ +}; + +/* Returns the Windows virtual key code associated with the X event */ +static WORD EVENT_event_to_vkey( XKeyEvent *e) +{ + KeySym keysym; + + TSXLookupString(e, NULL, 0, &keysym, NULL); + + if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (e->state & NumLockMask)) + /* Only the Keypad keys 0-9 and . send different keysyms + * depending on the NumLock state */ + return keypad_key[(keysym & 0xFF) - 0x7E]; + + return keyc2vkey[e->keycode]; +} + +static BOOL32 NumState=FALSE, CapsState=FALSE; + +/********************************************************************** + * KEYBOARD_GenerateMsg + * + * Generate Down+Up messages when NumLock or CapsLock is pressed. + * + * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL + * + */ +void KEYBOARD_GenerateMsg( WORD vkey, int Evtype, INT32 event_x, INT32 event_y, + DWORD event_time ) +{ + BOOL32 * State = (vkey==VK_NUMLOCK? &NumState : &CapsState); + + if (*State) { + /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes, + don't treat it. It's from the same key press. Then the state goes to ON. + And from there, a 'release' event will switch off the toggle key. */ + *State=FALSE; + TRACE(keyboard,"INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]); + } else + { + if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */ + { + if (Evtype!=KeyPress) + { + TRACE(keyboard,"ON + KeyRelease => generating DOWN and UP messages.\n"); + KEYBOARD_SendEvent( vkey, 0, 0, + event_x, event_y, event_time ); + KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, + event_x, event_y, event_time ); + *State=FALSE; + pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */ + } + } + else /* it was OFF */ + if (Evtype==KeyPress) + { + TRACE(keyboard,"OFF + Keypress => generating DOWN and UP messages.\n"); + KEYBOARD_SendEvent( vkey, 0, 0, + event_x, event_y, event_time ); + KEYBOARD_SendEvent( vkey, 0, KEYEVENTF_KEYUP, + event_x, event_y, event_time ); + *State=TRUE; /* Goes to intermediary state before going to ON */ + pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */ + } + } +} + +/*********************************************************************** + * KEYBOARD_UpdateOneState + * + * Updates internal state for , depending on key under X + * + */ +void KEYBOARD_UpdateOneState ( int vkey, int state ) +{ + /* Do something if internal table state != X state for keycode */ + if (((pKeyStateTable[vkey] & 0x80)!=0) != state) + { + TRACE(keyboard,"Adjusting state for vkey %#.2x. State before %#.2x \n", + vkey, pKeyStateTable[vkey]); + + /* Fake key being pressed inside wine */ + KEYBOARD_SendEvent( vkey, 0, state? 0 : KEYEVENTF_KEYUP, + 0, 0, GetTickCount() ); + + TRACE(keyboard,"State after %#.2x \n",pKeyStateTable[vkey]); + } +} + +/*********************************************************************** + * KEYBOARD_UpdateState + * + * Update modifiers state (Ctrl, Alt, Shift) + * when window is activated (called by EVENT_FocusIn in event.c) + * + * 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) + */ +void KEYBOARD_UpdateState ( void ) +{ +/* extract a bit from the char[32] bit suite */ +#define KeyState(keycode) ((keys_return[keycode/8] & (1<<(keycode%8)))!=0) + + char keys_return[32]; + + TRACE(keyboard,"called\n"); + if (!TSXQueryKeymap(display, keys_return)) { + ERR(keyboard,"Error getting keymap !"); + return; + } + + /* 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_HandleEvent + * + * Handle a X key event + */ +void KEYBOARD_HandleEvent( WND *pWnd, XKeyEvent *event ) +{ + char Str[24]; + XComposeStatus cs; + KeySym keysym; + WORD vkey = 0, bScan; + DWORD dwFlags; + static BOOL32 force_extended = FALSE; /* hack for AltGr translation */ + + int ascii_chars; + + INT32 event_x = (pWnd? pWnd->rectWindow.left : 0) + event->x; + INT32 event_y = (pWnd? pWnd->rectWindow.top : 0) + event->y; + DWORD event_time = event->time - MSG_WineStartTicks; + + /* this allows support for dead keys */ + if ((event->keycode >> 8) == 0x10) + event->keycode=(event->keycode & 0xff); + + ascii_chars = TSXLookupString(event, Str, 1, &keysym, &cs); + + TRACE(key, "EVENT_key : state = %X\n", event->state); + if (keysym == XK_Mode_switch) + { + TRACE(key, "Alt Gr key event received\n"); + event->keycode = kcControl; /* Simulate Control */ + KEYBOARD_HandleEvent( pWnd, event ); + + event->keycode = kcAlt; /* Simulate Alt */ + force_extended = TRUE; + KEYBOARD_HandleEvent( pWnd, event ); + force_extended = FALSE; + return; + } + + Str[ascii_chars] = '\0'; + if (TRACE_ON(key)){ + char *ksname; + + ksname = TSXKeysymToString(keysym); + if (!ksname) + ksname = "No Name"; + TRACE(key, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", + (event->type == KeyPress) ? "KeyPress" : "KeyRelease", + keysym, ksname, ascii_chars, Str[0] & 0xff, Str); + } + + vkey = EVENT_event_to_vkey(event); + if (force_extended) vkey |= 0x100; + + TRACE(key, "keycode 0x%x converted to vkey 0x%x\n", + event->keycode, vkey); + + if (vkey) + { + switch (vkey & 0xff) + { + case VK_NUMLOCK: + KEYBOARD_GenerateMsg( VK_NUMLOCK, event->type, event_x, event_y, + event_time ); + break; + case VK_CAPITAL: + TRACE(keyboard,"Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]); + KEYBOARD_GenerateMsg( VK_CAPITAL, event->type, event_x, event_y, + event_time ); + TRACE(keyboard,"State after : %#.2x\n",pKeyStateTable[vkey]); + break; + default: + /* Adjust the NUMLOCK state if it has been changed outside wine */ + if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask)) + { + TRACE(keyboard,"Adjusting NumLock state. \n"); + KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyPress, event_x, event_y, + event_time ); + KEYBOARD_GenerateMsg( VK_NUMLOCK, KeyRelease, event_x, event_y, + event_time ); + } + /* Adjust the CAPSLOCK state if it has been changed outside wine */ + if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask)) + { + TRACE(keyboard,"Adjusting Caps Lock state.\n"); + KEYBOARD_GenerateMsg( VK_CAPITAL, KeyPress, event_x, event_y, + event_time ); + KEYBOARD_GenerateMsg( VK_CAPITAL, KeyRelease, event_x, event_y, + event_time ); + } + /* Not Num nor Caps : end of intermediary states for both. */ + NumState = FALSE; + CapsState = FALSE; + + bScan = event->keycode - min_keycode; /* Windows starts from 0, X from + min_keycode (8 usually) */ + dwFlags = 0; + if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP; + if ( vkey & 0x100 ) dwFlags |= KEYEVENTF_EXTENDEDKEY; + if ( force_extended ) dwFlags |= KEYEVENTF_WINE_FORCEEXTENDED; + + KEYBOARD_SendEvent( vkey & 0xff, bScan, dwFlags, + event_x, event_y, event_time ); + } + } +} + +/********************************************************************** + * X11DRV_KEYBOARD_Init + */ +void X11DRV_KEYBOARD_Init(void) +{ + int i; + KeySym *ksp; + XModifierKeymap *mmp; + KeySym keysym; + KeyCode *kcp; + XKeyEvent e2; + WORD vkey, OEMvkey; + int keyc; + + TSXDisplayKeycodes(display, &min_keycode, &max_keycode); + ksp = TSXGetKeyboardMapping(display, min_keycode, + max_keycode + 1 - min_keycode, &keysyms_per_keycode); + /* We are only interested in keysyms_per_keycode. + There is no need to hold a local copy of the keysyms table */ + TSXFree(ksp); + mmp = TSXGetModifierMapping(display); + kcp = mmp->modifiermap; + for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */ + { + int j; + + for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1) + if (*kcp) + { + int k; + + for (k = 0; k < keysyms_per_keycode; k += 1) + if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Mode_switch) + { + AltGrMask = 1 << i; + TRACE(key, "AltGrMask is %x\n", AltGrMask); + } + else if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock) + { + NumLockMask = 1 << i; + TRACE(key, "NumLockMask is %x\n", NumLockMask); + } + } + } + TSXFreeModifiermap(mmp); + + /* Now build two conversion arrays : + * keycode -> vkey + extended + * vkey + extended -> keycode */ + + e2.display = display; + e2.state = 0; + + OEMvkey = VK_OEM_7; /* next is available. */ + for (keyc = min_keycode; keyc <= max_keycode; keyc++) + { + e2.keycode = (KeyCode)keyc; + TSXLookupString(&e2, NULL, 0, &keysym, NULL); + vkey = 0; + if (keysym) /* otherwise, keycode not used */ + { + if ((keysym >> 8) == 0xFF) /* non-character key */ + { + int key = keysym & 0xff; + + if (key >= 0x08 && key <= 0x1B) /* special key */ + vkey = special_key[key - 0x08]; + else if (key >= 0x50 && key <= 0x57) /* cursor key */ + vkey = cursor_key[key - 0x50]; + else if (key >= 0x60 && key <= 0x6B) /* miscellaneous key */ + vkey = misc_key[key - 0x60]; + else if (key >= 0x7E && key <= 0xB9) /* keypad key */ + vkey = keypad_key[key - 0x7E]; + else if (key >= 0xBE && key <= 0xCD) /* function key */ + { + vkey = function_key[key - 0xBE]; + vkey |= 0x100; /* set extended bit */ + } + else if (key >= 0xE1 && key <= 0xEA) /* modifier key */ + vkey = modifier_key[key - 0xE1]; + else if (key == 0xFF) /* DEL key */ + vkey = VK_DELETE; + /* extended must also be set for ALT_R, CTRL_R, + INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys, + keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */ + /* FIXME should we set extended bit for NumLock ? My + * Windows does ... DF */ + switch (keysym) + { + case XK_Control_R : + case XK_Alt_R : + case XK_Insert : + case XK_Delete : + case XK_Home : + case XK_End : + case XK_Prior : + case XK_Next : + case XK_Left : + case XK_Up : + case XK_Right : + case XK_Down : + case XK_KP_Divide : + case XK_KP_Enter : + vkey |= 0x100; + } + } + for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++) + { + keysym = TSXLookupKeysym(&e2, i); + if ((keysym >= VK_0 && keysym <= VK_9) + || (keysym >= VK_A && keysym <= VK_Z) + || keysym == VK_SPACE) + vkey = keysym; + } + + for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++) + { + keysym = TSXLookupKeysym(&e2, i); + switch (keysym) + { + case ';': vkey = VK_OEM_1; break; + case '/': vkey = VK_OEM_2; break; + case '`': vkey = VK_OEM_3; break; + case '[': vkey = VK_OEM_4; break; + case '\\': vkey = VK_OEM_5; break; + case ']': vkey = VK_OEM_6; break; + case '\'': vkey = VK_OEM_7; break; + case ',': vkey = VK_OEM_COMMA; break; + case '.': vkey = VK_OEM_PERIOD; break; + case '-': vkey = VK_OEM_MINUS; break; + case '+': vkey = VK_OEM_PLUS; break; + } + } + + if (!vkey) + { + /* Others keys: let's assign OEM virtual key codes in the allowed range, + * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */ + switch (++OEMvkey) + { + case 0xc1 : OEMvkey=0xdb; break; + case 0xe5 : OEMvkey=0xe9; break; + case 0xf6 : OEMvkey=0xf5; WARN(keyboard,"No more OEM vkey available!\n"); + } + + vkey = OEMvkey; + + if (TRACE_ON(keyboard)) + { + dbg_decl_str(keyboard, 1024); + + TRACE(keyboard, "OEM specific virtual key %X assigned " + "to keycode %X:\n", OEMvkey, e2.keycode); + for (i = 0; i < keysyms_per_keycode; i += 1) + { + char *ksname; + + keysym = TSXLookupKeysym(&e2, i); + ksname = TSXKeysymToString(keysym); + if (!ksname) + ksname = "NoSymbol"; + dsprintf(keyboard, "%lX (%s) ", keysym, ksname); + } + TRACE(keyboard, "(%s)\n", dbg_str(keyboard)); + } + } + } + keyc2vkey[e2.keycode] = vkey; + } /* for */ + /* Now store one keycode for each modifier. Used to simulate keypresses. */ + kcControl = TSXKeysymToKeycode(display, XK_Control_L); + kcAlt = TSXKeysymToKeycode(display, XK_Alt_L); + if (!kcAlt) kcAlt = TSXKeysymToKeycode(display, XK_Meta_L); + kcShift = TSXKeysymToKeycode(display, XK_Shift_L); + kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock); + kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock); +} + +/*********************************************************************** + * X11DRV_KEYBOARD_VkKeyScan + */ +WORD X11DRV_KEYBOARD_VkKeyScan(CHAR cChar) +{ + KeyCode keycode; + KeySym keysym; + int i,index; + int highbyte=0; + + /* char->keysym (same for ANSI chars) */ + keysym=(unsigned char) cChar;/* (!) cChar is signed */ + if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/ + + keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */ + if (!keycode) + { /* It didn't work ... let's try with deadchar code. */ + keycode = TSXKeysymToKeycode(display, keysym | 0xFE00); + } + + TRACE(keyboard,"VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n", + cChar,keysym,keysym,keycode); + + if (keycode) + { + for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */ + if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i; + switch (index) { + case -1 : + WARN(keyboard,"Keysym %lx not found while parsing the keycode table\n",keysym); break; + case 0 : break; + case 1 : highbyte = 0x0100; break; + case 2 : highbyte = 0X0600; break; + default : ERR(keyboard,"index %d found by XKeycodeToKeysym. please report! \n",index); + } + /* + index : 0 adds 0x0000 + index : 1 adds 0x0100 (shift) + index : ? adds 0x0200 (ctrl) + index : 2 adds 0x0600 (ctrl+alt) + index : ? adds 0x0700 (ctrl+alt+shift (used?)) + */ + } + TRACE(keyboard," ... returning %#.2x\n", keyc2vkey[keycode]+highbyte); + return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */ +} + +/*********************************************************************** + * X11DRV_KEYBOARD_MapVirtualKey + */ +UINT16 X11DRV_KEYBOARD_MapVirtualKey(UINT16 wCode, UINT16 wMapType) +{ +#define returnMVK(value) { TRACE(keyboard,"returning 0x%x.\n",value); return value; } + + TRACE(keyboard,"MapVirtualKey wCode=0x%x wMapType=%d ... \n", + wCode,wMapType); + switch(wMapType) { + case 0: { /* vkey-code to scan-code */ + /* let's do vkey -> keycode -> scan */ + int keyc; + for (keyc=min_keycode; keyc<=max_keycode; keyc++) + if ((keyc2vkey[keyc] & 0xFF) == wCode) + returnMVK (keyc - min_keycode); + return 0; } + + case 1: /* scan-code to vkey-code */ + /* let's do scan -> keycode -> vkey */ + + returnMVK (keyc2vkey[(wCode & 0xFF) + min_keycode]); + + case 2: { /* vkey-code to unshifted ANSI code */ + /* (was FIXME) : what does unshifted mean ? 'a' or 'A' ? */ + /* My Windows returns 'A'. */ + /* let's do vkey -> keycode -> (XLookupString) ansi char */ + XKeyEvent e; + KeySym keysym; + char s[2]; + e.display = display; + e.state = 0; /* unshifted */ + e.keycode = MapVirtualKey16( wCode, 0); + if (!TSXLookupString(&e, s , 2 , &keysym, NULL)) + returnMVK (*s); + + return 0; + } + default: /* reserved */ + WARN(keyboard, "Unknown wMapType %d !\n", + wMapType); + return 0; + } + return 0; +} + +/*********************************************************************** + * X11DRV_KEYBOARD_GetKeyNameText + */ +INT16 X11DRV_KEYBOARD_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT16 nSize) +{ +#if 0 + int i; +#endif + + FIXME(keyboard,"(%ld,,%d): stub\n",lParam,nSize); + +#if 0 + lParam >>= 16; + lParam &= 0xff; + + for (i = 0 ; i != KeyTableSize ; i++) + if (KeyTable[i].scancode == lParam) { + lstrcpyn32A( lpBuffer, KeyTable[i].name, nSize ); + return strlen(lpBuffer); + } +#endif + + *lpBuffer = 0; + return 0; +} + +/*********************************************************************** + * X11DRV_KEYBOARD_ToAscii + * + * The ToAscii function translates the specified virtual-key code and keyboard + * state to the corresponding Windows character or characters. + * + * If the specified key is a dead key, the return value is negative. Otherwise, + * it is one of the following values: + * Value Meaning + * 0 The specified virtual key has no translation for the current state of the keyboard. + * 1 One Windows character was copied to the buffer. + * 2 Two characters were copied to the buffer. This usually happens when a + * dead-key character (accent or diacritic) stored in the keyboard layout cannot + * be composed with the specified virtual key to form a single character. + * + * FIXME : should do the above (return 2 for non matching deadchar+char combinations) + * + */ +INT16 X11DRV_KEYBOARD_ToAscii( + UINT16 virtKey,UINT16 scanCode, LPBYTE lpKeyState, + LPVOID lpChar, UINT16 flags) +{ + XKeyEvent e; + KeySym keysym; + static XComposeStatus cs; + INT32 ret; + int keyc; + + if (scanCode==0) { + /* This happens when doing Alt+letter : a fake 'down arrow' key press + event is generated by windows. Just ignore it. */ + TRACE(keyboard,"scanCode=0, doing nothing\n"); + return 0; + } + e.display = display; + e.keycode = 0; + e.state = 0; + if (lpKeyState[VK_SHIFT] & 0x80) + e.state |= ShiftMask; + if (lpKeyState[VK_CAPITAL] & 0x01) + e.state |= LockMask; + if (lpKeyState[VK_CONTROL] & 0x80) + { + if (lpKeyState[VK_MENU] & 0x80) + e.state |= AltGrMask; + else + e.state |= ControlMask; + } + if (lpKeyState[VK_NUMLOCK] & 0x01) + e.state |= NumLockMask; + TRACE(key, "(%04X, %04X) : faked state = %X\n", + virtKey, scanCode, e.state); + /* We exit on the first keycode found, to speed up the thing. */ + for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++) + { /* Find a keycode that could have generated this virtual key */ + if ((keyc2vkey[keyc] & 0xFF) == virtKey) + { /* We filter the extended bit, we don't know it */ + e.keycode = keyc; /* Store it temporarily */ + if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) { + e.keycode = 0; /* Wrong one (ex: because of the NumLock + state), so set it to 0, we'll find another one */ + } + } + } + + if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9)) + e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0); + + if (virtKey==VK_DECIMAL) + e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal); + + if (!e.keycode) + { + WARN(keyboard,"Unknown virtual key %X !!! \n",virtKey); + return virtKey; /* whatever */ + } + else TRACE(keyboard,"Found keycode %d (0x%2X)\n",e.keycode,e.keycode); + + ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, &cs); + if (ret == 0) + { + BYTE dead_char = 0; + + ((char*)lpChar)[1] = '\0'; + switch (keysym) + { + /* symbolic ASCII is the same as defined in rfc1345 */ +#ifdef XK_dead_tilde + case XK_dead_tilde : +#endif + case 0x1000FE7E : /* Xfree's XK_Dtilde */ + dead_char = '~'; /* '? */ + break; +#ifdef XK_dead_acute + case XK_dead_acute : +#endif + case 0x1000FE27 : /* Xfree's XK_Dacute_accent */ + dead_char = 0xb4; /* '' */ + break; +#ifdef XK_dead_circumflex + case XK_dead_circumflex : +#endif + case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */ + dead_char = '^'; /* '> */ + break; +#ifdef XK_dead_grave + case XK_dead_grave : +#endif + case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */ + dead_char = '`'; /* '! */ + break; +#ifdef XK_dead_diaeresis + case XK_dead_diaeresis : +#endif + case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */ + dead_char = 0xa8; /* ': */ + break; +#ifdef XK_dead_cedilla + case XK_dead_cedilla : + dead_char = 0xb8; /* ', */ + break; +#endif +#ifdef XK_dead_macron + case XK_dead_macron : + dead_char = '-'; /* 'm isn't defined on iso-8859-x */ + break; +#endif +#ifdef XK_dead_breve + case XK_dead_breve : + dead_char = 0xa2; /* '( */ + break; +#endif +#ifdef XK_dead_abovedot + case XK_dead_abovedot : + dead_char = 0xff; /* '. */ + break; +#endif +#ifdef XK_dead_abovering + case XK_dead_abovering : + dead_char = '0'; /* '0 isn't defined on iso-8859-x */ + break; +#endif +#ifdef XK_dead_doubleacute + case XK_dead_doubleacute : + dead_char = 0xbd; /* '" */ + break; +#endif +#ifdef XK_dead_caron + case XK_dead_caron : + dead_char = 0xb7; /* '< */ + break; +#endif +#ifdef XK_dead_ogonek + case XK_dead_ogonek : + dead_char = 0xb2; /* '; */ + break; +#endif +/* FIXME: I don't know this three. + case XK_dead_iota : + dead_char = 'i'; + break; + case XK_dead_voiced_sound : + dead_char = 'v'; + break; + case XK_dead_semivoiced_sound : + dead_char = 's'; + break; +*/ + } + if (dead_char) + { + *(char*)lpChar = dead_char; + ret = -1; + } + else + { + char *ksname; + + ksname = TSXKeysymToString(keysym); + if (!ksname) + ksname = "No Name"; + if ((keysym >> 8) != 0xff) + { + ERR(keyboard, "Please report: no char for keysym %04lX (%s) :\n", + keysym, ksname); + ERR(keyboard, "(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n", + virtKey, scanCode, e.keycode, e.state); + } + } + } + else { /* ret = 1 */ + /* We have a special case to handle : Shift + arrow, shift + home, ... + X returns a char for it, but Windows doesn't. Let's eat it. */ + if (!(lpKeyState[VK_NUMLOCK] & 0x01) /* NumLock is off */ + && (lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */ + && (keysym>=XK_KP_0) && (keysym<=XK_KP_9)) + { + *(char*)lpChar = 0; + ret = 0; + } + } + + TRACE(key, "ToAscii about to return %d with char %x\n", + ret, *(char*)lpChar); + return ret; +} + +#endif /* !defined(X_DISPLAY_MISSING) */ + + diff --git a/windows/x11drv/mouse.c b/windows/x11drv/mouse.c new file mode 100644 index 00000000000..ed87b981f1e --- /dev/null +++ b/windows/x11drv/mouse.c @@ -0,0 +1,13 @@ +/* + * X11 windows driver + * + * Copyright 1998 Patrik Stridvall + */ + +#include "config.h" + +#ifndef X_DISPLAY_MISSING + +#include "x11drv.h" + +#endif /* !defined(X_DISPLAY_MISSING) */ diff --git a/windows/x11drv/wnd.c b/windows/x11drv/wnd.c new file mode 100644 index 00000000000..019886aacd1 --- /dev/null +++ b/windows/x11drv/wnd.c @@ -0,0 +1,431 @@ +/* + * X11 windows driver + * + * Copyright 1993, 1994, 1995, 1996 Alexandre Julliard + * 1993 David Metcalfe + * 1995, 1996 Alex Korobka + */ + +#include "config.h" + +#ifndef X_DISPLAY_MISSING + +#include +#include "ts_xlib.h" +#include "ts_xutil.h" + +#include +#include +#include "color.h" +#include "display.h" +#include "dce.h" +#include "options.h" +#include "message.h" +#include "win.h" +#include "windows.h" +#include "x11drv.h" + +/**********************************************************************/ + +extern Cursor DISPLAY_XCursor; /* Current X cursor */ + +/**********************************************************************/ + +/* X context to associate a hwnd to an X window */ +XContext winContext = 0; + +Atom wmProtocols = None; +Atom wmDeleteWindow = None; +Atom dndProtocol = None; +Atom dndSelection = None; + +/*********************************************************************** + * X11DRV_WND_GetXWindow + * + * Return the X window associated to a window. + */ +Window X11DRV_WND_GetXWindow(HWND32 hwnd) +{ + WND *wndPtr = WIN_FindWndPtr( hwnd ); + while (wndPtr && !wndPtr->window) wndPtr = wndPtr->parent; + return wndPtr ? wndPtr->window : 0; +} + +/*********************************************************************** + * X11DRV_WND_RegisterWindow + * + * Associate an X window to a HWND. + */ +static void X11DRV_WND_RegisterWindow(WND *pWnd) +{ + TSXSetWMProtocols( display, pWnd->window, &wmDeleteWindow, 1 ); + + if (!winContext) winContext = TSXUniqueContext(); + TSXSaveContext( display, pWnd->window, winContext, (char *)pWnd ); +} + +/********************************************************************** + * X11DRV_WND_CreateDesktopWindow + */ +BOOL32 X11DRV_WND_CreateDesktopWindow(WND *wndPtr, CLASS *classPtr, BOOL32 bUnicode) +{ + if (wmProtocols == None) + wmProtocols = TSXInternAtom( display, "WM_PROTOCOLS", True ); + if (wmDeleteWindow == None) + wmDeleteWindow = TSXInternAtom( display, "WM_DELETE_WINDOW", True ); + if( dndProtocol == None ) + dndProtocol = TSXInternAtom( display, "DndProtocol" , False ); + if( dndSelection == None ) + dndSelection = TSXInternAtom( display, "DndSelection" , False ); + + wndPtr->window = rootWindow; + wndPtr->expose_event = NULL; + X11DRV_WND_RegisterWindow( wndPtr ); + + return TRUE; +} + +/********************************************************************** + * X11DRV_WND_CreateWindow + */ +BOOL32 X11DRV_WND_CreateWindow(WND *wndPtr, CLASS *classPtr, CREATESTRUCT32A *cs, BOOL32 bUnicode) +{ + /* Create the X window (only for top-level windows, and then only */ + /* when there's no desktop window) */ + + if (!(cs->style & WS_CHILD) && (rootWindow == DefaultRootWindow(display))) + { + XSetWindowAttributes win_attr; + + if (Options.managed && ((cs->style & (WS_DLGFRAME | WS_THICKFRAME)) || + (cs->dwExStyle & WS_EX_DLGMODALFRAME))) + { + win_attr.event_mask = ExposureMask | KeyPressMask | + KeyReleaseMask | PointerMotionMask | + ButtonPressMask | ButtonReleaseMask | + FocusChangeMask | StructureNotifyMask; + win_attr.override_redirect = FALSE; + wndPtr->flags |= WIN_MANAGED; + } + else + { + win_attr.event_mask = ExposureMask | KeyPressMask | + KeyReleaseMask | PointerMotionMask | + ButtonPressMask | ButtonReleaseMask | + FocusChangeMask; + win_attr.override_redirect = TRUE; + } + win_attr.colormap = COLOR_GetColormap(); + win_attr.backing_store = Options.backingstore ? WhenMapped : NotUseful; + win_attr.save_under = ((classPtr->style & CS_SAVEBITS) != 0); + win_attr.cursor = DISPLAY_XCursor; + wndPtr->window = TSXCreateWindow( display, rootWindow, cs->x, cs->y, + cs->cx, cs->cy, 0, CopyFromParent, + InputOutput, CopyFromParent, + CWEventMask | CWOverrideRedirect | + CWColormap | CWCursor | CWSaveUnder | + CWBackingStore, &win_attr ); + + if(!wndPtr->window) + return FALSE; + + if ((wndPtr->flags & WIN_MANAGED) && + (cs->dwExStyle & WS_EX_DLGMODALFRAME)) + { + XSizeHints* size_hints = TSXAllocSizeHints(); + + if (size_hints) + { + size_hints->min_width = size_hints->max_width = cs->cx; + size_hints->min_height = size_hints->max_height = cs->cy; + size_hints->flags = (PSize | PMinSize | PMaxSize); + TSXSetWMSizeHints( display, wndPtr->window, size_hints, + XA_WM_NORMAL_HINTS ); + TSXFree(size_hints); + } + } + + if (cs->hwndParent) /* Get window owner */ + { + Window win = X11DRV_WND_GetXWindow( cs->hwndParent ); + if (win) TSXSetTransientForHint( display, wndPtr->window, win ); + } + X11DRV_WND_RegisterWindow( wndPtr ); + } + return TRUE; +} + +/*********************************************************************** + * X11DRV_WND_DestroyWindow + */ +BOOL32 X11DRV_WND_DestroyWindow(WND *pWnd) +{ + if (pWnd->expose_event) + { + free( pWnd->expose_event ); + pWnd->expose_event = NULL; + } + + if (pWnd->window) + { + XEvent xe; + TSXDeleteContext( display, pWnd->window, winContext ); + TSXDestroyWindow( display, pWnd->window ); + while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) ); + pWnd->window = None; + } + + return TRUE; +} + +/***************************************************************** + * X11DRV_WND_SetParent + */ +WND *X11DRV_WND_SetParent(WND *wndPtr, WND *pWndParent) +{ + if( wndPtr && pWndParent && (wndPtr != WIN_GetDesktop()) ) + { + WND* pWndPrev = wndPtr->parent; + + if( pWndParent != pWndPrev ) + { + BOOL32 bFixupDCE = IsWindowVisible32(wndPtr->hwndSelf); + + if ( wndPtr->window ) + { + /* Toplevel window needs to be reparented. Used by Tk 8.0 */ + + TSXDestroyWindow( display, wndPtr->window ); + wndPtr->window = None; + } + else if( bFixupDCE ) + DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow ); + + WIN_UnlinkWindow(wndPtr->hwndSelf); + wndPtr->parent = pWndParent; + + /* FIXME: Create an X counterpart for reparented top-level windows + * when not in the desktop mode. */ + + if ( pWndParent != WIN_GetDesktop() ) wndPtr->dwStyle |= WS_CHILD; + WIN_LinkWindow(wndPtr->hwndSelf, HWND_BOTTOM); + + if( bFixupDCE ) + { + DCE_InvalidateDCE( wndPtr, &wndPtr->rectWindow ); + UpdateWindow32(wndPtr->hwndSelf); + } + } + return pWndPrev; + } /* failure */ + return 0; +} + +/*********************************************************************** + * X11DRV_WND_ForceWindowRaise + * + * Raise a window on top of the X stacking order, while preserving + * the correct Windows Z order. + */ +void X11DRV_WND_ForceWindowRaise(WND *pWnd) +{ + XWindowChanges winChanges; + WND *wndPrev; + + if( !pWnd || !pWnd->window || (pWnd->flags & WIN_MANAGED) ) + return; + + /* Raise all windows up to pWnd according to their Z order. + * (it would be easier with sibling-related Below but it doesn't + * work very well with SGI mwm for instance) + */ + winChanges.stack_mode = Above; + while (pWnd) + { + if (pWnd->window) TSXReconfigureWMWindow( display, pWnd->window, 0, + CWStackMode, &winChanges ); + wndPrev = WIN_GetDesktop()->child; + if (wndPrev == pWnd) break; + while (wndPrev && (wndPrev->next != pWnd)) wndPrev = wndPrev->next; + pWnd = wndPrev; + } +} + +/*********************************************************************** + * X11DRV_WND_FindDesktopXWindow [Internal] + * + * Find the actual X window which needs be restacked. + * Used by X11DRV_SetWindowPos(). + */ +static Window X11DRV_WND_FindDesktopXWindow( WND *wndPtr ) +{ + if (!(wndPtr->flags & WIN_MANAGED)) + return wndPtr->window; + else + { + Window window, root, parent, *children; + int nchildren; + window = wndPtr->window; + for (;;) + { + TSXQueryTree( display, window, &root, &parent, + &children, &nchildren ); + TSXFree( children ); + if (parent == root) + return window; + window = parent; + } + } +} + +/*********************************************************************** + * WINPOS_SetXWindowPos + * + * SetWindowPos() for an X window. Used by the real SetWindowPos(). + */ +void X11DRV_WND_SetWindowPos(WND *wndPtr, const WINDOWPOS32 *winpos, BOOL32 bSMC_SETXPOS) +{ + XWindowChanges winChanges; + int changeMask = 0; + WND *winposPtr = WIN_FindWndPtr( winpos->hwnd ); + + if (!(winpos->flags & SWP_SHOWWINDOW) && (winpos->flags & SWP_HIDEWINDOW)) + { + if(wndPtr && wndPtr->window) TSXUnmapWindow( display, wndPtr->window ); + } + + if(bSMC_SETXPOS) + { + if ( !(winpos->flags & SWP_NOSIZE)) + { + winChanges.width = winpos->cx; + winChanges.height = winpos->cy; + changeMask |= CWWidth | CWHeight; + + /* Tweak dialog window size hints */ + + if ((winposPtr->flags & WIN_MANAGED) && + (winposPtr->dwExStyle & WS_EX_DLGMODALFRAME)) + { + XSizeHints *size_hints = TSXAllocSizeHints(); + + if (size_hints) + { + long supplied_return; + + TSXGetWMSizeHints( display, winposPtr->window, size_hints, + &supplied_return, XA_WM_NORMAL_HINTS); + size_hints->min_width = size_hints->max_width = winpos->cx; + size_hints->min_height = size_hints->max_height = winpos->cy; + TSXSetWMSizeHints( display, winposPtr->window, size_hints, + XA_WM_NORMAL_HINTS ); + TSXFree(size_hints); + } + } + } + if (!(winpos->flags & SWP_NOMOVE)) + { + winChanges.x = winpos->x; + winChanges.y = winpos->y; + changeMask |= CWX | CWY; + } + if (!(winpos->flags & SWP_NOZORDER)) + { + winChanges.stack_mode = Below; + changeMask |= CWStackMode; + + if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above; + else if (winpos->hwndInsertAfter != HWND_BOTTOM) + { + WND* insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter ); + Window stack[2]; + + stack[0] = X11DRV_WND_FindDesktopXWindow( insertPtr ); + stack[1] = X11DRV_WND_FindDesktopXWindow( winposPtr ); + + /* for stupid window managers (i.e. all of them) */ + + TSXRestackWindows(display, stack, 2); + changeMask &= ~CWStackMode; + } + } + if (changeMask) + { + TSXReconfigureWMWindow( display, winposPtr->window, 0, changeMask, &winChanges ); + } + } + + if ( winpos->flags & SWP_SHOWWINDOW ) + { + if(wndPtr && wndPtr->window) TSXMapWindow( display, wndPtr->window ); + } +} + +/***************************************************************** + * X11DRV_WND_SetText + */ +void X11DRV_WND_SetText(WND *wndPtr, LPCSTR text) +{ + if (!wndPtr->window) + return; + + TSXStoreName( display, wndPtr->window, text ); + TSXSetIconName( display, wndPtr->window, text ); +} + +/***************************************************************** + * X11DRV_WND_SetFocus + * + * Set the X focus. + * Explicit colormap management seems to work only with OLVWM. + */ +void X11DRV_WND_SetFocus(WND *wndPtr) +{ + HWND32 hwnd = wndPtr->hwndSelf; + XWindowAttributes win_attr; + + /* Only mess with the X focus if there's */ + /* no desktop window and no window manager. */ + if ((rootWindow != DefaultRootWindow(display)) || Options.managed) return; + + if (!hwnd) /* If setting the focus to 0, uninstall the colormap */ + { + if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) + TSXUninstallColormap( display, COLOR_GetColormap() ); + return; + } + + /* Set X focus and install colormap */ + + if (!wndPtr->window) return; + + if (!TSXGetWindowAttributes( display, wndPtr->window, &win_attr ) || + (win_attr.map_state != IsViewable)) + return; /* If window is not viewable, don't change anything */ + + TSXSetInputFocus( display,wndPtr->window, RevertToParent, CurrentTime ); + if (COLOR_GetSystemPaletteFlags() & COLOR_PRIVATE) + TSXInstallColormap( display, COLOR_GetColormap() ); + + EVENT_Synchronize(); +} + +/***************************************************************** + * X11DRV_WND_PreSizeMove + */ +void X11DRV_WND_PreSizeMove(WND *wndPtr) +{ + if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display))) + TSXGrabServer( display ); +} + +/***************************************************************** + * X11DRV_WND_PostSizeMove + */ +void X11DRV_WND_PostSizeMove(WND *wndPtr) +{ + if (!(wndPtr->dwStyle & WS_CHILD) && (rootWindow == DefaultRootWindow(display))) + TSXUngrabServer( display ); +} + +#endif /* !defined(X_DISPLAY_MISSING) */