diff --git a/graphics/ddraw.c b/graphics/ddraw.c index 63ec0893bab..c4ef83b43c8 100644 --- a/graphics/ddraw.c +++ b/graphics/ddraw.c @@ -3498,6 +3498,35 @@ static HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel( return DD_OK; } +#ifdef HAVE_LIBXXF86DGA2 +static HRESULT WINAPI DGA_IDirectDraw2Impl_SetCooperativeLevel( + LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel +) { + ICOM_THIS(IDirectDraw2Impl,iface); + HRESULT ret; + int evbase, erbase; + + ret = IDirectDraw2Impl_SetCooperativeLevel(iface, hwnd, cooplevel); + + if (This->e.dga.version != 2) { + return ret; + } else { + if (ret != DD_OK) + return ret; + + TSXDGAQueryExtension(display, &evbase, &erbase); + + /* Now, start handling of DGA events giving the handle to the DDraw window + as the window for which the event will be reported */ + TSXDGASelectInput(display, DefaultScreen(display), + KeyPressMask|KeyReleaseMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask ); + X11DRV_EVENT_SetDGAStatus(hwnd, evbase); + + return DD_OK; + } +} +#endif + /* Small helper to either use the cooperative window or create a new * one (for mouse and keyboard input) and drawing in the Xlib implementation. */ @@ -4197,13 +4226,14 @@ static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) { if (This->e.dga.version == 2) { TRACE("Closing access to the FrameBuffer\n"); TSXDGACloseFramebuffer(display, DefaultScreen(display)); + TRACE("Going back to normal X mode of operation\n"); + TSXDGASetMode(display, DefaultScreen(display), 0); /* Set the input handling back to absolute */ X11DRV_EVENT_SetInputMehod(X11DRV_INPUT_ABSOLUTE); - /* Ungrab mouse and keyboard */ - TSXUngrabPointer(display, CurrentTime); - TSXUngrabKeyboard(display, CurrentTime); + /* Remove the handling of DGA2 events */ + X11DRV_EVENT_SetDGAStatus(0, -1); } else #endif /* defined(HAVE_LIBXXF86DGA2) */ TSXF86DGADirectVideo(display,DefaultScreen(display),0); @@ -4822,7 +4852,11 @@ static ICOM_VTABLE(IDirectDraw) dga_ddvt = XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus, XCAST(Initialize)IDirectDraw2Impl_Initialize, XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode, +#ifdef HAVE_LIBXXF86DGA2 + XCAST(SetCooperativeLevel)DGA_IDirectDraw2Impl_SetCooperativeLevel, +#else XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel, +#endif DGA_IDirectDrawImpl_SetDisplayMode, XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank, }; @@ -5230,15 +5264,6 @@ static HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnk (*ilplpDD)->e.dga.version = 2; - - TSXGrabPointer(display, DefaultRootWindow(display), True, - PointerMotionMask | ButtonPressMask | ButtonReleaseMask, - GrabModeAsync, GrabModeAsync, None, None, CurrentTime); - - TSXGrabKeyboard(display, DefaultRootWindow(display), True, GrabModeAsync, - GrabModeAsync, CurrentTime); - - TSXDGAQueryVersion(display,&major,&minor); TRACE("XDGA is version %d.%d\n",major,minor); @@ -5246,15 +5271,9 @@ static HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnk if (!TSXDGAOpenFramebuffer(display, DefaultScreen(display))) { ERR("Error opening the frame buffer !!!\n"); - TSXUngrabPointer(display, CurrentTime); - TSXUngrabKeyboard(display, CurrentTime); - return DDERR_GENERIC; } - /* Set the input handling for relative mouse movements */ - X11DRV_EVENT_SetInputMehod(X11DRV_INPUT_RELATIVE); - /* List all available modes */ modes = TSXDGAQueryModes(display, DefaultScreen(display), &num_modes); if (TRACE_ON(ddraw)) { @@ -5289,6 +5308,9 @@ static HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnk /* Now, get the device / mode description */ (*ilplpDD)->e.dga.dev = TSXDGASetMode(display, DefaultScreen(display), mode_to_use); + /* Set the input handling for relative mouse movements */ + X11DRV_EVENT_SetInputMehod(X11DRV_INPUT_RELATIVE); + (*ilplpDD)->e.dga.fb_width = (*ilplpDD)->e.dga.dev->mode.imageWidth; TSXDGASetViewport(display,DefaultScreen(display),0,0, XDGAFlipImmediate); (*ilplpDD)->e.dga.fb_height = (*ilplpDD)->e.dga.dev->mode.viewportHeight; diff --git a/include/x11drv.h b/include/x11drv.h index adefa61beac..4fdf6a3fa4d 100644 --- a/include/x11drv.h +++ b/include/x11drv.h @@ -386,6 +386,11 @@ typedef enum { } INPUT_TYPE; extern INPUT_TYPE X11DRV_EVENT_SetInputMehod(INPUT_TYPE type); +#ifdef HAVE_LIBXXF86DGA2 +void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base) ; +#endif + + /* X11 keyboard driver */ extern struct tagKEYBOARD_DRIVER X11DRV_KEYBOARD_Driver; diff --git a/windows/x11drv/event.c b/windows/x11drv/event.c index f7ad7d4a21f..59989a1638a 100644 --- a/windows/x11drv/event.c +++ b/windows/x11drv/event.c @@ -18,6 +18,10 @@ #include "ts_xshm.h" #endif +#ifdef HAVE_LIBXXF86DGA2 +#include "ts_xf86dga2.h" +#endif + #include #include #include "callback.h" @@ -111,6 +115,21 @@ static int ShmCompletionType; extern int XShmGetEventBase( Display * );/* Missing prototype for function in libXext. */ #endif +#ifdef HAVE_LIBXXF86DGA2 +static int DGAMotionEventType; +static int DGAButtonPressEventType; +static int DGAButtonReleaseEventType; +static int DGAKeyPressEventType; +static int DGAKeyReleaseEventType; + +static BOOL DGAUsed = FALSE; +static HWND DGAhwnd = 0; + +static void EVENT_DGAMotionEvent( XDGAMotionEvent *event ); +static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event ); +static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event ); +#endif + /* Usable only with OLVWM - compile option perhaps? static void EVENT_EnterNotify( HWND hWnd, XCrossingEvent *event ); */ @@ -232,6 +251,38 @@ static void EVENT_ProcessEvent( XEvent *event ) } #endif +#ifdef HAVE_LIBXXF86DGA2 + if (DGAUsed) { + if (event->type == DGAMotionEventType) { + TRACE("DGAMotionEvent received.\n"); + EVENT_DGAMotionEvent((XDGAMotionEvent *) event); + return; + } + if (event->type == DGAButtonPressEventType) { + TRACE("DGAButtonPressEvent received.\n"); + EVENT_DGAButtonPressEvent((XDGAButtonEvent *) event); + return; + } + if (event->type == DGAButtonReleaseEventType) { + TRACE("DGAButtonReleaseEvent received.\n"); + EVENT_DGAButtonReleaseEvent((XDGAButtonEvent *) event); + return; + } + if ((event->type == DGAKeyPressEventType) || + (event->type == DGAKeyReleaseEventType)) { + /* Out of laziness, use the helper function to do the conversion :-) */ + XKeyEvent ke; + + TRACE("DGAKeyPress/ReleaseEvent received.\n"); + + XDGAKeyEventToXKeyEvent((XDGAKeyEvent *) event, &ke); + + EVENT_Key( DGAhwnd, &ke ); + return; + } + } +#endif + if ( TSXFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0) { if ( event->type == ClientMessage) { @@ -1802,6 +1853,102 @@ INPUT_TYPE X11DRV_EVENT_SetInputMehod(INPUT_TYPE type) return prev; } +#ifdef HAVE_LIBXXF86DGA2 +/********************************************************************** + * X11DRV_EVENT_SetDGAStatus + */ +void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base) +{ + if (event_base < 0) { + DGAUsed = FALSE; + DGAhwnd = 0; + } else { + DGAUsed = TRUE; + DGAhwnd = hwnd; + DGAMotionEventType = event_base + MotionNotify; + DGAButtonPressEventType = event_base + ButtonPress; + DGAButtonReleaseEventType = event_base + ButtonRelease; + DGAKeyPressEventType = event_base + KeyPress; + DGAKeyReleaseEventType = event_base + KeyRelease; + } +} + +/* DGA2 event handlers */ +static void EVENT_DGAMotionEvent( XDGAMotionEvent *event ) +{ + MOUSE_SendEvent( MOUSEEVENTF_MOVE, + event->dx, event->dy, + X11DRV_EVENT_XStateToKeyState( event->state ), + event->time - MSG_WineStartTicks, + DGAhwnd ); +} + +static void EVENT_DGAButtonPressEvent( XDGAButtonEvent *event ) +{ + static WORD statusCodes[NB_BUTTONS] = + { MOUSEEVENTF_LEFTDOWN, MOUSEEVENTF_MIDDLEDOWN, MOUSEEVENTF_RIGHTDOWN }; + int buttonNum = event->button - 1; + + WORD keystate; + + if (buttonNum >= NB_BUTTONS) return; + + keystate = X11DRV_EVENT_XStateToKeyState( event->state ); + + switch (buttonNum) + { + case 0: + keystate |= MK_LBUTTON; + break; + case 1: + keystate |= MK_MBUTTON; + break; + case 2: + keystate |= MK_RBUTTON; + break; + } + + MOUSE_SendEvent( statusCodes[buttonNum], + 0, 0, + keystate, + event->time - MSG_WineStartTicks, + DGAhwnd ); +} + +static void EVENT_DGAButtonReleaseEvent( XDGAButtonEvent *event ) +{ + static WORD statusCodes[NB_BUTTONS] = + { MOUSEEVENTF_LEFTUP, MOUSEEVENTF_MIDDLEUP, MOUSEEVENTF_RIGHTUP }; + int buttonNum = event->button - 1; + + WORD keystate; + + if (buttonNum >= NB_BUTTONS) return; + + keystate = X11DRV_EVENT_XStateToKeyState( event->state ); + + switch (buttonNum) + { + case 0: + keystate &= ~MK_LBUTTON; + break; + case 1: + keystate &= ~MK_MBUTTON; + break; + case 2: + keystate &= ~MK_RBUTTON; + break; + } + + MOUSE_SendEvent( statusCodes[buttonNum], + 0, 0, + keystate, + event->time - MSG_WineStartTicks, + DGAhwnd ); +} + +#endif + #ifdef HAVE_LIBXXSHM /*