Use a dispatch table to handle X client messages.
This commit is contained in:
parent
aa34768677
commit
2fd19dfb98
|
@ -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];
|
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
|
* EVENT_ClientMessage
|
||||||
*/
|
*/
|
||||||
static void EVENT_ClientMessage( HWND hWnd, XEvent *xev )
|
static void EVENT_ClientMessage( HWND hwnd, XEvent *xev )
|
||||||
{
|
{
|
||||||
XClientMessageEvent *event = &xev->xclient;
|
XClientMessageEvent *event = &xev->xclient;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
if (!hWnd) return;
|
if (!hwnd) return;
|
||||||
|
|
||||||
if (event->message_type != None && event->format == 32) {
|
if (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))
|
|
||||||
{
|
{
|
||||||
/* query window (drag&drop event contains only drag window) */
|
WARN( "Don't know how to handle format %d\n", event->format );
|
||||||
Window root, child;
|
return;
|
||||||
int root_x, root_y, child_x, child_y;
|
}
|
||||||
unsigned int u;
|
|
||||||
|
|
||||||
wine_tsx11_lock();
|
for (i = 0; i < sizeof(client_messages)/sizeof(client_messages[0]); i++)
|
||||||
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))
|
|
||||||
{
|
{
|
||||||
#if 0
|
if (event->message_type == X11DRV_Atoms[client_messages[i].atom - FIRST_XATOM])
|
||||||
/* enable this if you want to see the message */
|
{
|
||||||
unsigned char* p_data = NULL;
|
client_messages[i].handler( hwnd, event );
|
||||||
union {
|
return;
|
||||||
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" );
|
|
||||||
}
|
}
|
||||||
}
|
TRACE( "no handler found for %ld\n", event->message_type );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 XIM X11DRV_SetupXIM(Display *display, const char *input_style);
|
||||||
extern void X11DRV_XIMLookupChars( const char *str, DWORD count );
|
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 */
|
/* exported dib functions for now */
|
||||||
|
|
||||||
|
|
|
@ -77,148 +77,156 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
|
||||||
};
|
};
|
||||||
static CRITICAL_SECTION xdnd_cs = { &critsect_debug, -1, 0, 0, 0, 0 };
|
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;
|
Atom acttype;
|
||||||
unsigned long count = 0;
|
int actfmt;
|
||||||
|
unsigned long bytesret;
|
||||||
|
|
||||||
TRACE("XDNDEnter: ver(%ld) check-XdndTypeList(%ld) data=%ld,%ld,%ld,%ld,%ld\n",
|
/* Request supported formats from source window */
|
||||||
(event->data.l[1] & 0xFF000000) >> 24, (event->data.l[1] & 1),
|
wine_tsx11_lock();
|
||||||
event->data.l[0], event->data.l[1], event->data.l[2],
|
XGetWindowProperty(event->display, event->data.l[0], x11drv_atom(XdndTypeList),
|
||||||
event->data.l[3], event->data.l[4]);
|
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
|
if (TRACE_ON(xdnd))
|
||||||
* the entire list. */
|
{
|
||||||
if (event->data.l[1] & 1)
|
unsigned int i = 0;
|
||||||
|
|
||||||
|
wine_tsx11_lock();
|
||||||
|
for (; i < count; i++)
|
||||||
{
|
{
|
||||||
Atom acttype;
|
if (xdndtypes[i] != 0)
|
||||||
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)
|
char * pn = XGetAtomName(event->display, xdndtypes[i]);
|
||||||
{
|
TRACE("XDNDEnterAtom %ld: %s\n", xdndtypes[i], pn);
|
||||||
char * pn = XGetAtomName(event->display, xdndtypes[i]);
|
XFree(pn);
|
||||||
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();
|
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 */
|
if (event->data.l[1] & 1)
|
||||||
}
|
XFree(xdndtypes);
|
||||||
else /* Not an XDND message */
|
}
|
||||||
isXDNDMsg = 0;
|
|
||||||
|
|
||||||
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue