Use a dispatch table to handle X client messages.

oldstable
Alexandre Julliard 2005-03-01 11:52:02 +00:00
parent aa34768677
commit 2fd19dfb98
3 changed files with 192 additions and 170 deletions

View File

@ -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 );
}

View File

@ -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 */

View File

@ -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 */
}