1998-12-07 09:13:40 +00:00
|
|
|
/*
|
1998-12-26 12:00:43 +00:00
|
|
|
* X11 event driver
|
1998-12-07 09:13:40 +00:00
|
|
|
*
|
|
|
|
* Copyright 1993 Alexandre Julliard
|
1999-09-20 15:42:47 +00:00
|
|
|
* 1999 Noel Borthwick
|
2002-03-09 23:29:33 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
1998-12-07 09:13:40 +00:00
|
|
|
*/
|
|
|
|
|
2003-01-03 19:12:55 +00:00
|
|
|
#define COM_NO_WINDOWS_H
|
1998-12-07 09:13:40 +00:00
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/keysym.h>
|
2003-11-21 21:48:36 +00:00
|
|
|
#include <X11/Xlib.h>
|
2002-09-24 18:36:51 +00:00
|
|
|
#include <X11/Xresource.h>
|
|
|
|
#include <X11/Xutil.h>
|
1999-12-12 19:42:47 +00:00
|
|
|
#ifdef HAVE_LIBXXF86DGA2
|
2002-09-24 18:36:51 +00:00
|
|
|
#include <X11/extensions/xf86dga.h>
|
1999-12-12 19:42:47 +00:00
|
|
|
#endif
|
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
#include <assert.h>
|
2003-09-05 23:08:26 +00:00
|
|
|
#include <stdarg.h>
|
1998-12-07 09:13:40 +00:00
|
|
|
#include <string.h>
|
2000-09-16 20:58:06 +00:00
|
|
|
#include "wine/winuser16.h"
|
2003-09-05 23:08:26 +00:00
|
|
|
#include "windef.h"
|
|
|
|
#include "winbase.h"
|
|
|
|
#include "winuser.h"
|
|
|
|
#include "wingdi.h"
|
2000-09-25 23:56:41 +00:00
|
|
|
#include "shlobj.h" /* DROPFILES */
|
2000-09-16 20:58:06 +00:00
|
|
|
|
2000-03-08 18:26:56 +00:00
|
|
|
#include "win.h"
|
2001-06-26 19:36:23 +00:00
|
|
|
#include "winreg.h"
|
1998-12-07 09:13:40 +00:00
|
|
|
#include "x11drv.h"
|
2001-01-02 21:00:46 +00:00
|
|
|
#include "shellapi.h"
|
2002-12-03 23:34:52 +00:00
|
|
|
#include "wine/debug.h"
|
1999-04-19 14:56:29 +00:00
|
|
|
|
2002-03-09 23:29:33 +00:00
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(event);
|
2003-06-23 23:02:02 +00:00
|
|
|
WINE_DECLARE_DEBUG_CHANNEL(clipboard);
|
2002-05-31 23:06:46 +00:00
|
|
|
|
2004-01-21 02:22:26 +00:00
|
|
|
extern BOOL ximInComposeMode;
|
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
#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
|
|
|
|
|
|
|
|
#define DndEND 8
|
|
|
|
|
|
|
|
#define DndURL 128 /* KDE drag&drop */
|
|
|
|
|
|
|
|
static const char * const event_names[] =
|
|
|
|
{
|
|
|
|
"", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
|
|
|
|
"MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
|
|
|
|
"KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
|
|
|
|
"CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
|
|
|
|
"ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
|
|
|
|
"ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
|
|
|
|
"SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
|
|
|
|
"ClientMessage", "MappingNotify"
|
|
|
|
};
|
|
|
|
|
1999-09-20 15:42:47 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
static void EVENT_ProcessEvent( XEvent *event );
|
|
|
|
|
|
|
|
/* Event handlers */
|
1999-04-15 15:22:23 +00:00
|
|
|
static void EVENT_FocusIn( HWND hWnd, XFocusChangeEvent *event );
|
|
|
|
static void EVENT_FocusOut( HWND hWnd, XFocusChangeEvent *event );
|
1999-09-20 15:42:47 +00:00
|
|
|
static void EVENT_PropertyNotify( XPropertyEvent *event );
|
1999-04-15 15:22:23 +00:00
|
|
|
static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event );
|
1998-12-07 09:13:40 +00:00
|
|
|
|
1999-12-12 19:42:47 +00:00
|
|
|
#ifdef HAVE_LIBXXF86DGA2
|
|
|
|
static int DGAMotionEventType;
|
|
|
|
static int DGAButtonPressEventType;
|
|
|
|
static int DGAButtonReleaseEventType;
|
|
|
|
static int DGAKeyPressEventType;
|
|
|
|
static int DGAKeyReleaseEventType;
|
|
|
|
|
|
|
|
static BOOL DGAUsed = FALSE;
|
|
|
|
static HWND DGAhwnd = 0;
|
|
|
|
#endif
|
|
|
|
|
1999-11-07 21:25:57 +00:00
|
|
|
/* Static used for the current input method */
|
|
|
|
static INPUT_TYPE current_input_type = X11DRV_INPUT_ABSOLUTE;
|
|
|
|
static BOOL in_transition = FALSE; /* This is not used as for today */
|
1998-12-07 09:13:40 +00:00
|
|
|
|
|
|
|
|
1999-07-10 10:24:31 +00:00
|
|
|
/***********************************************************************
|
2001-05-16 19:52:29 +00:00
|
|
|
* process_events
|
1999-07-10 10:24:31 +00:00
|
|
|
*/
|
2001-06-04 21:55:17 +00:00
|
|
|
static int process_events( struct x11drv_thread_data *data )
|
1999-02-21 18:15:26 +00:00
|
|
|
{
|
1999-05-22 18:57:17 +00:00
|
|
|
XEvent event;
|
2001-06-04 21:55:17 +00:00
|
|
|
int count = 0;
|
1999-02-21 18:15:26 +00:00
|
|
|
|
2001-01-15 22:31:24 +00:00
|
|
|
wine_tsx11_lock();
|
2001-06-04 21:55:17 +00:00
|
|
|
while ( XPending( data->display ) )
|
1999-05-22 18:57:17 +00:00
|
|
|
{
|
2003-01-23 01:29:58 +00:00
|
|
|
Bool ignore;
|
|
|
|
|
2001-06-04 21:55:17 +00:00
|
|
|
XNextEvent( data->display, &event );
|
2003-01-23 01:29:58 +00:00
|
|
|
ignore = XFilterEvent( &event, None );
|
2001-01-15 22:31:24 +00:00
|
|
|
wine_tsx11_unlock();
|
2003-01-23 01:29:58 +00:00
|
|
|
if (!ignore) EVENT_ProcessEvent( &event );
|
2001-06-04 21:55:17 +00:00
|
|
|
count++;
|
2001-01-15 22:31:24 +00:00
|
|
|
wine_tsx11_lock();
|
1999-05-22 18:57:17 +00:00
|
|
|
}
|
2001-01-15 22:31:24 +00:00
|
|
|
wine_tsx11_unlock();
|
2001-06-04 21:55:17 +00:00
|
|
|
return count;
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
2001-05-16 19:52:29 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
/***********************************************************************
|
2001-05-18 22:51:56 +00:00
|
|
|
* MsgWaitForMultipleObjectsEx (X11DRV.@)
|
1998-12-07 09:13:40 +00:00
|
|
|
*/
|
2001-05-18 22:51:56 +00:00
|
|
|
DWORD X11DRV_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
|
|
|
|
DWORD timeout, DWORD mask, DWORD flags )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2001-05-16 19:52:29 +00:00
|
|
|
HANDLE new_handles[MAXIMUM_WAIT_OBJECTS+1]; /* FIXME! */
|
|
|
|
DWORD i, ret;
|
|
|
|
struct x11drv_thread_data *data = NtCurrentTeb()->driver_data;
|
|
|
|
|
|
|
|
if (!data || data->process_event_count)
|
2001-05-18 22:51:56 +00:00
|
|
|
return WaitForMultipleObjectsEx( count, handles, flags & MWMO_WAITALL,
|
|
|
|
timeout, flags & MWMO_ALERTABLE );
|
2001-05-16 19:52:29 +00:00
|
|
|
|
2003-05-19 19:07:32 +00:00
|
|
|
/* check whether only server queue handle was passed in */
|
|
|
|
if (count < 2) flags &= ~MWMO_WAITALL;
|
|
|
|
|
2001-05-16 19:52:29 +00:00
|
|
|
for (i = 0; i < count; i++) new_handles[i] = handles[i];
|
|
|
|
new_handles[count] = data->display_fd;
|
|
|
|
|
|
|
|
wine_tsx11_lock();
|
|
|
|
XFlush( gdi_display );
|
|
|
|
XFlush( data->display );
|
|
|
|
wine_tsx11_unlock();
|
2001-06-04 21:55:17 +00:00
|
|
|
|
|
|
|
data->process_event_count++;
|
|
|
|
if (process_events( data )) ret = count;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = WaitForMultipleObjectsEx( count+1, new_handles, flags & MWMO_WAITALL,
|
|
|
|
timeout, flags & MWMO_ALERTABLE );
|
|
|
|
if (ret == count) process_events( data );
|
|
|
|
}
|
2001-05-16 19:52:29 +00:00
|
|
|
data->process_event_count--;
|
|
|
|
return ret;
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
2005-01-14 17:06:40 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* EVENT_x11_time_to_win32_time
|
|
|
|
*
|
|
|
|
* Make our timer and the X timer line up as best we can
|
|
|
|
* Pass 0 to retrieve the current adjustment value (times -1)
|
|
|
|
*/
|
|
|
|
DWORD EVENT_x11_time_to_win32_time(Time time)
|
|
|
|
{
|
|
|
|
static DWORD adjust = 0;
|
|
|
|
DWORD now = GetTickCount();
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
if (! adjust && time != 0)
|
|
|
|
{
|
|
|
|
ret = now;
|
|
|
|
adjust = time - now;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* If we got an event in the 'future', then our clock is clearly wrong.
|
|
|
|
If we got it more than 10000 ms in the future, then it's most likely
|
|
|
|
that the clock has wrapped. */
|
|
|
|
|
|
|
|
ret = time - adjust;
|
|
|
|
if (ret > now && ((ret - now) < 10000) && time != 0)
|
|
|
|
{
|
|
|
|
adjust += ret - now;
|
|
|
|
ret -= ret - now;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
}
|
2001-05-16 19:52:29 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* EVENT_ProcessEvent
|
|
|
|
*
|
|
|
|
* Process an X event.
|
|
|
|
*/
|
|
|
|
static void EVENT_ProcessEvent( XEvent *event )
|
|
|
|
{
|
1999-04-15 15:22:23 +00:00
|
|
|
HWND hWnd;
|
2001-05-16 19:52:29 +00:00
|
|
|
Display *display = event->xany.display;
|
1999-03-16 10:37:30 +00:00
|
|
|
|
1999-12-08 03:56:23 +00:00
|
|
|
TRACE( "called.\n" );
|
1999-05-22 18:57:17 +00:00
|
|
|
|
1999-03-16 10:37:30 +00:00
|
|
|
switch (event->type)
|
1999-04-01 12:03:52 +00:00
|
|
|
{
|
|
|
|
case SelectionNotify: /* all of these should be caught by XCheckTypedWindowEvent() */
|
1999-12-08 03:56:23 +00:00
|
|
|
FIXME("Got SelectionNotify - must not happen!\n");
|
1999-04-01 12:03:52 +00:00
|
|
|
/* fall through */
|
|
|
|
|
1999-03-16 10:37:30 +00:00
|
|
|
/* We get all these because of StructureNotifyMask.
|
|
|
|
This check is placed here to avoid getting error messages below,
|
|
|
|
as X might send some of these even for windows that have already
|
|
|
|
been deleted ... */
|
|
|
|
case CirculateNotify:
|
|
|
|
case CreateNotify:
|
|
|
|
case DestroyNotify:
|
|
|
|
case GravityNotify:
|
|
|
|
case ReparentNotify:
|
|
|
|
return;
|
1999-04-01 12:03:52 +00:00
|
|
|
}
|
1999-11-07 22:44:06 +00:00
|
|
|
|
1999-12-12 19:42:47 +00:00
|
|
|
#ifdef HAVE_LIBXXF86DGA2
|
|
|
|
if (DGAUsed) {
|
|
|
|
if (event->type == DGAMotionEventType) {
|
|
|
|
TRACE("DGAMotionEvent received.\n");
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_DGAMotionEvent( DGAhwnd, (XDGAMotionEvent *)event );
|
1999-12-12 19:42:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event->type == DGAButtonPressEventType) {
|
|
|
|
TRACE("DGAButtonPressEvent received.\n");
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_DGAButtonPressEvent( DGAhwnd, (XDGAButtonEvent *)event );
|
1999-12-12 19:42:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event->type == DGAButtonReleaseEventType) {
|
|
|
|
TRACE("DGAButtonReleaseEvent received.\n");
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_DGAButtonReleaseEvent( DGAhwnd, (XDGAButtonEvent *)event );
|
1999-12-12 19:42:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((event->type == DGAKeyPressEventType) ||
|
|
|
|
(event->type == DGAKeyReleaseEventType)) {
|
1999-12-12 21:28:44 +00:00
|
|
|
/* Fill a XKeyEvent to send to EVENT_Key */
|
1999-12-12 19:42:47 +00:00
|
|
|
XKeyEvent ke;
|
1999-12-12 21:28:44 +00:00
|
|
|
XDGAKeyEvent *evt = (XDGAKeyEvent *) event;
|
1999-12-12 19:42:47 +00:00
|
|
|
|
|
|
|
TRACE("DGAKeyPress/ReleaseEvent received.\n");
|
2002-05-31 23:06:46 +00:00
|
|
|
|
1999-12-12 21:28:44 +00:00
|
|
|
if (evt->type == DGAKeyReleaseEventType)
|
|
|
|
ke.type = KeyRelease;
|
|
|
|
else
|
|
|
|
ke.type = KeyPress;
|
|
|
|
ke.serial = evt->serial;
|
|
|
|
ke.send_event = FALSE;
|
|
|
|
ke.display = evt->display;
|
|
|
|
ke.window = 0;
|
|
|
|
ke.root = 0;
|
|
|
|
ke.subwindow = 0;
|
|
|
|
ke.time = evt->time;
|
2001-10-17 17:50:02 +00:00
|
|
|
ke.x = -1;
|
|
|
|
ke.y = -1;
|
1999-12-12 21:28:44 +00:00
|
|
|
ke.x_root = -1;
|
|
|
|
ke.y_root = -1;
|
|
|
|
ke.state = evt->state;
|
|
|
|
ke.keycode = evt->keycode;
|
|
|
|
ke.same_screen = TRUE;
|
2001-10-17 17:50:02 +00:00
|
|
|
X11DRV_KeyEvent( 0, &ke );
|
1999-12-12 19:42:47 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2001-06-04 21:55:17 +00:00
|
|
|
|
2002-09-24 18:36:51 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
if (XFindContext( display, event->xany.window, winContext, (char **)&hWnd ) != 0)
|
1999-05-22 18:57:17 +00:00
|
|
|
hWnd = 0; /* Not for a registered window */
|
2002-09-24 18:36:51 +00:00
|
|
|
wine_tsx11_unlock();
|
2003-06-23 23:02:02 +00:00
|
|
|
if (!hWnd && event->xany.window == root_window) hWnd = GetDesktopWindow();
|
1999-04-15 15:22:23 +00:00
|
|
|
|
2004-03-19 01:17:32 +00:00
|
|
|
if (!hWnd && event->type != PropertyNotify &&
|
|
|
|
event->type != MappingNotify && event->type != KeymapNotify)
|
2001-06-04 21:55:17 +00:00
|
|
|
WARN( "Got event %s for unknown Window %08lx\n",
|
|
|
|
event_names[event->type], event->xany.window );
|
2004-01-09 00:03:00 +00:00
|
|
|
else if (event->type <= MappingNotify)
|
|
|
|
TRACE("Got event %s for hwnd/window %p/%lx, GetFocus()=%p\n",
|
|
|
|
event_names[event->type], hWnd, event->xany.window, GetFocus() );
|
1999-03-10 13:26:09 +00:00
|
|
|
else
|
2004-01-09 00:03:00 +00:00
|
|
|
TRACE("Got extension event for hwnd/window %p/%lx, GetFocus()=%p\n",
|
|
|
|
hWnd, event->xany.window, GetFocus() );
|
|
|
|
|
|
|
|
if (X11DRV_ProcessTabletEvent(hWnd, event))
|
|
|
|
{
|
|
|
|
TRACE("Return: filtered by tablet\n");
|
|
|
|
return;
|
|
|
|
}
|
1999-04-15 15:22:23 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
switch(event->type)
|
|
|
|
{
|
|
|
|
case KeyPress:
|
|
|
|
case KeyRelease:
|
2001-10-17 17:50:02 +00:00
|
|
|
/* FIXME: should generate a motion event if event point is different from current pos */
|
|
|
|
X11DRV_KeyEvent( hWnd, (XKeyEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-10-18 21:38:59 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case ButtonPress:
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_ButtonPress( hWnd, (XButtonEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-10-18 21:38:59 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case ButtonRelease:
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_ButtonRelease( hWnd, (XButtonEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-06-25 20:01:03 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case MotionNotify:
|
2001-10-18 21:38:59 +00:00
|
|
|
X11DRV_MotionNotify( hWnd, (XMotionEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
1999-07-24 12:16:00 +00:00
|
|
|
|
2002-06-14 00:08:40 +00:00
|
|
|
case EnterNotify:
|
|
|
|
X11DRV_EnterNotify( hWnd, (XCrossingEvent*)event );
|
|
|
|
break;
|
|
|
|
|
2001-06-04 21:55:17 +00:00
|
|
|
case FocusIn:
|
|
|
|
EVENT_FocusIn( hWnd, (XFocusChangeEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-06-04 21:55:17 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case FocusOut:
|
1999-04-15 15:22:23 +00:00
|
|
|
EVENT_FocusOut( hWnd, (XFocusChangeEvent*)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-06-04 21:55:17 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case Expose:
|
2001-06-22 03:42:27 +00:00
|
|
|
X11DRV_Expose( hWnd, &event->xexpose );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2001-06-04 21:55:17 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case ConfigureNotify:
|
2001-05-16 19:52:29 +00:00
|
|
|
if (!hWnd) return;
|
2001-06-04 21:55:17 +00:00
|
|
|
X11DRV_ConfigureNotify( hWnd, &event->xconfigure );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionRequest:
|
2005-02-25 21:01:15 +00:00
|
|
|
X11DRV_SelectionRequest( hWnd, (XSelectionRequestEvent *)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SelectionClear:
|
2005-02-25 21:01:15 +00:00
|
|
|
X11DRV_SelectionClear( hWnd, (XSelectionClearEvent*) event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
2002-05-31 23:06:46 +00:00
|
|
|
|
1999-09-20 15:42:47 +00:00
|
|
|
case PropertyNotify:
|
|
|
|
EVENT_PropertyNotify( (XPropertyEvent *)event );
|
|
|
|
break;
|
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case ClientMessage:
|
2001-05-16 19:52:29 +00:00
|
|
|
if (!hWnd) return;
|
1999-04-15 15:22:23 +00:00
|
|
|
EVENT_ClientMessage( hWnd, (XClientMessageEvent *) event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NoExpose:
|
|
|
|
break;
|
2001-06-04 21:55:17 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
case MapNotify:
|
2001-06-04 21:55:17 +00:00
|
|
|
X11DRV_MapNotify( hWnd, (XMapEvent *)event );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
1999-04-01 12:03:52 +00:00
|
|
|
|
|
|
|
case UnmapNotify:
|
2001-06-04 21:55:17 +00:00
|
|
|
X11DRV_UnmapNotify( hWnd, (XUnmapEvent *)event );
|
1999-04-01 12:03:52 +00:00
|
|
|
break;
|
|
|
|
|
2001-10-18 21:38:59 +00:00
|
|
|
case KeymapNotify:
|
|
|
|
X11DRV_KeymapNotify( hWnd, (XKeymapEvent *)event );
|
|
|
|
break;
|
|
|
|
|
2000-04-16 17:07:27 +00:00
|
|
|
case MappingNotify:
|
2001-10-17 17:50:02 +00:00
|
|
|
X11DRV_MappingNotify( (XMappingEvent *) event );
|
2000-04-16 17:07:27 +00:00
|
|
|
break;
|
|
|
|
|
2002-05-31 23:06:46 +00:00
|
|
|
default:
|
2002-10-31 02:38:20 +00:00
|
|
|
WARN("Unprocessed event %s for hwnd %p\n", event_names[event->type], hWnd );
|
1998-12-07 09:13:40 +00:00
|
|
|
break;
|
|
|
|
}
|
1999-12-08 03:56:23 +00:00
|
|
|
TRACE( "returns.\n" );
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-10-11 23:41:06 +00:00
|
|
|
/*******************************************************************
|
|
|
|
* can_activate_window
|
|
|
|
*
|
|
|
|
* Check if we can activate the specified window.
|
|
|
|
*/
|
|
|
|
inline static BOOL can_activate_window( HWND hwnd )
|
|
|
|
{
|
|
|
|
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
|
|
|
|
if (!(style & WS_VISIBLE)) return FALSE;
|
|
|
|
if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
|
|
|
|
return !(style & WS_DISABLED);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-09-18 23:09:50 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* set_focus
|
|
|
|
*/
|
|
|
|
static void set_focus( HWND hwnd, Time time )
|
|
|
|
{
|
2002-10-11 23:41:06 +00:00
|
|
|
HWND focus;
|
2002-09-18 23:09:50 +00:00
|
|
|
Window win;
|
2001-06-04 21:55:17 +00:00
|
|
|
|
2002-10-31 02:38:20 +00:00
|
|
|
TRACE( "setting foreground window to %p\n", hwnd );
|
2002-10-11 23:41:06 +00:00
|
|
|
SetForegroundWindow( hwnd );
|
2001-06-04 21:55:17 +00:00
|
|
|
|
2002-09-18 23:09:50 +00:00
|
|
|
focus = GetFocus();
|
2003-01-21 20:16:20 +00:00
|
|
|
if (focus) focus = GetAncestor( focus, GA_ROOT );
|
2002-09-18 23:09:50 +00:00
|
|
|
win = X11DRV_get_whole_window(focus);
|
|
|
|
|
|
|
|
if (win)
|
|
|
|
{
|
2002-10-31 02:38:20 +00:00
|
|
|
TRACE( "setting focus to %p (%lx) time=%ld\n", focus, win, time );
|
2003-11-21 05:30:34 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XSetInputFocus( thread_display(), win, RevertToParent, time );
|
|
|
|
wine_tsx11_unlock();
|
2002-09-18 23:09:50 +00:00
|
|
|
}
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
2002-09-18 23:09:50 +00:00
|
|
|
* handle_wm_protocols_message
|
1998-12-07 09:13:40 +00:00
|
|
|
*/
|
2002-09-18 23:09:50 +00:00
|
|
|
static void handle_wm_protocols_message( HWND hwnd, XClientMessageEvent *event )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2002-09-18 23:09:50 +00:00
|
|
|
Atom protocol = (Atom)event->data.l[0];
|
|
|
|
|
|
|
|
if (!protocol) return;
|
1999-10-13 13:49:01 +00:00
|
|
|
|
2003-11-20 04:24:18 +00:00
|
|
|
if (protocol == x11drv_atom(WM_DELETE_WINDOW))
|
2002-09-18 23:09:50 +00:00
|
|
|
{
|
|
|
|
/* Ignore the delete window request if the window has been disabled
|
|
|
|
* and we are in managed mode. This is to disallow applications from
|
|
|
|
* being closed by the window manager while in a modal state.
|
|
|
|
*/
|
2005-02-23 21:47:32 +00:00
|
|
|
if (IsWindowEnabled(hwnd)) PostMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, 0 );
|
2002-09-18 23:09:50 +00:00
|
|
|
}
|
2003-11-20 04:24:18 +00:00
|
|
|
else if (protocol == x11drv_atom(WM_TAKE_FOCUS))
|
2001-06-04 21:55:17 +00:00
|
|
|
{
|
2002-09-18 23:09:50 +00:00
|
|
|
Time event_time = (Time)event->data.l[1];
|
|
|
|
HWND last_focus = x11drv_thread_data()->last_focus;
|
|
|
|
|
2002-10-31 02:38:20 +00:00
|
|
|
TRACE( "got take focus msg for %p, enabled=%d, focus=%p, active=%p, fg=%p, last=%p\n",
|
2002-09-18 23:09:50 +00:00
|
|
|
hwnd, IsWindowEnabled(hwnd), GetFocus(), GetActiveWindow(),
|
|
|
|
GetForegroundWindow(), last_focus );
|
|
|
|
|
2002-10-11 23:41:06 +00:00
|
|
|
if (can_activate_window(hwnd))
|
2001-06-04 21:55:17 +00:00
|
|
|
{
|
2002-09-18 23:09:50 +00:00
|
|
|
/* simulate a mouse click on the caption to find out
|
|
|
|
* whether the window wants to be activated */
|
|
|
|
LRESULT ma = SendMessageW( hwnd, WM_MOUSEACTIVATE,
|
2002-10-31 02:38:20 +00:00
|
|
|
(WPARAM)GetAncestor( hwnd, GA_ROOT ),
|
2002-09-18 23:09:50 +00:00
|
|
|
MAKELONG(HTCAPTION,WM_LBUTTONDOWN) );
|
|
|
|
if (ma != MA_NOACTIVATEANDEAT && ma != MA_NOACTIVATE) set_focus( hwnd, event_time );
|
2002-10-31 02:38:20 +00:00
|
|
|
else TRACE( "not setting focus to %p (%lx), ma=%ld\n", hwnd, event->window, ma );
|
2001-06-04 21:55:17 +00:00
|
|
|
}
|
2002-09-18 23:09:50 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
hwnd = GetFocus();
|
2003-01-21 20:16:20 +00:00
|
|
|
if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
|
2002-09-18 23:09:50 +00:00
|
|
|
if (!hwnd) hwnd = GetActiveWindow();
|
|
|
|
if (!hwnd) hwnd = last_focus;
|
2002-10-11 23:41:06 +00:00
|
|
|
if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, event_time );
|
2002-09-18 23:09:50 +00:00
|
|
|
}
|
2003-11-20 04:24:18 +00:00
|
|
|
}
|
|
|
|
else if (protocol == x11drv_atom(_NET_WM_PING))
|
|
|
|
{
|
2003-05-04 02:27:20 +00:00
|
|
|
XClientMessageEvent xev;
|
|
|
|
xev = *event;
|
|
|
|
|
|
|
|
TRACE("NET_WM Ping\n");
|
|
|
|
xev.window = DefaultRootWindow(xev.display);
|
|
|
|
XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
|
|
|
|
/* this line is semi-stolen from gtk2 */
|
|
|
|
TRACE("NET_WM Pong\n");
|
2002-09-18 23:09:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char * const focus_details[] =
|
|
|
|
{
|
|
|
|
"NotifyAncestor",
|
|
|
|
"NotifyVirtual",
|
|
|
|
"NotifyInferior",
|
|
|
|
"NotifyNonlinear",
|
|
|
|
"NotifyNonlinearVirtual",
|
|
|
|
"NotifyPointer",
|
|
|
|
"NotifyPointerRoot",
|
|
|
|
"NotifyDetailNone"
|
|
|
|
};
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* EVENT_FocusIn
|
|
|
|
*/
|
|
|
|
static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
|
|
|
|
{
|
2003-01-23 01:29:58 +00:00
|
|
|
XIC xic;
|
|
|
|
|
2002-09-18 23:09:50 +00:00
|
|
|
if (!hwnd) return;
|
|
|
|
|
2002-10-31 02:38:20 +00:00
|
|
|
TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
|
2002-09-18 23:09:50 +00:00
|
|
|
|
|
|
|
if (event->detail == NotifyPointer) return;
|
|
|
|
|
2003-01-23 01:29:58 +00:00
|
|
|
if ((xic = X11DRV_get_ic( hwnd )))
|
|
|
|
{
|
|
|
|
wine_tsx11_lock();
|
|
|
|
XSetICFocus( xic );
|
|
|
|
wine_tsx11_unlock();
|
|
|
|
}
|
2003-11-20 04:24:18 +00:00
|
|
|
if (use_take_focus) return; /* ignore FocusIn if we are using take focus */
|
2003-01-23 01:29:58 +00:00
|
|
|
|
2002-10-11 23:41:06 +00:00
|
|
|
if (!can_activate_window(hwnd))
|
2002-09-18 23:09:50 +00:00
|
|
|
{
|
|
|
|
HWND hwnd = GetFocus();
|
2003-01-21 20:16:20 +00:00
|
|
|
if (hwnd) hwnd = GetAncestor( hwnd, GA_ROOT );
|
2002-09-18 23:09:50 +00:00
|
|
|
if (!hwnd) hwnd = GetActiveWindow();
|
|
|
|
if (!hwnd) hwnd = x11drv_thread_data()->last_focus;
|
2002-10-11 23:41:06 +00:00
|
|
|
if (hwnd && can_activate_window(hwnd)) set_focus( hwnd, CurrentTime );
|
2001-06-04 21:55:17 +00:00
|
|
|
}
|
2002-10-11 23:41:06 +00:00
|
|
|
else SetForegroundWindow( hwnd );
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
2002-09-18 23:09:50 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
/**********************************************************************
|
2002-09-18 23:09:50 +00:00
|
|
|
* EVENT_FocusOut
|
|
|
|
*
|
|
|
|
* Note: only top-level windows get FocusOut events.
|
1998-12-07 09:13:40 +00:00
|
|
|
*/
|
2002-09-18 23:09:50 +00:00
|
|
|
static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2002-09-18 23:09:50 +00:00
|
|
|
HWND hwnd_tmp;
|
|
|
|
Window focus_win;
|
|
|
|
int revert;
|
2003-01-23 01:29:58 +00:00
|
|
|
XIC xic;
|
2002-09-18 23:09:50 +00:00
|
|
|
|
2004-09-29 21:11:28 +00:00
|
|
|
if (!hwnd) return;
|
|
|
|
|
2002-10-31 02:38:20 +00:00
|
|
|
TRACE( "win %p xwin %lx detail=%s\n", hwnd, event->window, focus_details[event->detail] );
|
2002-09-18 23:09:50 +00:00
|
|
|
|
|
|
|
if (event->detail == NotifyPointer) return;
|
2004-01-21 02:22:26 +00:00
|
|
|
if (ximInComposeMode) return;
|
|
|
|
|
2002-10-11 23:41:06 +00:00
|
|
|
x11drv_thread_data()->last_focus = hwnd;
|
2003-01-23 01:29:58 +00:00
|
|
|
if ((xic = X11DRV_get_ic( hwnd )))
|
|
|
|
{
|
|
|
|
wine_tsx11_lock();
|
|
|
|
XUnsetICFocus( xic );
|
|
|
|
wine_tsx11_unlock();
|
|
|
|
}
|
2002-09-18 23:09:50 +00:00
|
|
|
if (hwnd != GetForegroundWindow()) return;
|
|
|
|
SendMessageA( hwnd, WM_CANCELMODE, 0, 0 );
|
|
|
|
|
|
|
|
/* don't reset the foreground window, if the window which is
|
|
|
|
getting the focus is a Wine window */
|
|
|
|
|
2002-09-24 18:36:51 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XGetInputFocus( thread_display(), &focus_win, &revert );
|
|
|
|
if (focus_win)
|
|
|
|
{
|
|
|
|
if (XFindContext( thread_display(), focus_win, winContext, (char **)&hwnd_tmp ) != 0)
|
|
|
|
focus_win = 0;
|
|
|
|
}
|
|
|
|
wine_tsx11_unlock();
|
|
|
|
|
|
|
|
if (!focus_win)
|
2002-09-18 23:09:50 +00:00
|
|
|
{
|
|
|
|
/* Abey : 6-Oct-99. Check again if the focus out window is the
|
|
|
|
Foreground window, because in most cases the messages sent
|
|
|
|
above must have already changed the foreground window, in which
|
|
|
|
case we don't have to change the foreground window to 0 */
|
|
|
|
if (hwnd == GetForegroundWindow())
|
|
|
|
{
|
|
|
|
TRACE( "lost focus, setting fg to 0\n" );
|
|
|
|
SetForegroundWindow( 0 );
|
|
|
|
}
|
|
|
|
}
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-09-20 15:42:47 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* EVENT_PropertyNotify
|
|
|
|
* We use this to release resources like Pixmaps when a selection
|
|
|
|
* client no longer needs them.
|
|
|
|
*/
|
|
|
|
static void EVENT_PropertyNotify( XPropertyEvent *event )
|
|
|
|
{
|
|
|
|
/* Check if we have any resources to free */
|
2001-05-09 17:31:31 +00:00
|
|
|
TRACE("Received PropertyNotify event: \n");
|
1999-09-20 15:42:47 +00:00
|
|
|
|
|
|
|
switch(event->state)
|
|
|
|
{
|
|
|
|
case PropertyDelete:
|
|
|
|
{
|
2003-11-21 21:48:36 +00:00
|
|
|
TRACE("\tPropertyDelete for atom %ld on window %ld\n",
|
|
|
|
event->atom, (long)event->window);
|
1999-09-20 15:42:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case PropertyNewValue:
|
|
|
|
{
|
2003-11-21 21:48:36 +00:00
|
|
|
TRACE("\tPropertyNewValue for atom %ld on window %ld\n\n",
|
|
|
|
event->atom, (long)event->window);
|
1999-09-20 15:42:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2002-05-31 23:06:46 +00:00
|
|
|
|
1999-09-20 15:42:47 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1998-12-07 09:13:40 +00:00
|
|
|
|
2002-09-23 20:56:37 +00:00
|
|
|
static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
|
|
|
|
{
|
|
|
|
RECT tempRect;
|
|
|
|
|
|
|
|
if (!IsWindowEnabled(hQueryWnd)) return 0;
|
|
|
|
|
|
|
|
GetWindowRect(hQueryWnd, &tempRect);
|
|
|
|
|
|
|
|
if(!PtInRect(&tempRect, *lpPt)) return 0;
|
|
|
|
|
|
|
|
if (!IsIconic( hQueryWnd ))
|
|
|
|
{
|
|
|
|
GetClientRect( hQueryWnd, &tempRect );
|
|
|
|
MapWindowPoints( hQueryWnd, 0, (LPPOINT)&tempRect, 2 );
|
|
|
|
|
|
|
|
if (PtInRect( &tempRect, *lpPt))
|
|
|
|
{
|
|
|
|
HWND *list = WIN_ListChildren( hQueryWnd );
|
|
|
|
HWND bResult = 0;
|
|
|
|
|
|
|
|
if (list)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; list[i]; i++)
|
|
|
|
{
|
|
|
|
if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)
|
|
|
|
{
|
|
|
|
GetWindowRect( list[i], &tempRect );
|
|
|
|
if (PtInRect( &tempRect, *lpPt )) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (list[i])
|
|
|
|
{
|
|
|
|
if (IsWindowEnabled( list[i] ))
|
|
|
|
bResult = find_drop_window( list[i], lpPt );
|
|
|
|
}
|
|
|
|
HeapFree( GetProcessHeap(), 0, list );
|
|
|
|
}
|
|
|
|
if(bResult) return bResult;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
|
|
|
|
|
|
|
|
ScreenToClient(hQueryWnd, lpPt);
|
|
|
|
|
|
|
|
return hQueryWnd;
|
|
|
|
}
|
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
/**********************************************************************
|
|
|
|
* EVENT_DropFromOffix
|
|
|
|
*
|
|
|
|
* don't know if it still works (last Changlog is from 96/11/04)
|
|
|
|
*/
|
1999-04-15 15:22:23 +00:00
|
|
|
static void EVENT_DropFromOffiX( HWND hWnd, XClientMessageEvent *event )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2002-09-23 20:56:37 +00:00
|
|
|
unsigned long data_length;
|
|
|
|
unsigned long aux_long;
|
|
|
|
unsigned char* p_data = NULL;
|
|
|
|
union {
|
|
|
|
Atom atom_aux;
|
|
|
|
struct {
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
} pt_aux;
|
|
|
|
int i;
|
|
|
|
} u;
|
|
|
|
int x, y;
|
|
|
|
BOOL bAccept;
|
2005-01-17 19:17:47 +00:00
|
|
|
Window win, w_aux_root, w_aux_child;
|
2002-09-23 20:56:37 +00:00
|
|
|
WND* pWnd;
|
|
|
|
HWND hScope = hWnd;
|
|
|
|
|
2005-01-17 19:17:47 +00:00
|
|
|
win = X11DRV_get_whole_window(hWnd);
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
2005-01-17 19:17:47 +00:00
|
|
|
XQueryPointer( event->display, win, &w_aux_root, &w_aux_child,
|
2003-11-21 21:48:36 +00:00
|
|
|
&x, &y, (int *) &u.pt_aux.x, (int *) &u.pt_aux.y,
|
|
|
|
(unsigned int*)&aux_long);
|
|
|
|
wine_tsx11_unlock();
|
2002-09-23 20:56:37 +00:00
|
|
|
|
2005-01-20 20:07:42 +00:00
|
|
|
pWnd = WIN_GetPtr(hWnd);
|
2005-01-17 19:17:47 +00:00
|
|
|
|
2002-09-23 20:56:37 +00:00
|
|
|
/* 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 = 0;
|
|
|
|
y = 0;
|
|
|
|
}
|
|
|
|
else
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2002-09-23 20:56:37 +00:00
|
|
|
POINT pt = { x, y };
|
|
|
|
HWND hwndDrop = find_drop_window( hWnd, &pt );
|
|
|
|
if (hwndDrop)
|
|
|
|
{
|
|
|
|
x = pt.x;
|
|
|
|
y = pt.y;
|
|
|
|
hScope = hwndDrop;
|
|
|
|
bAccept = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bAccept = FALSE;
|
|
|
|
}
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
2005-01-20 20:07:42 +00:00
|
|
|
WIN_ReleasePtr(pWnd);
|
2001-10-16 21:58:58 +00:00
|
|
|
|
|
|
|
if (!bAccept) return;
|
|
|
|
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XGetWindowProperty( event->display, DefaultRootWindow(event->display),
|
|
|
|
x11drv_atom(DndSelection), 0, 65535, FALSE,
|
|
|
|
AnyPropertyType, &u.atom_aux, (int *) &u.pt_aux.y,
|
|
|
|
&data_length, &aux_long, &p_data);
|
|
|
|
wine_tsx11_unlock();
|
2001-10-16 21:58:58 +00:00
|
|
|
|
|
|
|
if( !aux_long && p_data) /* don't bother if > 64K */
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
2001-10-16 21:58:58 +00:00
|
|
|
signed char *p = (signed char*) p_data;
|
|
|
|
char *p_drop;
|
1999-03-14 17:25:32 +00:00
|
|
|
|
2001-10-16 21:58:58 +00:00
|
|
|
aux_long = 0;
|
|
|
|
while( *p ) /* calculate buffer size */
|
|
|
|
{
|
|
|
|
p_drop = p;
|
|
|
|
if((u.i = *p) != -1 )
|
|
|
|
{
|
|
|
|
INT len = GetShortPathNameA( p, NULL, 0 );
|
|
|
|
if (len) aux_long += len + 1;
|
|
|
|
else *p = -1;
|
|
|
|
}
|
|
|
|
p += strlen(p) + 1;
|
|
|
|
}
|
|
|
|
if( aux_long && aux_long < 65535 )
|
|
|
|
{
|
|
|
|
HDROP hDrop;
|
|
|
|
DROPFILES *lpDrop;
|
|
|
|
|
|
|
|
aux_long += sizeof(DROPFILES) + 1;
|
|
|
|
hDrop = GlobalAlloc( GMEM_SHARE, aux_long );
|
|
|
|
lpDrop = (DROPFILES*)GlobalLock( hDrop );
|
|
|
|
|
|
|
|
if( lpDrop )
|
|
|
|
{
|
2005-01-20 20:07:42 +00:00
|
|
|
WND *pDropWnd = WIN_GetPtr( hScope );
|
2001-10-16 21:58:58 +00:00
|
|
|
lpDrop->pFiles = sizeof(DROPFILES);
|
|
|
|
lpDrop->pt.x = x;
|
|
|
|
lpDrop->pt.y = y;
|
|
|
|
lpDrop->fNC =
|
|
|
|
( 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->fWide = FALSE;
|
2005-01-20 20:07:42 +00:00
|
|
|
WIN_ReleasePtr(pDropWnd);
|
2001-10-16 21:58:58 +00:00
|
|
|
p_drop = (char *)(lpDrop + 1);
|
|
|
|
p = p_data;
|
|
|
|
while(*p)
|
|
|
|
{
|
|
|
|
if( *p != -1 ) /* use only "good" entries */
|
|
|
|
{
|
|
|
|
GetShortPathNameA( p, p_drop, 65535 );
|
|
|
|
p_drop += strlen( p_drop ) + 1;
|
|
|
|
}
|
|
|
|
p += strlen(p) + 1;
|
|
|
|
}
|
|
|
|
*p_drop = '\0';
|
|
|
|
PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
if( p_data ) XFree(p_data);
|
|
|
|
wine_tsx11_unlock();
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* EVENT_DropURLs
|
|
|
|
*
|
2002-05-31 23:06:46 +00:00
|
|
|
* drop items are separated by \n
|
1998-12-07 09:13:40 +00:00
|
|
|
* each item is prefixed by its mime type
|
|
|
|
*
|
|
|
|
* event->data.l[3], event->data.l[4] contains drop x,y position
|
|
|
|
*/
|
1999-04-15 15:22:23 +00:00
|
|
|
static void EVENT_DropURLs( HWND hWnd, XClientMessageEvent *event )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
|
|
|
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;
|
2000-09-25 23:56:41 +00:00
|
|
|
int x, y;
|
|
|
|
DROPFILES *lpDrop;
|
|
|
|
HDROP hDrop;
|
1998-12-07 09:13:40 +00:00
|
|
|
union {
|
|
|
|
Atom atom_aux;
|
|
|
|
int i;
|
|
|
|
Window w_aux;
|
|
|
|
} u; /* unused */
|
|
|
|
|
2001-10-16 21:58:58 +00:00
|
|
|
if (!(GetWindowLongW( hWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return;
|
1998-12-07 09:13:40 +00:00
|
|
|
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XGetWindowProperty( event->display, DefaultRootWindow(event->display),
|
|
|
|
x11drv_atom(DndSelection), 0, 65535, FALSE,
|
|
|
|
AnyPropertyType, &u.atom_aux, &u.i,
|
|
|
|
&data_length, &aux_long, &p_data);
|
|
|
|
wine_tsx11_unlock();
|
1998-12-07 09:13:40 +00:00
|
|
|
if (aux_long)
|
1999-12-08 03:56:23 +00:00
|
|
|
WARN("property too large, truncated!\n");
|
|
|
|
TRACE("urls=%s\n", p_data);
|
1998-12-07 09:13:40 +00:00
|
|
|
|
|
|
|
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 ) {
|
1999-02-26 11:11:13 +00:00
|
|
|
INT len = GetShortPathNameA( p+5, NULL, 0 );
|
1998-12-07 09:13:40 +00:00
|
|
|
if (len) drop_len += len + 1;
|
|
|
|
}
|
2002-05-31 23:06:46 +00:00
|
|
|
if (next) {
|
|
|
|
*next = '\n';
|
1998-12-07 09:13:40 +00:00
|
|
|
p = next + 1;
|
|
|
|
next = strchr(p, '\n');
|
|
|
|
} else {
|
|
|
|
p = NULL;
|
|
|
|
}
|
|
|
|
}
|
2002-05-31 23:06:46 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
if( drop_len && drop_len < 65535 ) {
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XQueryPointer( event->display, root_window, &u.w_aux, &u.w_aux,
|
|
|
|
&x, &y, &u.i, &u.i, &u.i);
|
|
|
|
wine_tsx11_unlock();
|
1999-04-15 15:22:23 +00:00
|
|
|
|
2000-09-25 23:56:41 +00:00
|
|
|
drop_len += sizeof(DROPFILES) + 1;
|
2001-01-02 21:00:46 +00:00
|
|
|
hDrop = GlobalAlloc( GMEM_SHARE, drop_len );
|
2000-09-25 23:56:41 +00:00
|
|
|
lpDrop = (DROPFILES *) GlobalLock( hDrop );
|
|
|
|
|
|
|
|
if( lpDrop ) {
|
2005-01-20 20:07:42 +00:00
|
|
|
WND *pDropWnd = WIN_GetPtr( hWnd );
|
2000-09-25 23:56:41 +00:00
|
|
|
lpDrop->pFiles = sizeof(DROPFILES);
|
|
|
|
lpDrop->pt.x = (INT)x;
|
|
|
|
lpDrop->pt.y = (INT)y;
|
|
|
|
lpDrop->fNC =
|
1998-12-07 09:13:40 +00:00
|
|
|
( 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) );
|
2000-09-25 23:56:41 +00:00
|
|
|
lpDrop->fWide = FALSE;
|
|
|
|
p_drop = (char*)(lpDrop + 1);
|
2005-01-20 20:07:42 +00:00
|
|
|
WIN_ReleasePtr(pDropWnd);
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
2000-09-25 23:56:41 +00:00
|
|
|
|
1998-12-07 09:13:40 +00:00
|
|
|
/* 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 ) {
|
1999-02-26 11:11:13 +00:00
|
|
|
INT len = GetShortPathNameA( p+5, p_drop, 65535 );
|
1998-12-07 09:13:40 +00:00
|
|
|
if (len) {
|
1999-12-08 03:56:23 +00:00
|
|
|
TRACE("drop file %s as %s\n", p+5, p_drop);
|
1998-12-07 09:13:40 +00:00
|
|
|
p_drop += len+1;
|
|
|
|
} else {
|
1999-12-08 03:56:23 +00:00
|
|
|
WARN("can't convert file %s to dos name \n", p+5);
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
} else {
|
1999-12-08 03:56:23 +00:00
|
|
|
WARN("unknown mime type %s\n", p);
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
2002-05-31 23:06:46 +00:00
|
|
|
if (next) {
|
|
|
|
*next = '\n';
|
1998-12-07 09:13:40 +00:00
|
|
|
p = next + 1;
|
|
|
|
next = strchr(p, '\n');
|
|
|
|
} else {
|
|
|
|
p = NULL;
|
|
|
|
}
|
|
|
|
*p_drop = '\0';
|
|
|
|
}
|
|
|
|
|
2000-09-25 23:56:41 +00:00
|
|
|
GlobalUnlock(hDrop);
|
2001-01-02 21:00:46 +00:00
|
|
|
PostMessageA( hWnd, WM_DROPFILES, (WPARAM)hDrop, 0L );
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
}
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
if( p_data ) XFree(p_data);
|
|
|
|
wine_tsx11_unlock();
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* EVENT_ClientMessage
|
|
|
|
*/
|
1999-04-15 15:22:23 +00:00
|
|
|
static void EVENT_ClientMessage( HWND hWnd, XClientMessageEvent *event )
|
1998-12-07 09:13:40 +00:00
|
|
|
{
|
|
|
|
if (event->message_type != None && event->format == 32) {
|
2003-11-20 04:24:18 +00:00
|
|
|
if (event->message_type == x11drv_atom(WM_PROTOCOLS))
|
2002-09-18 23:09:50 +00:00
|
|
|
handle_wm_protocols_message( hWnd, event );
|
2003-11-20 04:24:18 +00:00
|
|
|
else if (event->message_type == x11drv_atom(DndProtocol))
|
2001-06-04 21:55:17 +00:00
|
|
|
{
|
|
|
|
/* query window (drag&drop event contains only drag window) */
|
|
|
|
Window root, child;
|
|
|
|
int root_x, root_y, child_x, child_y;
|
|
|
|
unsigned int u;
|
2002-09-24 18:36:51 +00:00
|
|
|
|
|
|
|
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;
|
2001-06-04 21:55:17 +00:00
|
|
|
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);
|
1999-04-18 09:21:01 +00:00
|
|
|
}
|
2003-11-20 22:09:51 +00:00
|
|
|
else if (!X11DRV_XDND_Event(hWnd, event))
|
|
|
|
{
|
1998-12-07 09:13:40 +00:00
|
|
|
#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 */
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_lock();
|
|
|
|
XGetWindowProperty( event->display, DefaultRootWindow(event->display),
|
1998-12-07 09:13:40 +00:00
|
|
|
dndSelection, 0, 65535, FALSE,
|
|
|
|
AnyPropertyType, &u.atom, &u.i,
|
|
|
|
&u.l, &u.l, &p_data);
|
2003-11-21 21:48:36 +00:00
|
|
|
wine_tsx11_unlock();
|
1999-12-08 03:56:23 +00:00
|
|
|
TRACE("message_type=%ld, data=%ld,%ld,%ld,%ld,%ld, msg=%s\n",
|
2002-05-31 23:06:46 +00:00
|
|
|
event->message_type, event->data.l[0], event->data.l[1],
|
1998-12-07 09:13:40 +00:00
|
|
|
event->data.l[2], event->data.l[3], event->data.l[4],
|
|
|
|
p_data);
|
|
|
|
#endif
|
1999-12-08 03:56:23 +00:00
|
|
|
TRACE("unrecognized ClientMessage\n" );
|
1998-12-07 09:13:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-04-01 12:03:52 +00:00
|
|
|
|
1999-11-07 21:25:57 +00:00
|
|
|
/**********************************************************************
|
2000-04-14 14:09:50 +00:00
|
|
|
* X11DRV_EVENT_SetInputMethod
|
1999-11-07 21:25:57 +00:00
|
|
|
*/
|
2000-04-14 14:09:50 +00:00
|
|
|
INPUT_TYPE X11DRV_EVENT_SetInputMethod(INPUT_TYPE type)
|
1999-11-07 21:25:57 +00:00
|
|
|
{
|
|
|
|
INPUT_TYPE prev = current_input_type;
|
|
|
|
|
|
|
|
/* Flag not used yet */
|
|
|
|
in_transition = FALSE;
|
|
|
|
current_input_type = type;
|
|
|
|
|
|
|
|
return prev;
|
|
|
|
}
|
1999-04-01 12:03:52 +00:00
|
|
|
|
1999-12-12 19:42:47 +00:00
|
|
|
#ifdef HAVE_LIBXXF86DGA2
|
|
|
|
/**********************************************************************
|
|
|
|
* X11DRV_EVENT_SetDGAStatus
|
|
|
|
*/
|
|
|
|
void X11DRV_EVENT_SetDGAStatus(HWND hwnd, int event_base)
|
|
|
|
{
|
|
|
|
if (event_base < 0) {
|
|
|
|
DGAUsed = FALSE;
|
|
|
|
DGAhwnd = 0;
|
|
|
|
} else {
|
|
|
|
DGAUsed = TRUE;
|
|
|
|
DGAhwnd = hwnd;
|
|
|
|
DGAMotionEventType = event_base + MotionNotify;
|
|
|
|
DGAButtonPressEventType = event_base + ButtonPress;
|
|
|
|
DGAButtonReleaseEventType = event_base + ButtonRelease;
|
|
|
|
DGAKeyPressEventType = event_base + KeyPress;
|
|
|
|
DGAKeyReleaseEventType = event_base + KeyRelease;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|