From 2fd19dfb98423c6d411020d38129a59a5b7f6fd7 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 1 Mar 2005 11:52:02 +0000 Subject: [PATCH] Use a dispatch table to handle X client messages. --- dlls/x11drv/event.c | 101 +++++++++-------- dlls/x11drv/x11drv.h | 5 +- dlls/x11drv/xdnd.c | 256 ++++++++++++++++++++++--------------------- 3 files changed, 192 insertions(+), 170 deletions(-) diff --git a/dlls/x11drv/event.c b/dlls/x11drv/event.c index b8fe9ed31e1..c5f1801ae6f 100644 --- a/dlls/x11drv/event.c +++ b/dlls/x11drv/event.c @@ -347,9 +347,9 @@ static void set_focus( HWND hwnd, Time time ) /********************************************************************** - * handle_wm_protocols_message + * handle_wm_protocols */ -static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event ) +static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event ) { Atom protocol = (Atom)event->data.l[0]; @@ -836,58 +836,69 @@ static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event ) } } +/********************************************************************** + * handle_dnd_protocol + */ +static void handle_dnd_protocol( HWND hwnd, XClientMessageEvent *event ) +{ + Window root, child; + int root_x, root_y, child_x, child_y; + unsigned int u; + + /* query window (drag&drop event contains only drag window) */ + wine_tsx11_lock(); + XQueryPointer( event->display, root_window, &root, &child, + &root_x, &root_y, &child_x, &child_y, &u); + if (XFindContext( event->display, child, winContext, (char **)&hwnd ) != 0) hwnd = 0; + wine_tsx11_unlock(); + if (!hwnd) return; + if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) + EVENT_DropFromOffiX(hwnd, event); + else if (event->data.l[0] == DndURL) + EVENT_DropURLs(hwnd, event); +} + + +struct client_message_handler +{ + int atom; /* protocol atom */ + void (*handler)(HWND, XClientMessageEvent *); /* corresponding handler function */ +}; + +static const struct client_message_handler client_messages[] = +{ + { XATOM_WM_PROTOCOLS, handle_wm_protocols }, + { XATOM_DndProtocol, handle_dnd_protocol }, + { XATOM_XdndEnter, X11DRV_XDND_EnterEvent }, + { XATOM_XdndPosition, X11DRV_XDND_PositionEvent }, + { XATOM_XdndDrop, X11DRV_XDND_DropEvent }, + { XATOM_XdndLeave, X11DRV_XDND_LeaveEvent } +}; + + /********************************************************************** * EVENT_ClientMessage */ -static void EVENT_ClientMessage( HWND hWnd, XEvent *xev ) +static void EVENT_ClientMessage( HWND hwnd, XEvent *xev ) { XClientMessageEvent *event = &xev->xclient; + unsigned int i; - if (!hWnd) return; + if (!hwnd) return; - if (event->message_type != None && event->format == 32) { - if (event->message_type == x11drv_atom(WM_PROTOCOLS)) - handle_wm_protocols_message( hWnd, event ); - else if (event->message_type == x11drv_atom(DndProtocol)) + if (event->format != 32) { - /* query window (drag&drop event contains only drag window) */ - Window root, child; - int root_x, root_y, child_x, child_y; - unsigned int u; + WARN( "Don't know how to handle format %d\n", event->format ); + return; + } - wine_tsx11_lock(); - XQueryPointer( event->display, root_window, &root, &child, - &root_x, &root_y, &child_x, &child_y, &u); - if (XFindContext( event->display, child, winContext, (char **)&hWnd ) != 0) hWnd = 0; - wine_tsx11_unlock(); - if (!hWnd) return; - if (event->data.l[0] == DndFile || event->data.l[0] == DndFiles) - EVENT_DropFromOffiX(hWnd, event); - else if (event->data.l[0] == DndURL) - EVENT_DropURLs(hWnd, event); - } - else if (!X11DRV_XDND_Event(hWnd, event)) + for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++) { -#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 */ - wine_tsx11_lock(); - XGetWindowProperty( event->display, DefaultRootWindow(event->display), - dndSelection, 0, 65535, FALSE, - AnyPropertyType, &u.atom, &u.i, - &u.l, &u.l, &p_data); - wine_tsx11_unlock(); - TRACE("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("unrecognized ClientMessage\n" ); + if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM]) + { + client_messages[i].handler( hwnd, event ); + return; + } } - } + TRACE( "no handler found for %ld\n", event->message_type ); } diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h index db19661019b..f28bacebac7 100644 --- a/dlls/x11drv/x11drv.h +++ b/dlls/x11drv/x11drv.h @@ -243,7 +243,10 @@ extern XIC X11DRV_CreateIC(XIM xim, Display *display, Window win); extern XIM X11DRV_SetupXIM(Display *display, const char *input_style); extern void X11DRV_XIMLookupChars( const char *str, DWORD count ); -extern int X11DRV_XDND_Event(HWND hWnd, XClientMessageEvent *event); +extern void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event ); +extern void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event ); +extern void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event ); +extern void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event ); /* exported dib functions for now */ diff --git a/dlls/x11drv/xdnd.c b/dlls/x11drv/xdnd.c index 52ade4ca09d..dd8a4724f7f 100644 --- a/dlls/x11drv/xdnd.c +++ b/dlls/x11drv/xdnd.c @@ -77,148 +77,156 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION xdnd_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + /************************************************************************** - * X11DRV_XDND_Event + * X11DRV_XDND_EnterEvent * - * Entry point for X11 XDND events. Returns FALSE if event is not handled. + * Handle an XdndEnter event. */ -int X11DRV_XDND_Event(HWND hWnd, XClientMessageEvent *event) +void X11DRV_XDND_EnterEvent( HWND hWnd, XClientMessageEvent *event ) { - int isXDNDMsg = 1; + Atom *xdndtypes; + unsigned long count = 0; - TRACE("0x%p\n", hWnd); + TRACE("ver(%ld) check-XdndTypeList(%ld) data=%ld,%ld,%ld,%ld,%ld\n", + (event->data.l[1] & 0xFF000000) >> 24, (event->data.l[1] & 1), + event->data.l[0], event->data.l[1], event->data.l[2], + event->data.l[3], event->data.l[4]); - if (event->message_type == x11drv_atom(XdndEnter)) + /* If the source supports more than 3 data types we retrieve + * the entire list. */ + if (event->data.l[1] & 1) { - Atom *xdndtypes; - unsigned long count = 0; + Atom acttype; + int actfmt; + unsigned long bytesret; - TRACE("XDNDEnter: ver(%ld) check-XdndTypeList(%ld) data=%ld,%ld,%ld,%ld,%ld\n", - (event->data.l[1] & 0xFF000000) >> 24, (event->data.l[1] & 1), - event->data.l[0], event->data.l[1], event->data.l[2], - event->data.l[3], event->data.l[4]); + /* Request supported formats from source window */ + wine_tsx11_lock(); + XGetWindowProperty(event->display, event->data.l[0], x11drv_atom(XdndTypeList), + 0, 65535, FALSE, AnyPropertyType, &acttype, &actfmt, &count, + &bytesret, (unsigned char**)&xdndtypes); + wine_tsx11_unlock(); + } + else + { + count = 3; + xdndtypes = &event->data.l[2]; + } - /* If the source supports more than 3 data types we retrieve - * the entire list. */ - if (event->data.l[1] & 1) + if (TRACE_ON(xdnd)) + { + unsigned int i = 0; + + wine_tsx11_lock(); + for (; i < count; i++) { - Atom acttype; - int actfmt; - unsigned long bytesret; - - /* Request supported formats from source window */ - wine_tsx11_lock(); - XGetWindowProperty(event->display, event->data.l[0], x11drv_atom(XdndTypeList), - 0, 65535, FALSE, AnyPropertyType, &acttype, &actfmt, &count, - &bytesret, (unsigned char**)&xdndtypes); - wine_tsx11_unlock(); - } - else - { - count = 3; - xdndtypes = &event->data.l[2]; - } - - if (TRACE_ON(xdnd)) - { - unsigned int i = 0; - - wine_tsx11_lock(); - for (; i < count; i++) + if (xdndtypes[i] != 0) { - if (xdndtypes[i] != 0) - { - char * pn = XGetAtomName(event->display, xdndtypes[i]); - TRACE("XDNDEnterAtom %ld: %s\n", xdndtypes[i], pn); - XFree(pn); - } + char * pn = XGetAtomName(event->display, xdndtypes[i]); + TRACE("XDNDEnterAtom %ld: %s\n", xdndtypes[i], pn); + XFree(pn); } - wine_tsx11_unlock(); } - - /* Do a one-time data read and cache results */ - X11DRV_XDND_ResolveProperty(event->display, event->window, - event->data.l[1], xdndtypes, &count); - - if (event->data.l[1] & 1) - XFree(xdndtypes); - } - else if (event->message_type == x11drv_atom(XdndPosition)) - { - XClientMessageEvent e; - int accept = 0; /* Assume we're not accepting */ - - XDNDxy.x = event->data.l[2] >> 16; - XDNDxy.y = event->data.l[2] & 0xFFFF; - - /* FIXME: Notify OLE of DragEnter. Result determines if we accept */ - - if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) - accept = 1; - - TRACE("XDNDPosition. action req: %ld accept(%d) at x(%ld),y(%ld)\n", - event->data.l[4], accept, XDNDxy.x, XDNDxy.y); - - /* - * Let source know if we're accepting the drop by - * sending a status message. - */ - e.type = ClientMessage; - e.display = event->display; - e.window = event->data.l[0]; - e.message_type = x11drv_atom(XdndStatus); - e.format = 32; - e.data.l[0] = event->window; - e.data.l[1] = accept; - e.data.l[2] = 0; /* Empty Rect */ - e.data.l[3] = 0; /* Empty Rect */ - if (accept) - e.data.l[4] = event->data.l[4]; - else - e.data.l[4] = None; - wine_tsx11_lock(); - XSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e); - wine_tsx11_unlock(); - - /* FIXME: if drag accepted notify OLE of DragOver */ - } - else if (event->message_type == x11drv_atom(XdndDrop)) - { - XClientMessageEvent e; - - TRACE("XDNDDrop\n"); - - /* If we have a HDROP type we send a WM_ACCEPTFILES.*/ - if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) - X11DRV_XDND_SendDropFiles( hWnd ); - - /* FIXME: Notify OLE of Drop */ - X11DRV_XDND_FreeDragDropOp(); - - /* Tell the target we are finished. */ - memset(&e, 0, sizeof(e)); - e.type = ClientMessage; - e.display = event->display; - e.window = event->data.l[0]; - e.message_type = x11drv_atom(XdndFinished); - e.format = 32; - e.data.l[0] = event->window; - wine_tsx11_lock(); - XSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e); wine_tsx11_unlock(); } - else if (event->message_type == x11drv_atom(XdndLeave)) - { - TRACE("DND Operation canceled\n"); - X11DRV_XDND_FreeDragDropOp(); + /* Do a one-time data read and cache results */ + X11DRV_XDND_ResolveProperty(event->display, event->window, + event->data.l[1], xdndtypes, &count); - /* FIXME: Notify OLE of DragLeave */ - } - else /* Not an XDND message */ - isXDNDMsg = 0; + if (event->data.l[1] & 1) + XFree(xdndtypes); +} - return isXDNDMsg; +/************************************************************************** + * X11DRV_XDND_PositionEvent + * + * Handle an XdndPosition event. + */ +void X11DRV_XDND_PositionEvent( HWND hWnd, XClientMessageEvent *event ) +{ + XClientMessageEvent e; + int accept = 0; /* Assume we're not accepting */ + + XDNDxy.x = event->data.l[2] >> 16; + XDNDxy.y = event->data.l[2] & 0xFFFF; + + /* FIXME: Notify OLE of DragEnter. Result determines if we accept */ + + if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) + accept = 1; + + TRACE("action req: %ld accept(%d) at x(%ld),y(%ld)\n", + event->data.l[4], accept, XDNDxy.x, XDNDxy.y); + + /* + * Let source know if we're accepting the drop by + * sending a status message. + */ + e.type = ClientMessage; + e.display = event->display; + e.window = event->data.l[0]; + e.message_type = x11drv_atom(XdndStatus); + e.format = 32; + e.data.l[0] = event->window; + e.data.l[1] = accept; + e.data.l[2] = 0; /* Empty Rect */ + e.data.l[3] = 0; /* Empty Rect */ + if (accept) + e.data.l[4] = event->data.l[4]; + else + e.data.l[4] = None; + wine_tsx11_lock(); + XSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e); + wine_tsx11_unlock(); + + /* FIXME: if drag accepted notify OLE of DragOver */ +} + +/************************************************************************** + * X11DRV_XDND_DropEvent + * + * Handle an XdndDrop event. + */ +void X11DRV_XDND_DropEvent( HWND hWnd, XClientMessageEvent *event ) +{ + XClientMessageEvent e; + + TRACE("\n"); + + /* If we have a HDROP type we send a WM_ACCEPTFILES.*/ + if (GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES) + X11DRV_XDND_SendDropFiles( hWnd ); + + /* FIXME: Notify OLE of Drop */ + X11DRV_XDND_FreeDragDropOp(); + + /* Tell the target we are finished. */ + memset(&e, 0, sizeof(e)); + e.type = ClientMessage; + e.display = event->display; + e.window = event->data.l[0]; + e.message_type = x11drv_atom(XdndFinished); + e.format = 32; + e.data.l[0] = event->window; + wine_tsx11_lock(); + XSendEvent(event->display, event->data.l[0], False, NoEventMask, (XEvent*)&e); + wine_tsx11_unlock(); +} + +/************************************************************************** + * X11DRV_XDND_LeaveEvent + * + * Handle an XdndLeave event. + */ +void X11DRV_XDND_LeaveEvent( HWND hWnd, XClientMessageEvent *event ) +{ + TRACE("DND Operation canceled\n"); + + X11DRV_XDND_FreeDragDropOp(); + + /* FIXME: Notify OLE of DragLeave */ }