/*
* X events handling functions
- *
+ *
* Copyright 1993 Alexandre Julliard
+ *
*/
-static char Copyright[] = "Copyright Alexandre Julliard, 1993";
-
-#include <X11/Intrinsic.h>
-#include <X11/StringDefs.h>
-#include <X11/Core.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <X11/keysym.h>
+#include "ts_xlib.h"
+#include "ts_xresource.h"
+#include "ts_xutil.h"
+#include <X11/Xatom.h>
#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 "debug.h"
+#include "dde_proc.h"
+#include "winsock.h"
+#include "callback.h"
#define NB_BUTTONS 3 /* Windows can handle 3 buttons */
-static WORD dblclick_time = 300; /* Max. time for a double click (milliseconds) */
-extern Display * XT_display;
+#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
- /* Event handlers */
-static void EVENT_expose();
-static void EVENT_key();
-static void EVENT_mouse_motion();
-static void EVENT_mouse_button();
-static void EVENT_structure();
-static void EVENT_focus_change();
-static void EVENT_enter_notify();
+#define DndEND 8
- /* X context to associate a hwnd to an X window */
-static XContext winContext = 0;
-
- /* State variables */
-static HWND captureWnd = 0;
-Window winHasCursor = 0;
-extern HWND hWndFocus;
+#define DndURL 128 /* KDE drag&drop */
-/* Keyboard translation tables */
-static 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 cursor_key[] =
-{
- VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR,
- VK_NEXT, VK_END /* FF50 */
-};
-
-static 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 keypad_key[] =
-{
- VK_MENU, 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, 0, 0, 0, /* FF90 */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 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 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 */
-};
+ /* X context to associate a hwnd to an X window */
+static XContext winContext = 0;
-static modifier_key[] =
-{
- VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
- 0, 0, /* FFE1 */
- 0, VK_MENU, VK_MENU /* FFE8 */
-};
+static INT16 captureHT = HTCLIENT;
+static HWND32 captureWnd = 0;
+static BOOL32 InputEnabled = TRUE;
+static BOOL32 SwappedButtons = FALSE;
-typedef union
-{
- struct
- {
- unsigned long count : 16;
- unsigned long code : 8;
- unsigned long extended : 1;
- unsigned long : 4;
- unsigned long context : 1;
- unsigned long previous : 1;
- unsigned long transition : 1;
- } lp1;
- unsigned long lp2;
-} KEYLP;
+static Atom wmProtocols = None;
+static Atom wmDeleteWindow = None;
+static Atom dndProtocol = None;
+static Atom dndSelection = None;
-static BOOL KeyDown = FALSE;
+/* EVENT_WaitNetEvent() master fd sets */
+static fd_set __event_io_set[3];
+static int __event_max_fd = 0;
+static int __event_x_connection = 0;
-#ifdef DEBUG_EVENT
-static char *event_names[] =
+static const char * const event_names[] =
{
"", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
"MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
"SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
"ClientMessage", "MappingNotify"
};
-#endif
+ /* 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 void 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_SendMouseEvent( WORD mouseStatus, WORD deltaX, WORD deltaY,
+ WORD buttonCount, DWORD extraInfo );
+
+/***********************************************************************
+ * 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;
+}
+
+/***********************************************************************
+ * EVENT_AddIO
+ */
+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_ProcessEvent
*/
void EVENT_ProcessEvent( XEvent *event )
{
- HWND hwnd;
- XPointer ptr;
- Boolean cont_dispatch = TRUE;
+ WND *pWnd;
- XFindContext( XT_display, ((XAnyEvent *)event)->window, winContext, &ptr );
- hwnd = (HWND)ptr & 0xffff;
+ 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 {
+ return; /* Not for a registered window */
+ }
+ }
-#ifdef DEBUG_EVENT
- printf( "Got event %s for hwnd %d\n",
- event_names[event->type], hwnd );
-#endif
+ TRACE(event, "Got event %s for hwnd %04x\n",
+ event_names[event->type], pWnd->hwndSelf );
switch(event->type)
{
- case Expose:
- EVENT_expose( 0, hwnd, event, &cont_dispatch );
- break;
-
- case KeyPress:
- case KeyRelease:
- EVENT_key( 0, hwnd, event, &cont_dispatch );
- break;
-
- case MotionNotify:
- EVENT_mouse_motion( 0, hwnd, event, &cont_dispatch );
- break;
-
- case ButtonPress:
- case ButtonRelease:
- EVENT_mouse_button( 0, hwnd, event, &cont_dispatch );
- break;
-
- case CirculateNotify:
- case ConfigureNotify:
- case MapNotify:
- case UnmapNotify:
- EVENT_structure( 0, hwnd, event, &cont_dispatch );
- break;
-
- case FocusIn:
- case FocusOut:
- EVENT_focus_change( 0, hwnd, event, &cont_dispatch );
- break;
-
- case EnterNotify:
- EVENT_enter_notify( 0, hwnd, event, &cont_dispatch );
- break;
-
-#ifdef DEBUG_EVENT
- default:
- printf( "Unprocessed event %s for hwnd %d\n",
- event_names[event->type], hwnd );
- break;
-#endif
+ case KeyPress:
+ case KeyRelease:
+ if (InputEnabled) EVENT_Key( pWnd, (XKeyEvent*)event );
+ break;
+
+ case ButtonPress:
+ if (InputEnabled)
+ EVENT_ButtonPress( pWnd, (XButtonEvent*)event );
+ break;
+
+ case ButtonRelease:
+ if (InputEnabled)
+ 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.
+ */
+ if (InputEnabled)
+ {
+ while (TSXCheckTypedWindowEvent(display,((XAnyEvent *)event)->window,
+ MotionNotify, event));
+ EVENT_MotionNotify( pWnd, (XMotionEvent*)event );
+ }
+ break;
+
+ case FocusIn:
+ EVENT_FocusIn( pWnd, (XFocusChangeEvent*)event );
+ break;
+
+ case FocusOut:
+ EVENT_FocusOut( pWnd, (XFocusChangeEvent*)event );
+ break;
+
+ case Expose:
+ EVENT_Expose( pWnd, (XExposeEvent *)event );
+ break;
+
+ case GraphicsExpose:
+ EVENT_GraphicsExpose( pWnd, (XGraphicsExposeEvent *)event );
+ break;
+
+ case ConfigureNotify:
+ EVENT_ConfigureNotify( pWnd, (XConfigureEvent*)event );
+ break;
+
+ case SelectionRequest:
+ EVENT_SelectionRequest( pWnd, (XSelectionRequestEvent *)event );
+ break;
+
+ case SelectionNotify:
+ EVENT_SelectionNotify( (XSelectionEvent *)event );
+ break;
+
+ case SelectionClear:
+ EVENT_SelectionClear( pWnd, (XSelectionClearEvent*) event );
+ break;
+
+ case ClientMessage:
+ 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:
+ EVENT_MapNotify( pWnd->hwndSelf, (XMapEvent *)event );
+ break;
+
+ default:
+ WARN(event, "Unprocessed event %s for hwnd %04x\n",
+ event_names[event->type], pWnd->hwndSelf );
+ break;
}
}
/***********************************************************************
- * EVENT_AddHandlers
+ * EVENT_RegisterWindow
*
- * Add the event handlers to the given window
- */
-#ifdef USE_XLIB
-void EVENT_AddHandlers( Window w, int hwnd )
-{
- if (!winContext) winContext = XUniqueContext();
- XSaveContext( XT_display, w, winContext, (XPointer)hwnd );
-}
-#else
-void EVENT_AddHandlers( Widget w, int hwnd )
-{
- XtAddEventHandler(w, ExposureMask, FALSE,
- EVENT_expose, (XtPointer)hwnd );
- XtAddEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE,
- EVENT_key, (XtPointer)hwnd );
- XtAddEventHandler(w, PointerMotionMask, FALSE,
- EVENT_mouse_motion, (XtPointer)hwnd );
- XtAddEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
- EVENT_mouse_button, (XtPointer)hwnd );
- XtAddEventHandler(w, StructureNotifyMask, FALSE,
- EVENT_structure, (XtPointer)hwnd );
- XtAddEventHandler(w, FocusChangeMask, FALSE,
- EVENT_focus_change, (XtPointer)hwnd );
- XtAddEventHandler(w, EnterWindowMask, FALSE,
- EVENT_enter_notify, (XtPointer)hwnd );
+ * 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_DestroyWindow
+ */
+void EVENT_DestroyWindow( WND *pWnd )
+{
+ XEvent xe;
+
+ TSXDeleteContext( display, pWnd->window, winContext );
+ TSXDestroyWindow( display, pWnd->window );
+ while( TSXCheckWindowEvent(display, pWnd->window, NoEventMask, &xe) );
}
-#endif
/***********************************************************************
- * EVENT_RemoveHandlers
+ * IsUserIdle (USER.333)
*
- * Remove the event handlers of the given window
- */
-void EVENT_RemoveHandlers( Widget w, int hwnd )
-{
-#ifndef USE_XLIB
- XtRemoveEventHandler(w, ExposureMask, FALSE,
- EVENT_expose, (XtPointer)hwnd );
- XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE,
- EVENT_key, (XtPointer)hwnd );
- XtRemoveEventHandler(w, PointerMotionMask, FALSE,
- EVENT_mouse_motion, (XtPointer)hwnd );
- XtRemoveEventHandler(w, ButtonPressMask | ButtonReleaseMask, FALSE,
- EVENT_mouse_button, (XtPointer)hwnd );
- XtRemoveEventHandler(w, StructureNotifyMask, FALSE,
- EVENT_structure, (XtPointer)hwnd );
- XtRemoveEventHandler(w, FocusChangeMask, FALSE,
- EVENT_focus_change, (XtPointer)hwnd );
- XtRemoveEventHandler(w, EnterWindowMask, FALSE,
- EVENT_enter_notify, (XtPointer)hwnd );
-#endif
+ * 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
+ *
+ * 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 )
+{
+ 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))
+ continue;
+
+ 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 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_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_expose
+ * EVENT_Expose
+ */
+static void EVENT_Expose( WND *pWnd, XExposeEvent *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_FRAME | RDW_ALLCHILDREN | RDW_ERASE |
+ (event->count ? 0 : RDW_ERASENOW), 0 );
+}
+
+
+/***********************************************************************
+ * EVENT_GraphicsExpose
*
- * Handle a X expose event
+ * This is needed when scrolling area is partially obscured
+ * by non-Wine X window.
*/
-static void EVENT_expose( Widget w, int hwnd, XExposeEvent *event,
- Boolean *cont_dispatch )
+static void EVENT_GraphicsExpose( WND *pWnd, XGraphicsExposeEvent *event )
{
- RECT rect;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
- /* Make position relative to client area instead of window */
- rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
- rect.top = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
+ 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;
- winHasCursor = event->window;
-
- InvalidateRect( hwnd, &rect, TRUE );
+
+ PAINT_RedrawWindow( pWnd->hwndSelf, &rect, 0,
+ RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE |
+ (event->count ? 0 : RDW_ERASENOW), 0 );
}
/***********************************************************************
- * EVENT_key
+ * EVENT_Key
*
* Handle a X key event
*/
-static void EVENT_key( Widget w, int hwnd, XKeyEvent *event,
- Boolean *cont_dispatch )
-{
- MSG msg;
- char Str[24];
- XComposeStatus cs;
- KeySym keysym;
- WORD xkey, vkey, key_type, key;
- KEYLP keylp;
- BOOL extended = FALSE;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- int count = XLookupString(event, Str, 1, &keysym, &cs);
- Str[count] = '\0';
-#ifdef DEBUG_KEY
- printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n",
- keysym, count, Str[0], Str);
-#endif
+static void EVENT_Key( WND *pWnd, XKeyEvent *event )
+{
+ KEYBOARD_HandleEvent( pWnd, event );
+}
- xkey = LOWORD(keysym);
- key_type = HIBYTE(xkey);
- key = LOBYTE(xkey);
-#ifdef DEBUG_KEY
- printf(" key_type=%X, key=%X\n", key_type, key);
-#endif
- /* Position must be relative to client area */
- event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
- event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+/***********************************************************************
+ * EVENT_MotionNotify
+ */
+static void EVENT_MotionNotify( WND *pWnd, XMotionEvent *event )
+{
+ hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ event->time - MSG_WineStartTicks, pWnd->hwndSelf );
+
+ EVENT_SendMouseEvent( ME_MOVE,
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ 0, 0 );
+}
+
- if (key_type == 0xFF) /* non-character key */
+/***********************************************************************
+ * EVENT_DummyMotionNotify
+ *
+ * Generate a dummy MotionNotify event. Used to force a WM_SETCURSOR message.
+ */
+void EVENT_DummyMotionNotify(void)
+{
+ Window root, child;
+ int rootX, rootY, winX, winY;
+ unsigned int state;
+
+ if (TSXQueryPointer( display, rootWindow, &root, &child,
+ &rootX, &rootY, &winX, &winY, &state ))
{
- 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];
- extended = TRUE;
- }
- else if (key >= 0xBE && key <= 0xCD) /* function key */
- {
- vkey = function_key[key - 0xBE];
- extended = TRUE;
- }
- else if (key >= 0xE1 && key <= 0xEA) /* modifier key */
- vkey = modifier_key[key - 0xE1];
- else if (key == 0xFF) /* DEL key */
- vkey = VK_DELETE;
+ hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( state ), 0L,
+ winX, winY, GetTickCount(), 0 );
+ }
+}
+
+
+/***********************************************************************
+ * EVENT_ButtonPress
+ */
+static void EVENT_ButtonPress( WND *pWnd, XButtonEvent *event )
+{
+ static WORD messages[NB_BUTTONS] =
+ { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
+ static WORD statusCodes[NB_BUTTONS] =
+ { ME_LDOWN, 0, ME_RDOWN };
+ int buttonNum = event->button - 1;
+
+ if (buttonNum >= NB_BUTTONS) return;
+ if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
+ MouseButtonsStates[buttonNum] = TRUE;
+ AsyncMouseButtonsStates[buttonNum] = TRUE;
+ hardware_event( messages[buttonNum],
+ EVENT_XStateToKeyState( event->state ), 0L,
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ event->time - MSG_WineStartTicks, pWnd->hwndSelf );
+
+ EVENT_SendMouseEvent( statusCodes[buttonNum],
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ 0, 0 );
+}
+
+
+/***********************************************************************
+ * EVENT_ButtonRelease
+ */
+static void EVENT_ButtonRelease( WND *pWnd, XButtonEvent *event )
+{
+ static const WORD messages[NB_BUTTONS] =
+ { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
+ static WORD statusCodes[NB_BUTTONS] =
+ { ME_LUP, 0, ME_RUP };
+ int buttonNum = event->button - 1;
+
+ if (buttonNum >= NB_BUTTONS) return;
+ if (SwappedButtons) buttonNum = NB_BUTTONS - 1 - buttonNum;
+ MouseButtonsStates[buttonNum] = FALSE;
+ hardware_event( messages[buttonNum],
+ EVENT_XStateToKeyState( event->state ), 0L,
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ event->time - MSG_WineStartTicks, pWnd->hwndSelf );
+
+ EVENT_SendMouseEvent( statusCodes[buttonNum],
+ pWnd->rectWindow.left + event->x,
+ pWnd->rectWindow.top + event->y,
+ 0, 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 );
}
- else if (key_type == 0) /* character key */
+}
+
+
+/**********************************************************************
+ * EVENT_FocusOut
+ *
+ * Note: only top-level override-redirect windows get FocusOut events.
+ */
+static void EVENT_FocusOut( WND *pWnd, XFocusChangeEvent *event )
+{
+ if (event->detail != NotifyPointer)
{
- if (key >= 0x61 && key <= 0x7A)
- vkey = key - 0x20; /* convert lower to uppercase */
- else
- vkey = key;
+ HWND32 hwnd = pWnd->hwndSelf;
+
+ if (hwnd == GetActiveWindow32())
+ WINPOS_ChangeActiveWindow( 0, FALSE );
+ if ((hwnd == GetFocus32()) || IsChild32( hwnd, GetFocus32()))
+ SetFocus32( 0 );
}
+}
+
+/**********************************************************************
+ * 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 (event->type == KeyPress)
+ if (!TSXGetGeometry( display, win, &root, px, py, pwidth, pheight,
+ &border, &depth )) return;
+ if (win == rootWindow)
{
- msg.hwnd = hwnd;
- msg.message = WM_KEYDOWN;
- msg.wParam = vkey;
- keylp.lp1.count = 1;
- keylp.lp1.code = LOBYTE(event->keycode);
- keylp.lp1.extended = (extended ? 1 : 0);
- keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
- keylp.lp1.previous = (KeyDown ? 0 : 1);
- keylp.lp1.transition = 0;
- msg.lParam = keylp.lp2;
-#ifdef DEBUG_KEY
- printf(" wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
-#endif
- msg.time = event->time;
- msg.pt.x = event->x & 0xffff;
- msg.pt.y = event->y & 0xffff;
-
- hardware_event( hwnd, WM_KEYDOWN, vkey, keylp.lp2,
- event->x & 0xffff, event->y & 0xffff, event->time, 0 );
- KeyDown = TRUE;
-
- /* The key translation ought to take place in TranslateMessage().
- * However, there is no way of passing the required information
- * in a Windows message, so TranslateMessage does not currently
- * do anything and the translation is done here.
- */
- if (count == 1) /* key has an ASCII representation */
- {
- msg.hwnd = hwnd;
- msg.message = WM_CHAR;
- msg.wParam = (WORD)Str[0];
- msg.lParam = keylp.lp2;
-#ifdef DEBUG_KEY
- printf("WM_CHAR : wParam=%X\n", msg.wParam);
-#endif
- msg.time = event->time;
- msg.pt.x = event->x & 0xffff;
- msg.pt.y = event->y & 0xffff;
- PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
- }
+ *px = *py = 0;
+ return;
}
- else
+
+ for (;;)
{
- msg.hwnd = hwnd;
- msg.message = WM_KEYUP;
- msg.wParam = vkey;
- keylp.lp1.count = 1;
- keylp.lp1.code = LOBYTE(event->keycode);
- keylp.lp1.extended = (extended ? 1 : 0);
- keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
- keylp.lp1.previous = 1;
- keylp.lp1.transition = 1;
- msg.lParam = keylp.lp2;
-#ifdef DEBUG_KEY
- printf(" wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
-#endif
- msg.time = event->time;
- msg.pt.x = event->x & 0xffff;
- msg.pt.y = event->y & 0xffff;
-
- hardware_event( hwnd, WM_KEYUP, vkey, keylp.lp2,
- event->x & 0xffff, event->y & 0xffff, event->time, 0 );
- KeyDown = FALSE;
+ 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_mouse_motion
+/**********************************************************************
+ * EVENT_ConfigureNotify
*
- * Handle a X mouse motion event
+ * The ConfigureNotify event is only selected on top-level windows
+ * when the -managed flag is used.
*/
-static void EVENT_mouse_motion( Widget w, int hwnd, XMotionEvent *event,
- Boolean *cont_dispatch )
+static void EVENT_ConfigureNotify( WND *pWnd, XConfigureEvent *event )
{
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
+ 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 );
+ }
- /* Position must be relative to client area */
- event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
- event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+ /* Send WM_WINDOWPOSCHANGING */
+ SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
- hardware_event( hwnd, WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ),
- (event->x & 0xffff) | (event->y << 16),
- event->x & 0xffff, event->y & 0xffff,
- event->time, 0 );
+ /* 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_mouse_button
- *
- * Handle a X mouse button event
+ * EVENT_SelectionRequest
*/
-static void EVENT_mouse_button( Widget w, int hwnd, XButtonEvent *event,
- Boolean *cont_dispatch )
+static void EVENT_SelectionRequest( WND *pWnd, XSelectionRequestEvent *event )
{
- static WORD messages[3][NB_BUTTONS] =
+ XSelectionEvent result;
+ Atom rprop = None;
+ Window request = event->requestor;
+
+ if(event->target == XA_STRING)
{
- { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN },
- { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP },
- { WM_LBUTTONDBLCLK, WM_MBUTTONDBLCLK, WM_RBUTTONDBLCLK }
- };
- static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
-
- int buttonNum, prevTime, type;
-
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
-
- /* Position must be relative to client area */
- event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
- event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
-
- buttonNum = event->button-1;
- if (buttonNum >= NB_BUTTONS) return;
- if (event->type == ButtonRelease) type = 1;
- else
- { /* Check if double-click */
- prevTime = lastClickTime[buttonNum];
- lastClickTime[buttonNum] = event->time;
- if (event->time - prevTime < dblclick_time)
+ 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
{
- WND * wndPtr;
- CLASS * classPtr;
- if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
- if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return;
- type = (classPtr->wc.style & CS_DBLCLKS) ? 2 : 0;
+ /* 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();
}
- else type = 0;
- }
-
- winHasCursor = event->window;
+ }
- hardware_event( hwnd, messages[type][buttonNum],
- EVENT_XStateToKeyState( event->state ),
- (event->x & 0xffff) | (event->y << 16),
- event->x & 0xffff, event->y & 0xffff,
- event->time, 0 );
+ 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_structure
- *
- * Handle a X StructureNotify event
+ * EVENT_SelectionNotify
*/
-static void EVENT_structure( Widget w, int hwnd, XEvent *event,
- Boolean *cont_dispatch )
+static void EVENT_SelectionNotify( XSelectionEvent *event )
{
- MSG msg;
-
- msg.hwnd = hwnd;
- msg.time = GetTickCount();
- msg.pt.x = 0;
- msg.pt.y = 0;
+ if (event->selection != XA_PRIMARY) return;
- switch(event->type)
- {
- case ConfigureNotify:
- {
- HANDLE handle;
- NCCALCSIZE_PARAMS *params;
- XConfigureEvent * evt = (XConfigureEvent *)event;
- WND * wndPtr = WIN_FindWndPtr( hwnd );
- if (!wndPtr) return;
- wndPtr->rectWindow.left = evt->x;
- wndPtr->rectWindow.top = evt->y;
- wndPtr->rectWindow.right = evt->x + evt->width;
- wndPtr->rectWindow.bottom = evt->y + evt->height;
-
- /* Send WM_NCCALCSIZE message */
- handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
- params = (NCCALCSIZE_PARAMS *)GlobalLock( handle );
- params->rgrc[0] = wndPtr->rectWindow;
- params->lppos = NULL; /* Should be WINDOWPOS struct */
- SendMessage( hwnd, WM_NCCALCSIZE, FALSE, params );
- wndPtr->rectClient = params->rgrc[0];
- PostMessage( hwnd, WM_MOVE, 0,
- MAKELONG( wndPtr->rectClient.left,
- wndPtr->rectClient.top ));
- PostMessage( hwnd, WM_SIZE, SIZE_RESTORED,
- MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
- wndPtr->rectClient.bottom-wndPtr->rectClient.top));
- GlobalUnlock( handle );
- GlobalFree( handle );
- }
- break;
-
- }
+ 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_focus_change
+ * EVENT_DropFromOffix
*
- * Handle an X FocusChange event
+ * don't know if it still works (last Changlog is from 96/11/04)
*/
-static void EVENT_focus_change( Widget w, int hwnd, XEvent *event,
- Boolean *cont_dispatch )
+static void EVENT_DropFromOffiX( WND *pWnd, XClientMessageEvent *event )
{
- switch(event->type)
+ 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
{
- case FocusIn:
+ 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 */
{
- PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
- hWndFocus = hwnd;
+ 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 );
+ }
+ }
}
- break;
+ 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 );
- case FocusOut:
- {
- if (hWndFocus)
- {
- PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
- hWndFocus = 0;
+ 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_enter_notify
+ * EVENT_EnterNotify
*
- * Handle an X EnterNotify event
+ * 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
*/
-static void EVENT_enter_notify( Widget w, int hwnd, XCrossingEvent *event,
- Boolean *cont_dispatch )
+void EVENT_MapNotify( HWND32 hWnd, XMapEvent *event )
{
- if (captureWnd != 0) return;
+ HWND32 hwndFocus = GetFocus32();
- winHasCursor = event->window;
+ if (hwndFocus && IsChild32( hWnd, hwndFocus ))
+ FOCUS_SetXFocus( (HWND32)hwndFocus );
- switch(event->type)
- {
- case EnterNotify:
- PostMessage( hwnd, WM_SETCURSOR, hwnd, 0 );
- break;
- }
+ return;
}
-
/**********************************************************************
- * SetCapture (USER.18)
+ * EVENT_Capture
+ *
+ * We need this to be able to generate double click messages
+ * when menu code captures mouse in the window without CS_DBLCLK style.
*/
-HWND SetCapture(HWND wnd)
+HWND32 EVENT_Capture(HWND32 hwnd, INT16 ht)
{
- int rv;
- HWND old_capture_wnd = captureWnd;
- WND *wnd_p = WIN_FindWndPtr(wnd);
- if (wnd_p == NULL)
- return 0;
-
-#ifdef USE_XLIB
- rv = XGrabPointer(XT_display, wnd_p->window, False,
- ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
- GrabModeAsync, GrabModeSync, None, None, CurrentTime);
-#else
- rv = XtGrabPointer(wnd_p->winWidget, False,
- ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
- GrabModeAsync, GrabModeSync, None, None, CurrentTime);
-#endif
+ HWND32 capturePrev = captureWnd;
- if (rv == GrabSuccess)
+ if (!hwnd)
{
- captureWnd = wnd;
- return old_capture_wnd;
+ captureWnd = 0L;
+ captureHT = 0;
}
else
- return 0;
+ {
+ WND* wndPtr = WIN_FindWndPtr( hwnd );
+ if (wndPtr)
+ {
+ TRACE(win, "(0x%04x)\n", hwnd );
+ captureWnd = hwnd;
+ captureHT = ht;
+ }
+ }
+
+ if( capturePrev && capturePrev != captureWnd )
+ {
+ WND* wndPtr = WIN_FindWndPtr( capturePrev );
+ if( wndPtr && (wndPtr->flags & WIN_ISWIN32) )
+ SendMessage32A( capturePrev, WM_CAPTURECHANGED, 0L, hwnd);
+ }
+ return capturePrev;
}
/**********************************************************************
- * ReleaseCapture (USER.19)
+ * EVENT_GetCaptureInfo
*/
-void ReleaseCapture()
+INT16 EVENT_GetCaptureInfo()
{
- WND *wnd_p;
-
- if (captureWnd == 0)
- return;
-
- wnd_p = WIN_FindWndPtr(captureWnd);
- if (wnd_p == NULL)
- return;
-
-#ifdef USE_XLIB
- XUngrabPointer( XT_display, CurrentTime );
-#else
- XtUngrabPointer(wnd_p->winWidget, CurrentTime);
-#endif
+ return captureHT;
+}
+
+/**********************************************************************
+ * SetCapture16 (USER.18)
+ */
+HWND16 WINAPI SetCapture16( HWND16 hwnd )
+{
+ return (HWND16)EVENT_Capture( hwnd, HTCLIENT );
+}
- captureWnd = 0;
+
+/**********************************************************************
+ * SetCapture32 (USER32.464)
+ */
+HWND32 WINAPI SetCapture32( HWND32 hwnd )
+{
+ return EVENT_Capture( hwnd, HTCLIENT );
}
+
/**********************************************************************
- * GetCapture (USER.236)
+ * ReleaseCapture (USER.19) (USER32.439)
*/
-HWND GetCapture()
+void WINAPI ReleaseCapture(void)
+{
+ TRACE(win, "captureWnd=%04x\n", captureWnd );
+ if( captureWnd ) EVENT_Capture( 0, 0 );
+}
+
+
+/**********************************************************************
+ * GetCapture16 (USER.236)
+ */
+HWND16 WINAPI GetCapture16(void)
{
return captureWnd;
}
-
+
+
/**********************************************************************
- * SetDoubleClickTime (USER.20)
+ * GetCapture32 (USER32.208)
*/
-void SetDoubleClickTime (WORD interval)
+HWND32 WINAPI GetCapture32(void)
{
- if (interval == 0)
- dblclick_time = 500;
- else
- dblclick_time = interval;
-}
+ return captureWnd;
+}
+
+
+
+/***********************************************************************
+ * Mouse driver routines:
+ */
+
+#pragma pack(1)
+typedef struct _MOUSEINFO
+{
+ BYTE msExist;
+ BYTE msRelative;
+ WORD msNumButtons;
+ WORD msRate;
+ WORD msXThreshold;
+ WORD msYThreshold;
+ WORD msXRes;
+ WORD msYRes;
+ WORD msMouseCommPort;
+} MOUSEINFO;
+#pragma pack(4)
+
+static SEGPTR MouseEventProc = 0;
+
+/***********************************************************************
+ * MouseInquire (MOUSE.1)
+ */
+
+WORD WINAPI MouseInquire(MOUSEINFO *mouseInfo)
+{
+ mouseInfo->msExist = TRUE;
+ mouseInfo->msRelative = FALSE;
+ mouseInfo->msNumButtons = 2;
+ mouseInfo->msRate = 34; /* the DDK says so ... */
+ mouseInfo->msXThreshold = 0;
+ mouseInfo->msYThreshold = 0;
+ mouseInfo->msXRes = 0;
+ mouseInfo->msYRes = 0;
+ mouseInfo->msMouseCommPort = 0;
+
+ return sizeof(MOUSEINFO);
+}
+
+/***********************************************************************
+ * MouseEnable (MOUSE.2)
+ */
+VOID WINAPI MouseEnable(SEGPTR eventProc)
+{
+ MouseEventProc = eventProc;
+}
+
+/***********************************************************************
+ * MouseDisable (MOUSE.3)
+ */
+VOID WINAPI MouseDisable(VOID)
+{
+ MouseEventProc = 0;
+}
+
+/***********************************************************************
+ * EVENT_SendMouseEvent
+ */
+static void EVENT_SendMouseEvent( WORD mouseStatus, WORD deltaX, WORD deltaY,
+ WORD buttonCount, DWORD extraInfo )
+{
+ CONTEXT context;
+
+ if ( !MouseEventProc ) return;
+
+ TRACE( keyboard, "(%04X,%d,%d,%d,%ld)\n", mouseStatus, deltaX, deltaY, buttonCount, extraInfo );
+
+ mouseStatus |= 0x8000;
+ deltaX = (((long)deltaX << 16) + screenWidth/2) / screenWidth;
+ deltaY = (((long)deltaY << 16) + screenHeight/2) / screenHeight;
+
+ memset( &context, 0, sizeof(context) );
+ CS_reg(&context) = SELECTOROF( MouseEventProc );
+ EIP_reg(&context) = OFFSETOF( MouseEventProc );
+ EAX_reg(&context) = mouseStatus;
+ EBX_reg(&context) = deltaX;
+ ECX_reg(&context) = deltaY;
+ EDX_reg(&context) = buttonCount;
+ ESI_reg(&context) = LOWORD( extraInfo );
+ EDI_reg(&context) = HIWORD( extraInfo );
+
+ Callbacks->CallRegisterShortProc( &context, 0 );
+}
+
+
+
+
+/***********************************************************************
+ * GetMouseEventProc (USER.337)
+ */
+FARPROC16 WINAPI GetMouseEventProc(void)
+{
+ HMODULE16 hmodule = GetModuleHandle16("USER");
+ return NE_GetEntryPoint( hmodule, NE_GetOrdinal( hmodule, "Mouse_Event" ));
+}
+
+
+/***********************************************************************
+ * Mouse_Event (USER.299)
+ */
+void WINAPI Mouse_Event( CONTEXT *context )
+{
+ /* Register values:
+ * AX = mouse event
+ * BX = horizontal displacement if AX & ME_MOVE
+ * CX = vertical displacement if AX & ME_MOVE
+ * DX = button state (?)
+ * SI = mouse event flags (?)
+ */
+ Window root, child;
+ int rootX, rootY, winX, winY;
+ unsigned int state;
+
+ if (AX_reg(context) & ME_MOVE)
+ {
+ /* We have to actually move the cursor */
+ TSXWarpPointer( display, rootWindow, None, 0, 0, 0, 0,
+ (short)BX_reg(context), (short)CX_reg(context) );
+ return;
+ }
+ if (!TSXQueryPointer( display, rootWindow, &root, &child,
+ &rootX, &rootY, &winX, &winY, &state )) return;
+ if (AX_reg(context) & ME_LDOWN)
+ hardware_event( WM_LBUTTONDOWN, EVENT_XStateToKeyState( state ),
+ 0L, winX, winY, GetTickCount(), 0 );
+ if (AX_reg(context) & ME_LUP)
+ hardware_event( WM_LBUTTONUP, EVENT_XStateToKeyState( state ),
+ 0L, winX, winY, GetTickCount(), 0 );
+ if (AX_reg(context) & ME_RDOWN)
+ hardware_event( WM_RBUTTONDOWN, EVENT_XStateToKeyState( state ),
+ 0L, winX, winY, GetTickCount(), 0 );
+ if (AX_reg(context) & ME_RUP)
+ hardware_event( WM_RBUTTONUP, EVENT_XStateToKeyState( state ),
+ 0L, winX, winY, GetTickCount(), 0 );
+}
+
/**********************************************************************
- * GetDoubleClickTime (USER.21)
+ * EnableHardwareInput (USER.331)
*/
-WORD GetDoubleClickTime ()
+BOOL16 WINAPI EnableHardwareInput(BOOL16 bEnable)
{
- return ((WORD)dblclick_time);
-}
+ BOOL16 bOldState = InputEnabled;
+ FIXME(event,"(%d) - stub\n", bEnable);
+ InputEnabled = bEnable;
+ return bOldState;
+}
+/***********************************************************************
+ * SwapMouseButton16 (USER.186)
+ */
+BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
+{
+ BOOL16 ret = SwappedButtons;
+ SwappedButtons = fSwap;
+ return ret;
+}
+
+
+/***********************************************************************
+ * SwapMouseButton32 (USER32.537)
+ */
+BOOL32 WINAPI SwapMouseButton32( BOOL32 fSwap )
+{
+ BOOL32 ret = SwappedButtons;
+ SwappedButtons = fSwap;
+ return ret;
+}